blob: 2c59fa617bf2377fafe4bf7284902bdb39992759 [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);
anthony7bcfe7f2012-03-30 14:01:22 +0000191 if (IfMagickTrue(image->debug))
anthony805a2d42011-09-25 08:25:12 +0000192 (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) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000209 IfMagickTrue(image->matte))
anthony805a2d42011-09-25 08:25:12 +0000210 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 }
anthony31f1bf72012-01-30 12:37:22 +0000226 /* control points and color values */
anthony7bcfe7f2012-03-30 14:01:22 +0000227 error = IsMagickTrue( x % (2+number_colors) );
anthony31f1bf72012-01-30 12:37:22 +0000228 number_arguments=x;
anthony7bcfe7f2012-03-30 14:01:22 +0000229 if ( IfMagickTrue(error) ) {
anthony805a2d42011-09-25 08:25:12 +0000230 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000231 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000232 "Invalid number of Arguments");
233 return( (Image *)NULL);
234 }
235
236 /* Allocate and fill in the floating point arguments */
237 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
238 sizeof(*sparse_arguments));
239 if (sparse_arguments == (double *) NULL) {
240 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
241 "MemoryAllocationFailed","%s","SparseColorOption");
242 return( (Image *)NULL);
243 }
244 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
245 sizeof(*sparse_arguments));
246 p=arguments;
247 x=0;
248 while( *p != '\0' && x < number_arguments ) {
249 /* X coordinate */
250 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
251 if ( token[0] == '\0' ) break;
252 if ( isalpha((int) token[0]) || token[0] == '#' ) {
253 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000254 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000255 "Color found, instead of X-coord");
256 error = MagickTrue;
257 break;
258 }
cristydbdd0e32011-11-04 23:29:40 +0000259 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000260 /* Y coordinate */
261 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
262 if ( token[0] == '\0' ) break;
263 if ( isalpha((int) token[0]) || token[0] == '#' ) {
264 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000265 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000266 "Color found, instead of Y-coord");
267 error = MagickTrue;
268 break;
269 }
cristydbdd0e32011-11-04 23:29:40 +0000270 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000271 /* color name or function given in string argument */
272 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
273 if ( token[0] == '\0' ) break;
274 if ( isalpha((int) token[0]) || token[0] == '#' ) {
275 /* Color string given */
276 (void) QueryColorCompliance(token,AllCompliance,&color,
277 exception);
278 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
279 sparse_arguments[x++] = QuantumScale*color.red;
280 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
281 sparse_arguments[x++] = QuantumScale*color.green;
282 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
283 sparse_arguments[x++] = QuantumScale*color.blue;
284 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
285 (image->colorspace == CMYKColorspace))
286 sparse_arguments[x++] = QuantumScale*color.black;
287 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000288 IfMagickTrue(image->matte))
anthony31f1bf72012-01-30 12:37:22 +0000289 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000290 }
anthony31f1bf72012-01-30 12:37:22 +0000291 else {
292 /* Colors given as a set of floating point values - experimental */
293 /* NB: token contains the first floating point value to use! */
294 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
295 {
296 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
297 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
298 break;
299 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
300 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000301 }
anthony31f1bf72012-01-30 12:37:22 +0000302 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
303 {
304 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
305 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
306 break;
307 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
308 token[0] = ','; /* used this token - get another */
309 }
310 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
311 {
312 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
313 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
314 break;
315 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
316 token[0] = ','; /* used this token - get another */
317 }
318 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
319 (image->colorspace == CMYKColorspace))
320 {
321 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
322 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
323 break;
324 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
325 token[0] = ','; /* used this token - get another */
326 }
327 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
anthony7bcfe7f2012-03-30 14:01:22 +0000328 IfMagickTrue(image->matte))
anthony31f1bf72012-01-30 12:37:22 +0000329 {
330 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
331 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
332 break;
333 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
334 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000335 }
336 }
337 }
338 if ( number_arguments != x && !error ) {
339 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000340 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000341 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
342 return( (Image *)NULL);
343 }
344 if ( error )
345 return( (Image *)NULL);
346
anthony31f1bf72012-01-30 12:37:22 +0000347 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000348 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
349 exception);
350 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
351 return( sparse_image );
352}
353
354/*
355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
356% %
357% %
358% %
anthony43f425d2012-02-26 12:58:58 +0000359+ A c q u i r e W a n d C L I %
anthony805a2d42011-09-25 08:25:12 +0000360% %
361% %
362% %
363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
364%
anthony43f425d2012-02-26 12:58:58 +0000365% AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
366% Wand). The given image_info and exception is included as is if provided.
anthony805a2d42011-09-25 08:25:12 +0000367%
anthony43f425d2012-02-26 12:58:58 +0000368% Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
369% needed.
370%
371% The format of the NewMagickWand method is:
anthonyafa3dfc2012-03-03 11:31:30 +0000372%
anthony43f425d2012-02-26 12:58:58 +0000373% MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
374% ExceptionInfo *exception)
375%
376*/
377WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
378 ExceptionInfo *exception)
379{
380 MagickCLI
381 *cli_wand;
382
383 /* precaution - as per NewMagickWand() */
384 {
385 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
386 const char *quantum = GetMagickQuantumDepth(&depth);
387 if (depth != MAGICKCORE_QUANTUM_DEPTH)
388 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
389 }
390
391 /* allocate memory for MgaickCLI */
392 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
393 if (cli_wand == (MagickCLI *) NULL)
394 {
395 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
396 GetExceptionMessage(errno));
397 return((MagickCLI *)NULL);
398 }
399
400 /* Initialize Wand Part of MagickCLI
401 FUTURE: this is a repeat of code from NewMagickWand()
402 However some parts may be given fro man external source!
403 */
404 cli_wand->wand.id=AcquireWandId();
405 (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
406 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
407 cli_wand->wand.images=NewImageList();
408 if ( image_info == (ImageInfo *)NULL)
409 cli_wand->wand.image_info=AcquireImageInfo();
410 else
411 cli_wand->wand.image_info=image_info;
412 if ( exception == (ExceptionInfo *)NULL)
413 cli_wand->wand.exception=AcquireExceptionInfo();
414 else
415 cli_wand->wand.exception=exception;
416 cli_wand->wand.debug=IsEventLogging();
417 cli_wand->wand.signature=WandSignature;
418
419 /* Initialize CLI Part of MagickCLI */
420 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
421 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
422 cli_wand->image_list_stack=(Stack *)NULL;
423 cli_wand->image_info_stack=(Stack *)NULL;
anthony5330ae02012-03-20 14:17:01 +0000424 cli_wand->location="'%s'"; /* option location not known by default */
425 cli_wand->location2="'%s' '%s'";
anthony319dac62012-03-06 04:12:44 +0000426 cli_wand->filename=cli_wand->wand.name;
anthony1cdc5b72012-03-03 02:31:18 +0000427 cli_wand->line=0;
428 cli_wand->column=0;
anthony43f425d2012-02-26 12:58:58 +0000429 cli_wand->signature=WandSignature;
430
anthony7bcfe7f2012-03-30 14:01:22 +0000431 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +0000432 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
433 return(cli_wand);
434}
435
436/*
437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438% %
439% %
440% %
441+ D e s t r o y W a n d C L I %
442% %
443% %
444% %
445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446%
447% DestroyMagickCLI() destorys everything in a CLI wand, including image_info
448% and any exceptions, if still present in the wand.
449%
450% The format of the NewMagickWand method is:
anthonyafa3dfc2012-03-03 11:31:30 +0000451%
anthony43f425d2012-02-26 12:58:58 +0000452% MagickWand *DestroyMagickCLI()
453% Exception *exception)
454%
455*/
456WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
457{
458 Stack
459 *node;
460
461 assert(cli_wand != (MagickCLI *) NULL);
462 assert(cli_wand->signature == WandSignature);
463 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000464 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +0000465 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
466
467 /* Destroy CLI part of MagickCLI */
468 if (cli_wand->draw_info != (DrawInfo *) NULL )
469 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
470 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
471 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
472 while(cli_wand->image_list_stack != (Stack *)NULL)
473 {
474 node=cli_wand->image_list_stack;
475 cli_wand->image_list_stack=node->next;
476 (void) DestroyImageList((Image *)node->data);
477 (void) RelinquishMagickMemory(node);
478 }
479 while(cli_wand->image_info_stack != (Stack *)NULL)
480 {
481 node=cli_wand->image_info_stack;
482 cli_wand->image_info_stack=node->next;
483 (void) DestroyImageInfo((ImageInfo *)node->data);
484 (void) RelinquishMagickMemory(node);
485 }
486 cli_wand->signature=(~WandSignature);
487
488 /* Destroy Wand part MagickCLI */
489 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
490 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
491 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
492 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
493 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
494 RelinquishWandId(cli_wand->wand.id);
495 cli_wand->wand.signature=(~WandSignature);
496
497 return((MagickCLI *)NULL);
498}
499
500/*
501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
502% %
503% %
504% %
anthony2052d272012-02-28 12:48:29 +0000505+ C L I C a t c h E x c e p t i o n %
506% %
507% %
508% %
509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510%
511% CLICatchException() will report exceptions, either just non-fatal warnings
512% only, or all errors, according to 'all_execeptions' boolean argument.
513%
514% The function returns true is errors are fatal, in which case the caller
515% should abort and re-call with an 'all_exceptions' argument of true before
516% quitting.
517%
518% The cut-off level between fatal and non-fatal may be controlled by options
519% (FUTURE), but defaults to 'Error' exceptions.
520%
521% The format of the CLICatchException method is:
522%
523% MagickBooleanType CLICatchException(MagickCLI *cli_wand,
524% const MagickBooleanType all_exceptions );
525%
526*/
527WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
528 const MagickBooleanType all_exceptions )
529{
530 MagickBooleanType
531 status;
532 assert(cli_wand != (MagickCLI *) NULL);
533 assert(cli_wand->signature == WandSignature);
534 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000535 if (IfMagickTrue(cli_wand->wand.debug))
anthony2052d272012-02-28 12:48:29 +0000536 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
537
538 // FUTURE: '-regard_warning' should make this more sensitive.
539 // Note pipelined options may like more control over this level
540
anthony7bcfe7f2012-03-30 14:01:22 +0000541 status = IsMagickTrue(cli_wand->wand.exception->severity > ErrorException);
anthony2052d272012-02-28 12:48:29 +0000542
anthony7bcfe7f2012-03-30 14:01:22 +0000543 if ( IfMagickFalse(status) || IfMagickTrue(all_exceptions) )
anthony2052d272012-02-28 12:48:29 +0000544 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
545
546 return(status);
547}
548
549/*
550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551% %
552% %
553% %
anthony43f425d2012-02-26 12:58:58 +0000554+ C L I S e t t i n g O p t i o n I n f o %
555% %
556% %
557% %
558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559%
560% CLISettingOptionInfo() applies a single settings option into a CLI wand
561% holding the image_info, draw_info, quantize_info structures that will be
562% used when processing the images.
563%
564% These options do no require images to be present in the CLI wand for them
565% to be able to be set, in which case they will generally be applied to image
566% that are read in later
anthony80c37752012-01-16 01:03:11 +0000567%
568% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000569% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000570%
anthony2052d272012-02-28 12:48:29 +0000571% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000572%
anthonyafa3dfc2012-03-03 11:31:30 +0000573% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +0000574% const char *option, const char *arg1)
anthony805a2d42011-09-25 08:25:12 +0000575%
576% A description of each parameter follows:
577%
anthony43f425d2012-02-26 12:58:58 +0000578% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000579%
anthonydcf510d2011-10-30 13:51:40 +0000580% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000581%
anthony24aa8822012-03-11 00:56:06 +0000582% o arg1: The single argument used to set this option.
anthonydcf510d2011-10-30 13:51:40 +0000583%
anthony72feaa62012-01-17 06:46:23 +0000584% Example usage...
585%
anthonyafa3dfc2012-03-03 11:31:30 +0000586% CLISettingOptionInfo(cli_wand, "-background", "Red"); // set value
587% CLISettingOptionInfo(cli_wand, "-adjoin", NULL); // set boolean
588% CLISettingOptionInfo(cli_wand, "+adjoin", NULL); // unset
anthony72feaa62012-01-17 06:46:23 +0000589%
anthony24aa8822012-03-11 00:56:06 +0000590% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +0000591%
592% argc,argv
593% i=index in argv
594%
anthony2052d272012-02-28 12:48:29 +0000595% option_info = GetCommandOptionInfo(argv[i]);
596% count=option_info->type;
597% option_type=option_info->flags;
598%
599% if ( (option_type & SettingOperatorOptionFlags) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +0000600% CLISettingOptionInfo(cli_wand, argv[i],
601% (count>0) ? argv[i+1] : (char *)NULL);
anthonydcf510d2011-10-30 13:51:40 +0000602% i += count+1;
603%
anthony805a2d42011-09-25 08:25:12 +0000604*/
anthonyafa3dfc2012-03-03 11:31:30 +0000605WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +0000606 const char *option,const char *arg1)
anthony805a2d42011-09-25 08:25:12 +0000607{
anthony30b912a2012-03-22 01:20:28 +0000608 ssize_t
609 parse; /* option argument parsing (string to value table lookup) */
610
anthony43f425d2012-02-26 12:58:58 +0000611 assert(cli_wand != (MagickCLI *) NULL);
612 assert(cli_wand->signature == WandSignature);
613 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +0000614 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +0000615 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony1afdc7a2011-10-05 11:54:28 +0000616
anthony2e4501b2012-03-30 04:41:54 +0000617#define _image_info (cli_wand->wand.image_info)
618#define _exception (cli_wand->wand.exception)
619#define _draw_info (cli_wand->draw_info)
620#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000621#define IfSetOption (*option=='-')
anthony7bcfe7f2012-03-30 14:01:22 +0000622#define ArgBoolean IsMagickTrue(IfSetOption)
623#define ArgBooleanNot IsMagickFalse(IfSetOption)
anthony24aa8822012-03-11 00:56:06 +0000624#define ArgBooleanString (IfSetOption?"true":"false")
625#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000626
anthonyafa3dfc2012-03-03 11:31:30 +0000627 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000628 {
629 case 'a':
630 {
anthonyafa3dfc2012-03-03 11:31:30 +0000631 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000632 {
anthony92c93bd2012-03-19 14:02:47 +0000633 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000634 break;
635 }
anthonyafa3dfc2012-03-03 11:31:30 +0000636 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000637 {
anthony92c93bd2012-03-19 14:02:47 +0000638 /* DEPRECIATED: _draw_info setting only: for -draw and -transform */
anthony74b1cfc2011-10-06 12:44:16 +0000639 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000640 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000641 else
anthony92c93bd2012-03-19 14:02:47 +0000642 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000643 break;
644 }
anthonyafa3dfc2012-03-03 11:31:30 +0000645 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000646 {
anthony92c93bd2012-03-19 14:02:47 +0000647 _image_info->antialias =
648 _draw_info->stroke_antialias =
649 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000650 break;
651 }
anthony31f1bf72012-01-30 12:37:22 +0000652 if (LocaleCompare("attenuate",option+1) == 0)
653 {
anthony7bcfe7f2012-03-30 14:01:22 +0000654 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +0000655 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
656 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000657 break;
658 }
anthonyafa3dfc2012-03-03 11:31:30 +0000659 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000660 {
anthony92c93bd2012-03-19 14:02:47 +0000661 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000662 break;
663 }
anthonyebb73a22012-03-22 14:25:52 +0000664 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000665 }
666 case 'b':
667 {
anthonyafa3dfc2012-03-03 11:31:30 +0000668 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000669 {
anthony92c93bd2012-03-19 14:02:47 +0000670 /* FUTURE: both _image_info attribute & ImageOption in use!
671 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000672 SyncImageSettings() used to set per-image attribute.
673
anthony92c93bd2012-03-19 14:02:47 +0000674 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000675 we should fall back to per-image background_color
676
677 At this time -background will 'wipe out' the per-image
678 background color!
679
680 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000681 */
anthony92c93bd2012-03-19 14:02:47 +0000682 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000683 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000684 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000685 break;
686 }
anthonyafa3dfc2012-03-03 11:31:30 +0000687 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000688 {
anthony52bef752012-03-27 13:54:47 +0000689 /* FUTURE: bias OBSOLETED, replaced by Artifact "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000690 as it is actually rarely used except in direct convolve operations
691 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000692
693 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000694 */
anthony7bcfe7f2012-03-30 14:01:22 +0000695 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000696 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000697 (void) SetImageOption(_image_info,"convolve:bias",ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000698 break;
699 }
anthonyafa3dfc2012-03-03 11:31:30 +0000700 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000701 {
anthony72feaa62012-01-17 06:46:23 +0000702 /* Used as a image chromaticity setting
703 SyncImageSettings() used to set per-image attribute.
704 */
anthony92c93bd2012-03-19 14:02:47 +0000705 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000706 break;
707 }
anthonyafa3dfc2012-03-03 11:31:30 +0000708 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000709 {
anthonyafbaed72011-10-26 12:05:04 +0000710 /* Image chromaticity X,Y NB: Y=X if Y not defined
711 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000712 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000713 */
anthonyf42014d2012-03-25 09:53:06 +0000714 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +0000715 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000716 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +0000717 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000718 break;
719 }
anthonyafa3dfc2012-03-03 11:31:30 +0000720 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000721 {
anthony92c93bd2012-03-19 14:02:47 +0000722 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000723 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000724 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000725 */
anthony74b1cfc2011-10-06 12:44:16 +0000726 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000727 {
anthony92c93bd2012-03-19 14:02:47 +0000728 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000729 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000730 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000731 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000732 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000733 break;
734 }
anthony92c93bd2012-03-19 14:02:47 +0000735 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000736 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000737 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000738 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000739 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000740 break;
741 }
anthonyafa3dfc2012-03-03 11:31:30 +0000742 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000743 {
anthonyfd706f92012-01-19 04:22:02 +0000744 /* DEPRECIATED - now "undercolor" */
anthony24aa8822012-03-11 00:56:06 +0000745 CLISettingOptionInfo(cli_wand,"undercolor",arg1);
anthonyfd706f92012-01-19 04:22:02 +0000746 break;
anthony805a2d42011-09-25 08:25:12 +0000747 }
anthonyebb73a22012-03-22 14:25:52 +0000748 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000749 }
750 case 'c':
751 {
anthonyafa3dfc2012-03-03 11:31:30 +0000752 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000753 {
754 MagickSizeType
755 limit;
756
anthony7bcfe7f2012-03-30 14:01:22 +0000757 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +0000758 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000759 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000760 if (LocaleCompare("unlimited",arg1) != 0)
761 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000762 (void) SetMagickResourceLimit(MemoryResource,limit);
763 (void) SetMagickResourceLimit(MapResource,2*limit);
764 break;
765 }
anthonyafa3dfc2012-03-03 11:31:30 +0000766 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000767 {
anthony92c93bd2012-03-19 14:02:47 +0000768 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000769 break;
770 }
anthonyafa3dfc2012-03-03 11:31:30 +0000771 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000772 {
anthony30b912a2012-03-22 01:20:28 +0000773 arg1=ArgOption("default");
774 parse=ParseChannelOption(arg1);
775 if (parse < 0)
776 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
777 option,arg1);
778 _image_info->channel=(ChannelType) parse;
779 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000780 break;
781 }
anthonyafa3dfc2012-03-03 11:31:30 +0000782 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000783 {
anthonyafbaed72011-10-26 12:05:04 +0000784 /* Setting used for new images via AquireImage()
785 But also used as a SimpleImageOperator
786 Undefined colorspace means don't modify images on
787 read or as a operation */
anthony30b912a2012-03-22 01:20:28 +0000788 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
789 ArgOption("undefined"));
790 if (parse < 0)
anthony5330ae02012-03-20 14:17:01 +0000791 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
792 option,arg1);
anthony30b912a2012-03-22 01:20:28 +0000793 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000794 break;
795 }
anthonyafa3dfc2012-03-03 11:31:30 +0000796 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000797 {
anthony92c93bd2012-03-19 14:02:47 +0000798 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000799 break;
800 }
anthonyafa3dfc2012-03-03 11:31:30 +0000801 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000802 {
anthony92c93bd2012-03-19 14:02:47 +0000803 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000804 SyncImageSettings() used to set per-image attribute. - REMOVE
805
anthonyafbaed72011-10-26 12:05:04 +0000806 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000807 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000808 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000809 */
anthonyebb73a22012-03-22 14:25:52 +0000810 parse = ParseCommandOption(MagickComposeOptions,MagickFalse,
811 ArgOption("undefined"));
812 if (parse < 0)
813 CLIWandExceptArgBreak(OptionError,"UnrecognizedComposeOperator",
814 option,arg1);
815 _image_info->compose=(CompositeOperator) parse;
anthony92c93bd2012-03-19 14:02:47 +0000816 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000817 break;
818 }
anthonyafa3dfc2012-03-03 11:31:30 +0000819 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000820 {
anthony92c93bd2012-03-19 14:02:47 +0000821 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000822 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000823 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000824
anthony92c93bd2012-03-19 14:02:47 +0000825 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000826 however the image attribute (for save) is set from the
827 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000828
829 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000830 */
anthonyebb73a22012-03-22 14:25:52 +0000831 parse = ParseCommandOption(MagickCompressOptions,MagickFalse,
832 ArgOption("undefined"));
833 if (parse < 0)
834 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageCompression",
835 option,arg1);
836 _image_info->compression=(CompressionType) parse;
anthony92c93bd2012-03-19 14:02:47 +0000837 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000838 break;
839 }
anthonyebb73a22012-03-22 14:25:52 +0000840 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000841 }
842 case 'd':
843 {
anthonyafa3dfc2012-03-03 11:31:30 +0000844 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000845 {
anthony72feaa62012-01-17 06:46:23 +0000846 /* SyncImageSettings() used to set per-image attribute. */
anthonyebb73a22012-03-22 14:25:52 +0000847 arg1=ArgOption("none");
848 parse = ParseCommandOption(MagickLogEventOptions,MagickFalse,arg1);
849 if (parse < 0)
850 CLIWandExceptArgBreak(OptionError,"UnrecognizedEventType",
851 option,arg1);
852 (void) SetLogEventMask(arg1);
853 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000854 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000855 break;
856 }
anthonyafa3dfc2012-03-03 11:31:30 +0000857 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000858 {
anthony24aa8822012-03-11 00:56:06 +0000859 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000860 {
anthony5f867ae2011-10-09 10:28:34 +0000861 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000862 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000863 else
anthony24aa8822012-03-11 00:56:06 +0000864 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000865 break;
866 }
anthony24aa8822012-03-11 00:56:06 +0000867 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000868 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000869 (void) DefineImageOption(_image_info,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +0000870 else if (IsMagickFalse(DeleteImageOption(_image_info,arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000871 CLIWandExceptArgBreak(OptionError,"NoSuchOption",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000872 break;
873 }
anthonyafa3dfc2012-03-03 11:31:30 +0000874 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000875 {
anthonyafbaed72011-10-26 12:05:04 +0000876 /* Only used for new images via AcquireImage()
877 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000878 */
anthonyebb73a22012-03-22 14:25:52 +0000879 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +0000880 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000881 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
882 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000883 break;
884 }
anthonyafa3dfc2012-03-03 11:31:30 +0000885 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000886 {
anthony92c93bd2012-03-19 14:02:47 +0000887 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000888 Basically as density can be in a XxY form!
889
890 SyncImageSettings() used to set per-image attribute.
891 */
anthony7bcfe7f2012-03-30 14:01:22 +0000892 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000893 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000894 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
895 (void) CloneString(&_image_info->density,ArgOption(NULL));
896 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000897 break;
898 }
anthonyafa3dfc2012-03-03 11:31:30 +0000899 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000900 {
anthony72feaa62012-01-17 06:46:23 +0000901 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
902 SyncImageSettings() used to set per-image attribute.
903 */
anthony7bcfe7f2012-03-30 14:01:22 +0000904 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +0000905 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000906 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000907 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000908 break;
909 }
anthonyafa3dfc2012-03-03 11:31:30 +0000910 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000911 {
anthony92c93bd2012-03-19 14:02:47 +0000912 /* Image Option is only used to set _draw_info */
anthonyebb73a22012-03-22 14:25:52 +0000913 arg1=ArgOption("undefined");
914 parse = ParseCommandOption(MagickDirectionOptions,MagickFalse,arg1);
915 if (parse < 0)
916 CLIWandExceptArgBreak(OptionError,"UnrecognizedDirectionType",
917 option,arg1);
918 _draw_info->direction=(DirectionType) parse;
919 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000920 break;
921 }
anthonyafa3dfc2012-03-03 11:31:30 +0000922 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000923 {
anthony92c93bd2012-03-19 14:02:47 +0000924 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
925 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000926 break;
927 }
anthonyafa3dfc2012-03-03 11:31:30 +0000928 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000929 {
anthony72feaa62012-01-17 06:46:23 +0000930 /* only used in setting new images */
anthonyebb73a22012-03-22 14:25:52 +0000931 arg1=ArgOption("undefined");
932 parse = ParseCommandOption(MagickDisposeOptions,MagickFalse,arg1);
933 if (parse < 0)
934 CLIWandExceptArgBreak(OptionError,"UnrecognizedDisposeMethod",
935 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000936 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000937 break;
938 }
anthonyafa3dfc2012-03-03 11:31:30 +0000939 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000940 {
anthony92c93bd2012-03-19 14:02:47 +0000941 /* _image_info attr (on/off), _quantize_info attr (on/off)
942 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000943 FUTURE: merge the duality of the dithering options
944 */
anthony92c93bd2012-03-19 14:02:47 +0000945 _image_info->dither = _quantize_info->dither = ArgBoolean;
946 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
947 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000948 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000949 if (_quantize_info->dither_method == NoDitherMethod)
950 _image_info->dither = _quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000951 break;
952 }
anthonyebb73a22012-03-22 14:25:52 +0000953 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000954 }
955 case 'e':
956 {
anthonyafa3dfc2012-03-03 11:31:30 +0000957 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000958 {
anthony92c93bd2012-03-19 14:02:47 +0000959 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
960 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000961 break;
962 }
anthonyafa3dfc2012-03-03 11:31:30 +0000963 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000964 {
anthony92c93bd2012-03-19 14:02:47 +0000965 /* Both _image_info attr and ImageInfo */
anthony2a0ec8c2012-03-24 04:35:56 +0000966 arg1 = ArgOption("undefined");
967 parse = ParseCommandOption(MagickEndianOptions,MagickFalse,arg1);
968 if (parse < 0)
969 CLIWandExceptArgBreak(OptionError,"UnrecognizedEndianType",
970 option,arg1);
anthonyf46d4262012-03-26 03:30:34 +0000971 /* FUTURE: check alloc/free of endian string! - remove? */
cristyaa2c16c2012-03-25 22:21:35 +0000972 _image_info->endian=(EndianType) (*arg1);
anthony2a0ec8c2012-03-24 04:35:56 +0000973 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000974 break;
975 }
anthonyafa3dfc2012-03-03 11:31:30 +0000976 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000977 {
anthony92c93bd2012-03-19 14:02:47 +0000978 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000979 break;
980 }
anthonyebb73a22012-03-22 14:25:52 +0000981 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +0000982 }
983 case 'f':
984 {
anthonyafa3dfc2012-03-03 11:31:30 +0000985 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000986 {
anthony92c93bd2012-03-19 14:02:47 +0000987 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000988 break;
989 }
anthonyafa3dfc2012-03-03 11:31:30 +0000990 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000991 {
anthony92c93bd2012-03-19 14:02:47 +0000992 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000993 The original fill color is preserved if a fill-pattern is given.
994 That way it does not effect other operations that directly using
995 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000996 */
anthony72feaa62012-01-17 06:46:23 +0000997 MagickBooleanType
998 status;
anthony6dc09cd2011-10-12 08:56:49 +0000999
1000 ExceptionInfo
1001 *sans;
1002
anthonyfd706f92012-01-19 04:22:02 +00001003 PixelInfo
1004 color;
1005
anthony2a0ec8c2012-03-24 04:35:56 +00001006 arg1 = ArgOption("none"); /* +fill turns it off! */
1007 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001008 if (_draw_info->fill_pattern != (Image *) NULL)
1009 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +00001010
1011 /* is it a color or a image? -- ignore exceptions */
1012 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001013 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +00001014 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001015
anthony7bcfe7f2012-03-30 14:01:22 +00001016 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001017 _draw_info->fill_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001018 else
anthony92c93bd2012-03-19 14:02:47 +00001019 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +00001020 break;
1021 }
anthonyafa3dfc2012-03-03 11:31:30 +00001022 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001023 {
anthony72feaa62012-01-17 06:46:23 +00001024 /* SyncImageSettings() used to set per-image attribute. */
anthony2a0ec8c2012-03-24 04:35:56 +00001025 arg1 = ArgOption("undefined");
1026 parse = ParseCommandOption(MagickFilterOptions,MagickFalse,arg1);
1027 if (parse < 0)
1028 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageFilter",
1029 option,arg1);
1030 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001031 break;
1032 }
anthonyafa3dfc2012-03-03 11:31:30 +00001033 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001034 {
anthony92c93bd2012-03-19 14:02:47 +00001035 (void) CloneString(&_draw_info->font,ArgOption(NULL));
1036 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +00001037 break;
1038 }
anthonyafa3dfc2012-03-03 11:31:30 +00001039 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001040 {
anthonydcf510d2011-10-30 13:51:40 +00001041 /* FUTURE: why the ping test, you could set ping after this! */
1042 /*
anthony805a2d42011-09-25 08:25:12 +00001043 register const char
1044 *q;
1045
anthony24aa8822012-03-11 00:56:06 +00001046 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +00001047 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00001048 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +00001049 */
anthony92c93bd2012-03-19 14:02:47 +00001050 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001051 break;
1052 }
anthonyafa3dfc2012-03-03 11:31:30 +00001053 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001054 {
anthony72feaa62012-01-17 06:46:23 +00001055 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +00001056 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +00001057 SyncImageSettings() used to set per-image attribute.
1058
anthony2a0ec8c2012-03-24 04:35:56 +00001059 FUTURE: Can't find anything else using _image_info->fuzz directly!
1060 remove direct sttribute from image_info
anthony6613bf32011-10-15 07:24:44 +00001061 */
anthony2a0ec8c2012-03-24 04:35:56 +00001062 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001063 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00001064 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1065 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +00001066 QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00001067 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001068 break;
1069 }
anthonyebb73a22012-03-22 14:25:52 +00001070 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001071 }
1072 case 'g':
1073 {
anthonyafa3dfc2012-03-03 11:31:30 +00001074 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001075 {
anthony72feaa62012-01-17 06:46:23 +00001076 /* SyncImageSettings() used to set per-image attribute. */
anthonyfe1aa782012-03-24 13:43:04 +00001077 arg1 = ArgOption("none");
1078 parse = ParseCommandOption(MagickGravityOptions,MagickFalse,arg1);
1079 if (parse < 0)
1080 CLIWandExceptArgBreak(OptionError,"UnrecognizedGravityType",
1081 option,arg1);
anthonyfe1aa782012-03-24 13:43:04 +00001082 _draw_info->gravity=(GravityType) parse;
anthonye8490972012-04-03 13:16:01 +00001083 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001084 break;
1085 }
anthonyafa3dfc2012-03-03 11:31:30 +00001086 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001087 {
anthonydcf510d2011-10-30 13:51:40 +00001088 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +00001089 SyncImageSettings() used to set per-image attribute.
1090 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +00001091 */
anthonyf42014d2012-03-25 09:53:06 +00001092 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001093 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001094 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001095 (void) SetImageOption(_image_info,option+1,arg1);
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 {
anthony7bcfe7f2012-03-30 14:01:22 +00001132 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001133 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 {
anthony7bcfe7f2012-03-30 14:01:22 +00001152 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001153 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 {
anthony7bcfe7f2012-03-30 14:01:22 +00001164 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001165 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");
anthony7bcfe7f2012-03-30 14:01:22 +00001193 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001194 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1195 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001196 break;
1197 }
anthonyebb73a22012-03-22 14:25:52 +00001198 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001199 }
1200 case 'm':
1201 {
anthonyafa3dfc2012-03-03 11:31:30 +00001202 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001203 {
anthony72feaa62012-01-17 06:46:23 +00001204 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001205 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001206 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001207 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001208 break;
1209 }
anthonyafa3dfc2012-03-03 11:31:30 +00001210 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001211 {
anthony92c93bd2012-03-19 14:02:47 +00001212 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001213 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001214 break;
1215 }
anthonyafa3dfc2012-03-03 11:31:30 +00001216 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001217 {
anthony24aa8822012-03-11 00:56:06 +00001218 /* Setting (used by some input coders!) -- why?
1219 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001220 */
anthony92c93bd2012-03-19 14:02:47 +00001221 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001222 break;
1223 }
anthonyebb73a22012-03-22 14:25:52 +00001224 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001225 }
1226 case 'o':
1227 {
anthonyafa3dfc2012-03-03 11:31:30 +00001228 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001229 {
anthony72feaa62012-01-17 06:46:23 +00001230 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001231 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001232 FUTURE: make set meta-data operator instead.
1233 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001234 */
anthony7bc87992012-03-25 02:32:51 +00001235 parse=ParseCommandOption(MagickOrientationOptions,MagickFalse,
1236 ArgOption("undefined"));
1237 if (parse < 0)
1238 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageOrientation",
1239 option,arg1);
1240 _image_info->orientation=(OrientationType)parse;
anthony92c93bd2012-03-19 14:02:47 +00001241 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001242 break;
1243 }
anthonyebb73a22012-03-22 14:25:52 +00001244 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001245 }
1246 case 'p':
1247 {
anthonyafa3dfc2012-03-03 11:31:30 +00001248 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001249 {
anthony7bc87992012-03-25 02:32:51 +00001250 /* Only used for new images and image generators.
anthony72feaa62012-01-17 06:46:23 +00001251 SyncImageSettings() used to set per-image attribute. ?????
1252 That last is WRONG!!!!
anthony7bc87992012-03-25 02:32:51 +00001253 FUTURE: adjust named 'page' sizes according density
anthony72feaa62012-01-17 06:46:23 +00001254 */
anthony805a2d42011-09-25 08:25:12 +00001255 char
1256 *canonical_page,
1257 page[MaxTextExtent];
1258
1259 const char
1260 *image_option;
1261
1262 MagickStatusType
1263 flags;
1264
1265 RectangleInfo
1266 geometry;
1267
anthonydcf510d2011-10-30 13:51:40 +00001268 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001269 {
anthony92c93bd2012-03-19 14:02:47 +00001270 (void) DeleteImageOption(_image_info,option+1);
1271 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001272 break;
1273 }
1274 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001275 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001276 if (image_option != (const char *) NULL)
1277 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001278 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001279 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1280 canonical_page=DestroyString(canonical_page);
1281 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1282 (unsigned long) geometry.width,(unsigned long) geometry.height);
1283 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1284 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1285 (unsigned long) geometry.width,(unsigned long) geometry.height,
1286 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001287 (void) SetImageOption(_image_info,option+1,page);
1288 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001289 break;
1290 }
anthonyafa3dfc2012-03-03 11:31:30 +00001291 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001292 {
anthony92c93bd2012-03-19 14:02:47 +00001293 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001294 break;
1295 }
anthonyafa3dfc2012-03-03 11:31:30 +00001296 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001297 {
anthonyf42014d2012-03-25 09:53:06 +00001298 if (IfSetOption) {
anthony7bcfe7f2012-03-30 14:01:22 +00001299 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001300 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1301 _image_info->pointsize =
1302 _draw_info->pointsize =
1303 StringToDouble(arg1,(char **) NULL);
1304 }
1305 else {
1306 _image_info->pointsize=0.0; /* unset pointsize */
1307 _draw_info->pointsize=12.0;
1308 }
anthony805a2d42011-09-25 08:25:12 +00001309 break;
1310 }
anthonyafa3dfc2012-03-03 11:31:30 +00001311 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001312 {
anthonyf42014d2012-03-25 09:53:06 +00001313 arg1=ArgOption("-1");
anthony7bcfe7f2012-03-30 14:01:22 +00001314 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001315 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1316 (void) SetMagickPrecision(StringToInteger(arg1));
anthony805a2d42011-09-25 08:25:12 +00001317 break;
1318 }
anthonydcf510d2011-10-30 13:51:40 +00001319 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001320 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001321 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001322 {
anthony92c93bd2012-03-19 14:02:47 +00001323 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001324 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001325 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001326 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001327 break;
1328 }
anthonydcf510d2011-10-30 13:51:40 +00001329 */
anthonyebb73a22012-03-22 14:25:52 +00001330 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001331 }
1332 case 'q':
1333 {
anthonyafa3dfc2012-03-03 11:31:30 +00001334 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001335 {
anthony7bcfe7f2012-03-30 14:01:22 +00001336 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00001337 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001338 _image_info->quality= IfSetOption ? StringToUnsignedLong(arg1)
1339 : UNDEFINED_COMPRESSION_QUALITY;
anthony92c93bd2012-03-19 14:02:47 +00001340 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001341 break;
1342 }
anthonyafa3dfc2012-03-03 11:31:30 +00001343 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001344 {
anthony92c93bd2012-03-19 14:02:47 +00001345 /* Just a set direct in _quantize_info */
anthony7bc87992012-03-25 02:32:51 +00001346 arg1=ArgOption("undefined");
1347 parse=ParseCommandOption(MagickColorspaceOptions,MagickFalse,arg1);
1348 if (parse < 0)
1349 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
1350 option,arg1);
1351 _quantize_info->colorspace=(ColorspaceType)parse;
anthonyafbaed72011-10-26 12:05:04 +00001352 break;
1353 }
anthonyafa3dfc2012-03-03 11:31:30 +00001354 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001355 {
anthonyf42014d2012-03-25 09:53:06 +00001356 /* FUTURE: if two -quiet is performed you can not do +quiet!
1357 This needs to be checked over thoughly.
1358 */
anthony805a2d42011-09-25 08:25:12 +00001359 static WarningHandler
1360 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001361
anthonyafbaed72011-10-26 12:05:04 +00001362 WarningHandler
1363 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001364
anthonyafbaed72011-10-26 12:05:04 +00001365 if ( tmp != (WarningHandler) NULL)
1366 warning_handler = tmp; /* remember the old handler */
1367 if (!IfSetOption) /* set the old handler */
1368 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001369 break;
1370 }
anthonyebb73a22012-03-22 14:25:52 +00001371 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001372 }
1373 case 'r':
1374 {
anthonyafa3dfc2012-03-03 11:31:30 +00001375 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001376 {
anthonydcf510d2011-10-30 13:51:40 +00001377 /* Image chromaticity X,Y NB: Y=X if Y not defined
1378 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001379 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001380 */
anthonyf42014d2012-03-25 09:53:06 +00001381 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001382 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00001383 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf42014d2012-03-25 09:53:06 +00001384 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001385 break;
1386 }
anthonyafa3dfc2012-03-03 11:31:30 +00001387 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001388 {
anthony92c93bd2012-03-19 14:02:47 +00001389 /* _draw_info only setting */
1390 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001391 break;
1392 }
anthonyebb73a22012-03-22 14:25:52 +00001393 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001394 }
1395 case 's':
1396 {
anthonyafa3dfc2012-03-03 11:31:30 +00001397 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001398 {
anthonyafbaed72011-10-26 12:05:04 +00001399 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001400 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001401 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001402 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001403 break;
1404 }
anthonyafa3dfc2012-03-03 11:31:30 +00001405 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001406 {
anthonyf42014d2012-03-25 09:53:06 +00001407 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001408 What ??? Why ????
1409 */
anthony7bcfe7f2012-03-30 14:01:22 +00001410 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001411 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001412 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1413 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001414 break;
1415 }
anthonyafa3dfc2012-03-03 11:31:30 +00001416 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001417 {
anthony7bcfe7f2012-03-30 14:01:22 +00001418 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001419 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafbaed72011-10-26 12:05:04 +00001420 SeedPseudoRandomGenerator(
anthony24aa8822012-03-11 00:56:06 +00001421 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001422 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001423 break;
1424 }
anthonyafa3dfc2012-03-03 11:31:30 +00001425 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001426 {
anthony92c93bd2012-03-19 14:02:47 +00001427 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001428 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001429 */
anthony92c93bd2012-03-19 14:02:47 +00001430 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001431 break;
1432 }
anthonyafa3dfc2012-03-03 11:31:30 +00001433 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001434 {
anthonyf42014d2012-03-25 09:53:06 +00001435 arg1=ArgOption("undefined");
1436 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1437 if (parse < 0)
1438 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1439 option,arg1);
1440 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001441 break;
1442 }
anthonyafa3dfc2012-03-03 11:31:30 +00001443 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001444 {
anthonyafbaed72011-10-26 12:05:04 +00001445 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001446 UPDATE: ensure stroke color is not destroyed is a pattern
1447 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001448 */
anthony72feaa62012-01-17 06:46:23 +00001449 MagickBooleanType
1450 status;
anthonyafbaed72011-10-26 12:05:04 +00001451
1452 ExceptionInfo
1453 *sans;
1454
anthonyfd706f92012-01-19 04:22:02 +00001455 PixelInfo
1456 color;
1457
anthony2a0ec8c2012-03-24 04:35:56 +00001458 arg1 = ArgOption("none"); /* +fill turns it off! */
1459 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001460 if (_draw_info->stroke_pattern != (Image *) NULL)
1461 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001462
1463 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001464 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001465 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001466 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001467
anthony7bcfe7f2012-03-30 14:01:22 +00001468 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001469 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001470 else
anthony92c93bd2012-03-19 14:02:47 +00001471 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001472 break;
1473 }
anthonyafa3dfc2012-03-03 11:31:30 +00001474 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001475 {
anthony7bcfe7f2012-03-30 14:01:22 +00001476 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001477 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001478 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1479 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001480 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001481 break;
1482 }
anthonyafa3dfc2012-03-03 11:31:30 +00001483 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001484 {
anthonyf42014d2012-03-25 09:53:06 +00001485 arg1=ArgOption("undefined");
1486 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1487 if (parse < 0)
1488 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1489 option,arg1);
1490 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001491 break;
1492 }
anthonyafa3dfc2012-03-03 11:31:30 +00001493 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001494 {
anthonyf42014d2012-03-25 09:53:06 +00001495 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001496 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001497 break;
1498 }
anthonyebb73a22012-03-22 14:25:52 +00001499 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001500 }
1501 case 't':
1502 {
anthonyafa3dfc2012-03-03 11:31:30 +00001503 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001504 {
anthony72feaa62012-01-17 06:46:23 +00001505 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001506 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001507 break;
1508 }
anthonyafa3dfc2012-03-03 11:31:30 +00001509 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001510 {
anthony52bef752012-03-27 13:54:47 +00001511 /* FUTURE: move _image_info string to option splay-tree
1512 Other than "montage" what uses "texture" ????
1513 */
anthony92c93bd2012-03-19 14:02:47 +00001514 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001515 break;
1516 }
anthonyafa3dfc2012-03-03 11:31:30 +00001517 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001518 {
anthony92c93bd2012-03-19 14:02:47 +00001519 _draw_info->fill_pattern=IfSetOption
1520 ?GetImageCache(_image_info,arg1,_exception)
1521 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001522 break;
1523 }
anthonyafa3dfc2012-03-03 11:31:30 +00001524 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001525 {
anthony72feaa62012-01-17 06:46:23 +00001526 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001527 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001528 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001529 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1530 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001531 break;
1532 }
anthonyafa3dfc2012-03-03 11:31:30 +00001533 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001534 {
anthony92c93bd2012-03-19 14:02:47 +00001535 /* FUTURE: both _image_info attribute & ImageOption in use!
1536 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001537 SyncImageSettings() used to set per-image attribute.
1538
anthonyafbaed72011-10-26 12:05:04 +00001539 Note that +transparent-color, means fall-back to image
1540 attribute so ImageOption is deleted, not set to a default.
1541 */
anthony7bcfe7f2012-03-30 14:01:22 +00001542 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001543 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001544 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001545 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001546 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001547 break;
1548 }
anthonyafa3dfc2012-03-03 11:31:30 +00001549 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001550 {
anthony92c93bd2012-03-19 14:02:47 +00001551 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1552 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001553 break;
1554 }
anthonyafa3dfc2012-03-03 11:31:30 +00001555 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001556 {
anthony72feaa62012-01-17 06:46:23 +00001557 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001558 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1559 ArgOption("undefined"));
1560 if (parse < 0)
1561 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1562 option,arg1);
1563 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001564 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001565 break;
1566 }
anthonyebb73a22012-03-22 14:25:52 +00001567 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001568 }
1569 case 'u':
1570 {
anthonyafa3dfc2012-03-03 11:31:30 +00001571 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001572 {
anthony92c93bd2012-03-19 14:02:47 +00001573 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001574 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001575 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001576 break;
1577 }
anthonyafa3dfc2012-03-03 11:31:30 +00001578 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001579 {
anthony72feaa62012-01-17 06:46:23 +00001580 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001581 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001582 FUTURE: this probably should be part of the density setting
1583 */
anthony52bef752012-03-27 13:54:47 +00001584 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1585 ArgOption("undefined"));
1586 if (parse < 0)
1587 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1588 option,arg1);
1589 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001590 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001591 break;
1592 }
anthonyebb73a22012-03-22 14:25:52 +00001593 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001594 }
1595 case 'v':
1596 {
anthonyafa3dfc2012-03-03 11:31:30 +00001597 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001598 {
anthony24aa8822012-03-11 00:56:06 +00001599 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001600 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001601 */
anthony92c93bd2012-03-19 14:02:47 +00001602 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1603 _image_info->verbose= ArgBoolean;
1604 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001605 break;
1606 }
anthonyafa3dfc2012-03-03 11:31:30 +00001607 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001608 {
anthony92c93bd2012-03-19 14:02:47 +00001609 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001610 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001611 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001612 */
anthony92c93bd2012-03-19 14:02:47 +00001613 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001614 break;
1615 }
anthonyafa3dfc2012-03-03 11:31:30 +00001616 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001617 {
anthonyfd706f92012-01-19 04:22:02 +00001618 /* SyncImageSettings() used to set per-image attribute.
1619 This is VERY deep in the image caching structure.
1620 */
anthony52bef752012-03-27 13:54:47 +00001621 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1622 ArgOption("undefined"));
1623 if (parse < 0)
1624 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1625 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001626 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001627 break;
1628 }
anthonyebb73a22012-03-22 14:25:52 +00001629 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001630 }
1631 case 'w':
1632 {
anthonyafa3dfc2012-03-03 11:31:30 +00001633 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001634 {
anthony72feaa62012-01-17 06:46:23 +00001635 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001636 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001637 */
anthony52bef752012-03-27 13:54:47 +00001638 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001639 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001640 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001641 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001642 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001643 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001644 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001645 if (_draw_info->weight <= 800)
1646 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001647 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001648 if (_draw_info->weight >= 100)
1649 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001650 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001651 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001652 break;
1653 }
anthonyafa3dfc2012-03-03 11:31:30 +00001654 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001655 {
anthony72feaa62012-01-17 06:46:23 +00001656 /* Used as a image chromaticity setting
1657 SyncImageSettings() used to set per-image attribute.
1658 */
anthony52bef752012-03-27 13:54:47 +00001659 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001660 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001661 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1662 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001663 break;
1664 }
anthonyebb73a22012-03-22 14:25:52 +00001665 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001666 }
1667 default:
anthonyebb73a22012-03-22 14:25:52 +00001668 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001669 }
anthony24aa8822012-03-11 00:56:06 +00001670
anthony92c93bd2012-03-19 14:02:47 +00001671#undef _image_info
1672#undef _exception
1673#undef _draw_info
1674#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001675#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001676#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001677#undef ArgBooleanNot
1678#undef ArgBooleanString
1679#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001680
anthony31f1bf72012-01-30 12:37:22 +00001681 return;
anthony805a2d42011-09-25 08:25:12 +00001682}
1683
1684/*
1685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1686% %
1687% %
1688% %
anthony43f425d2012-02-26 12:58:58 +00001689+ 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 +00001690% %
1691% %
1692% %
1693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1694%
anthony31f1bf72012-01-30 12:37:22 +00001695% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001696% the images in the CLI wand, with the settings that was previously saved in
1697% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001698%
1699% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001700% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001701%
anthonyd1447672012-01-19 05:33:53 +00001702% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001703%
anthony43f425d2012-02-26 12:58:58 +00001704% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001705% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001706%
1707% A description of each parameter follows:
1708%
anthony43f425d2012-02-26 12:58:58 +00001709% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001710%
anthonyfd706f92012-01-19 04:22:02 +00001711% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001712%
anthonyfd706f92012-01-19 04:22:02 +00001713% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001714%
anthony31f1bf72012-01-30 12:37:22 +00001715% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001716%
anthony31f1bf72012-01-30 12:37:22 +00001717% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001718%
anthonyafa3dfc2012-03-03 11:31:30 +00001719% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1720% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1721% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001722%
anthony24aa8822012-03-11 00:56:06 +00001723% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +00001724%
anthony43f425d2012-02-26 12:58:58 +00001725% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001726% argc,argv
1727% i=index in argv
1728%
anthony2052d272012-02-28 12:48:29 +00001729% option_info = GetCommandOptionInfo(argv[i]);
1730% count=option_info->type;
1731% option_type=option_info->flags;
1732%
1733% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001734% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001735% count>=1 ? argv[i+1] : (char *)NULL,
1736% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001737% i += count+1;
1738%
anthony805a2d42011-09-25 08:25:12 +00001739*/
anthony31f1bf72012-01-30 12:37:22 +00001740
1741/*
1742 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001743 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001744
1745 The image in the list may be modified in three different ways...
1746 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1747 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1748 * one image replace by a list of images (-separate and -crop only!)
1749
anthonyafa3dfc2012-03-03 11:31:30 +00001750 In each case the result replaces the single original image in the list, as
1751 well as the pointer to the modified image (last image added if replaced by a
1752 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001753
1754 As the image pointed to may be replaced, the first image in the list may
1755 also change. GetFirstImageInList() should be used by caller if they wish
1756 return the Image pointer to the first image in list.
1757*/
anthony43f425d2012-02-26 12:58:58 +00001758static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001759 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001760{
1761 Image *
1762 new_image;
1763
anthony805a2d42011-09-25 08:25:12 +00001764 GeometryInfo
1765 geometry_info;
1766
1767 RectangleInfo
1768 geometry;
1769
1770 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001771 flags;
1772
anthony92c93bd2012-03-19 14:02:47 +00001773 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001774 parse;
anthony92c93bd2012-03-19 14:02:47 +00001775
anthony2e4501b2012-03-30 04:41:54 +00001776#define _image_info (cli_wand->wand.image_info)
1777#define _image (cli_wand->wand.images)
1778#define _exception (cli_wand->wand.exception)
1779#define _draw_info (cli_wand->draw_info)
1780#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001781#define IfNormalOp (*option=='-')
1782#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00001783#define normal_op IsMagickTrue(IfNormalOp)
1784#define plus_alt_op IsMagickFalse(IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001785
anthony43f425d2012-02-26 12:58:58 +00001786 assert(cli_wand != (MagickCLI *) NULL);
1787 assert(cli_wand->signature == WandSignature);
1788 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001789 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001790 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001791 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001792
anthony92c93bd2012-03-19 14:02:47 +00001793 (void) SyncImageSettings(_image_info,_image,_exception);
anthony24aa8822012-03-11 00:56:06 +00001794
anthony805a2d42011-09-25 08:25:12 +00001795 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001796
anthony5330ae02012-03-20 14:17:01 +00001797 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001798
anthonyfd706f92012-01-19 04:22:02 +00001799 /* FUTURE: We may need somthing a little more optimized than this!
1800 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1801 */
anthonyafa3dfc2012-03-03 11:31:30 +00001802 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001803 {
1804 case 'a':
1805 {
anthonyafa3dfc2012-03-03 11:31:30 +00001806 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001807 {
anthony7bcfe7f2012-03-30 14:01:22 +00001808 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001809 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001810 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001811 if ((flags & SigmaValue) == 0)
1812 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001813 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001814 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001815 break;
1816 }
anthonyafa3dfc2012-03-03 11:31:30 +00001817 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001818 {
anthonyfe1aa782012-03-24 13:43:04 +00001819 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001820 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001821 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1822 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1823 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001824 _exception);
anthony805a2d42011-09-25 08:25:12 +00001825 break;
1826 }
anthonyafa3dfc2012-03-03 11:31:30 +00001827 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001828 {
anthony7bcfe7f2012-03-30 14:01:22 +00001829 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001830 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001831 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001832 if ((flags & SigmaValue) == 0)
1833 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001834 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001835 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001836 break;
1837 }
anthonyafa3dfc2012-03-03 11:31:30 +00001838 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001839 {
anthony2a0ec8c2012-03-24 04:35:56 +00001840 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1841 if (parse < 0)
anthony92c93bd2012-03-19 14:02:47 +00001842 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1843 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001844 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1845 _exception);
anthony805a2d42011-09-25 08:25:12 +00001846 break;
1847 }
anthonyafa3dfc2012-03-03 11:31:30 +00001848 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001849 {
1850 char
1851 *text,
1852 geometry[MaxTextExtent];
1853
anthony7bcfe7f2012-03-30 14:01:22 +00001854 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001855 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001856 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001857 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001858 if ((flags & SigmaValue) == 0)
1859 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001860 text=InterpretImageProperties(_image_info,_image,arg2,
1861 _exception);
anthony805a2d42011-09-25 08:25:12 +00001862 if (text == (char *) NULL)
1863 break;
anthony92c93bd2012-03-19 14:02:47 +00001864 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001865 text=DestroyString(text);
1866 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1867 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001868 (void) CloneString(&_draw_info->geometry,geometry);
1869 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001870 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001871 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001872 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001873 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001874 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001875 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001876 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001877 (void) AnnotateImage(_image,_draw_info,_exception);
1878 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001879 break;
1880 }
anthonyafa3dfc2012-03-03 11:31:30 +00001881 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001882 {
anthony92c93bd2012-03-19 14:02:47 +00001883 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001884 break;
1885 }
anthonyafa3dfc2012-03-03 11:31:30 +00001886 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001887 {
anthony92c93bd2012-03-19 14:02:47 +00001888 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001889 break;
1890 }
anthonyafa3dfc2012-03-03 11:31:30 +00001891 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001892 {
anthony5330ae02012-03-20 14:17:01 +00001893 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001894 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001895 {
1896 case TopRightOrientation:
1897 {
anthony92c93bd2012-03-19 14:02:47 +00001898 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001899 break;
1900 }
1901 case BottomRightOrientation:
1902 {
anthony92c93bd2012-03-19 14:02:47 +00001903 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001904 break;
1905 }
1906 case BottomLeftOrientation:
1907 {
anthony92c93bd2012-03-19 14:02:47 +00001908 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001909 break;
1910 }
1911 case LeftTopOrientation:
1912 {
anthony92c93bd2012-03-19 14:02:47 +00001913 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001914 break;
1915 }
1916 case RightTopOrientation:
1917 {
anthony92c93bd2012-03-19 14:02:47 +00001918 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001919 break;
1920 }
1921 case RightBottomOrientation:
1922 {
anthony92c93bd2012-03-19 14:02:47 +00001923 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001924 break;
1925 }
1926 case LeftBottomOrientation:
1927 {
anthony92c93bd2012-03-19 14:02:47 +00001928 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001929 break;
1930 }
1931 default:
1932 break;
1933 }
1934 if (new_image != (Image *) NULL)
1935 new_image->orientation=TopLeftOrientation;
1936 break;
1937 }
anthonyebb73a22012-03-22 14:25:52 +00001938 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001939 }
1940 case 'b':
1941 {
anthonyafa3dfc2012-03-03 11:31:30 +00001942 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001943 {
anthony7bcfe7f2012-03-30 14:01:22 +00001944 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001945 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001946 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001947 break;
1948 }
anthonyafa3dfc2012-03-03 11:31:30 +00001949 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001950 {
anthony805a2d42011-09-25 08:25:12 +00001951 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001952 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00001953 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001954 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001955 flags=ParseGeometry(arg1,&geometry_info);
anthony5330ae02012-03-20 14:17:01 +00001956 }
anthony92c93bd2012-03-19 14:02:47 +00001957 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001958 break;
1959 }
anthonyafa3dfc2012-03-03 11:31:30 +00001960 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001961 {
anthony7bcfe7f2012-03-30 14:01:22 +00001962 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001963 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001964 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001965 if ((flags & SigmaValue) == 0)
1966 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001967 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1968 _exception);
anthony805a2d42011-09-25 08:25:12 +00001969 break;
1970 }
anthonyafa3dfc2012-03-03 11:31:30 +00001971 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001972 {
anthony31f1bf72012-01-30 12:37:22 +00001973 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001974 compose;
1975
1976 const char*
anthony5f867ae2011-10-09 10:28:34 +00001977 value;
1978
anthony7bcfe7f2012-03-30 14:01:22 +00001979 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001980 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1981
anthony92c93bd2012-03-19 14:02:47 +00001982 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001983 if (value != (const char *) NULL)
1984 compose=(CompositeOperator) ParseCommandOption(
1985 MagickComposeOptions,MagickFalse,value);
1986 else
anthony92c93bd2012-03-19 14:02:47 +00001987 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001988
anthony92c93bd2012-03-19 14:02:47 +00001989 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001990 if ((flags & SigmaValue) == 0)
1991 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00001992 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001993 break;
1994 }
anthonyafa3dfc2012-03-03 11:31:30 +00001995 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001996 {
1997 double
1998 brightness,
1999 contrast;
2000
2001 GeometryInfo
2002 geometry_info;
2003
2004 MagickStatusType
2005 flags;
2006
anthony7bcfe7f2012-03-30 14:01:22 +00002007 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002008 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002009 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002010 brightness=geometry_info.rho;
2011 contrast=0.0;
2012 if ((flags & SigmaValue) != 0)
2013 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00002014 (void) BrightnessContrastImage(_image,brightness,contrast,
2015 _exception);
anthony805a2d42011-09-25 08:25:12 +00002016 break;
2017 }
anthonyebb73a22012-03-22 14:25:52 +00002018 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002019 }
2020 case 'c':
2021 {
anthonyafa3dfc2012-03-03 11:31:30 +00002022 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002023 {
2024 char
2025 *color_correction_collection;
2026
2027 /*
2028 Color correct with a color decision list.
2029 */
anthony92c93bd2012-03-19 14:02:47 +00002030 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002031 if (color_correction_collection == (char *) NULL)
2032 break;
anthony92c93bd2012-03-19 14:02:47 +00002033 (void) ColorDecisionListImage(_image,color_correction_collection,
2034 _exception);
anthony805a2d42011-09-25 08:25:12 +00002035 break;
2036 }
anthonyafa3dfc2012-03-03 11:31:30 +00002037 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002038 {
anthony7bcfe7f2012-03-30 14:01:22 +00002039 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002040 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002041 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002042 if ((flags & SigmaValue) == 0)
2043 geometry_info.sigma=1.0;
2044 if ((flags & XiValue) == 0)
2045 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002046 new_image=CharcoalImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002047 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002048 break;
2049 }
anthonyafa3dfc2012-03-03 11:31:30 +00002050 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002051 {
anthony7bcfe7f2012-03-30 14:01:22 +00002052 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002053 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002054 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
2055 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002056 break;
2057 }
anthonyafa3dfc2012-03-03 11:31:30 +00002058 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002059 {
anthony92c93bd2012-03-19 14:02:47 +00002060 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002061 break;
2062 }
anthonyafa3dfc2012-03-03 11:31:30 +00002063 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002064 {
anthonyafa3dfc2012-03-03 11:31:30 +00002065 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002066 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00002067 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002068 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002069 break;
2070 }
anthonyafa3dfc2012-03-03 11:31:30 +00002071 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002072 {
2073 CacheView
2074 *mask_view;
2075
2076 Image
2077 *mask_image;
2078
2079 register Quantum
2080 *restrict q;
2081
2082 register ssize_t
2083 x;
2084
2085 ssize_t
2086 y;
2087
anthonyafa3dfc2012-03-03 11:31:30 +00002088 if (IfPlusOp) {
2089 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002090 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002091 break;
2092 }
anthony92c93bd2012-03-19 14:02:47 +00002093 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002094 if (mask_image == (Image *) NULL)
2095 break;
anthony7bcfe7f2012-03-30 14:01:22 +00002096 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00002097 break;
anthony5330ae02012-03-20 14:17:01 +00002098 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002099 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00002100 mask_view=AcquireCacheView(mask_image);
2101 for (y=0; y < (ssize_t) mask_image->rows; y++)
2102 {
2103 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002104 _exception);
anthony805a2d42011-09-25 08:25:12 +00002105 if (q == (Quantum *) NULL)
2106 break;
2107 for (x=0; x < (ssize_t) mask_image->columns; x++)
2108 {
anthony7bcfe7f2012-03-30 14:01:22 +00002109 if (IfMagickFalse(mask_image->matte))
anthony805a2d42011-09-25 08:25:12 +00002110 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2111 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2112 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2113 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2114 q+=GetPixelChannels(mask_image);
2115 }
anthony7bcfe7f2012-03-30 14:01:22 +00002116 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00002117 break;
2118 }
anthonyfd706f92012-01-19 04:22:02 +00002119 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002120 mask_view=DestroyCacheView(mask_view);
2121 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002122 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002123 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002124 break;
2125 }
anthonyafa3dfc2012-03-03 11:31:30 +00002126 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002127 {
anthony92c93bd2012-03-19 14:02:47 +00002128 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002129 break;
2130 }
anthonyafa3dfc2012-03-03 11:31:30 +00002131 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002132 {
anthony7bcfe7f2012-03-30 14:01:22 +00002133 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002134 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002135 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002136 break;
2137 }
anthonyafa3dfc2012-03-03 11:31:30 +00002138 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002139 {
2140 KernelInfo
2141 *kernel;
2142
anthonyfd706f92012-01-19 04:22:02 +00002143 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002144 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002145 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002146 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002147 kernel=DestroyKernelInfo(kernel);
2148 break;
2149 }
anthonyafa3dfc2012-03-03 11:31:30 +00002150 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002151 {
anthony5330ae02012-03-20 14:17:01 +00002152 /* Reduce the number of colors in the image.
2153 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002154 */
anthony92c93bd2012-03-19 14:02:47 +00002155 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2156 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002157 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002158 if ((_image->storage_class == DirectClass) ||
2159 _image->colors > _quantize_info->number_colors)
2160 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002161 else
anthony92c93bd2012-03-19 14:02:47 +00002162 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002163 break;
2164 }
anthonyafa3dfc2012-03-03 11:31:30 +00002165 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002166 {
anthony5330ae02012-03-20 14:17:01 +00002167 /* WARNING: this is both a image_info setting (already done)
2168 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002169
2170 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002171 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002172
anthonyd2cdc862011-10-07 14:07:17 +00002173 Note that +colorspace sets "undefined" or no effect on
2174 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002175 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002176 */
anthony92c93bd2012-03-19 14:02:47 +00002177 (void) TransformImageColorspace(_image,
2178 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2179 _exception);
anthony805a2d42011-09-25 08:25:12 +00002180 break;
2181 }
anthonyafa3dfc2012-03-03 11:31:30 +00002182 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002183 {
anthonydcf3a912012-03-22 14:33:17 +00002184 /* DEPRECIATED: The -/+level provides far more controlled form */
anthony92c93bd2012-03-19 14:02:47 +00002185 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002186 break;
2187 }
anthonyafa3dfc2012-03-03 11:31:30 +00002188 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002189 {
2190 double
2191 black_point,
2192 white_point;
2193
2194 MagickStatusType
2195 flags;
2196
anthony7bcfe7f2012-03-30 14:01:22 +00002197 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002198 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002199 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002200 black_point=geometry_info.rho;
2201 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2202 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002203 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002204 black_point*=(double) _image->columns*_image->rows/100.0;
2205 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002206 }
anthony92c93bd2012-03-19 14:02:47 +00002207 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002208 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002209 (void) ContrastStretchImage(_image,black_point,white_point,
2210 _exception);
anthony805a2d42011-09-25 08:25:12 +00002211 break;
2212 }
anthonyafa3dfc2012-03-03 11:31:30 +00002213 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002214 {
2215 KernelInfo
2216 *kernel_info;
2217
anthonyfd706f92012-01-19 04:22:02 +00002218 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002219 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002220 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +00002221 /* kernel_info->bias=_image->bias; -- FUTURE: check this path! */
anthony92c93bd2012-03-19 14:02:47 +00002222 new_image=ConvolveImage(_image,kernel_info,_exception);
anthony805a2d42011-09-25 08:25:12 +00002223 kernel_info=DestroyKernelInfo(kernel_info);
2224 break;
2225 }
anthonyafa3dfc2012-03-03 11:31:30 +00002226 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002227 {
anthony31f1bf72012-01-30 12:37:22 +00002228 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002229 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002230 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002231 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002232 break;
2233 }
anthonyafa3dfc2012-03-03 11:31:30 +00002234 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002235 {
anthony7bcfe7f2012-03-30 14:01:22 +00002236 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002237 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002238 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2239 _exception);
anthony805a2d42011-09-25 08:25:12 +00002240 break;
2241 }
anthonyebb73a22012-03-22 14:25:52 +00002242 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002243 }
2244 case 'd':
2245 {
anthonyafa3dfc2012-03-03 11:31:30 +00002246 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002247 {
2248 StringInfo
2249 *passkey;
2250
anthony92c93bd2012-03-19 14:02:47 +00002251 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002252 if (passkey == (StringInfo *) NULL)
2253 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2254
2255 (void) PasskeyDecipherImage(_image,passkey,_exception);
2256 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002257 break;
2258 }
anthonyafa3dfc2012-03-03 11:31:30 +00002259 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002260 {
anthony92c93bd2012-03-19 14:02:47 +00002261 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002262 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002263
anthonydcf510d2011-10-30 13:51:40 +00002264 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2265 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002266
anthonyfd706f92012-01-19 04:22:02 +00002267 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002268 */
anthony92c93bd2012-03-19 14:02:47 +00002269 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002270 break;
2271 }
anthonyafa3dfc2012-03-03 11:31:30 +00002272 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002273 {
2274 double
2275 threshold;
2276
anthonyebb73a22012-03-22 14:25:52 +00002277 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002278 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002279 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002280 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002281 }
anthonyafa3dfc2012-03-03 11:31:30 +00002282 else
2283 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002284 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002285 break;
2286 }
anthonyafa3dfc2012-03-03 11:31:30 +00002287 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002288 {
anthony92c93bd2012-03-19 14:02:47 +00002289 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002290 break;
2291 }
anthonyafa3dfc2012-03-03 11:31:30 +00002292 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002293 {
2294 char
2295 *args,
2296 token[MaxTextExtent];
2297
2298 const char
2299 *p;
2300
anthony805a2d42011-09-25 08:25:12 +00002301 double
2302 *arguments;
2303
2304 register ssize_t
2305 x;
2306
2307 size_t
2308 number_arguments;
2309
anthony2a0ec8c2012-03-24 04:35:56 +00002310 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2311 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002312 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2313 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002314 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002315 {
anthony80c37752012-01-16 01:03:11 +00002316 double
2317 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002318 /* Special Case - Argument is actually a resize geometry!
2319 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002320 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002321 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002322 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002323 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2324 option,arg2);
2325 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002326 resize_args[0]=(double) geometry.width;
2327 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002328 new_image=DistortImage(_image,(DistortImageMethod) parse,
2329 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002330 break;
2331 }
anthonyfd706f92012-01-19 04:22:02 +00002332 /* handle percent arguments */
anthonyebb73a22012-03-22 14:25:52 +00002333 args=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00002334 if (args == (char *) NULL)
2335 break;
anthonyfd706f92012-01-19 04:22:02 +00002336 /* convert arguments into an array of doubles
2337 FUTURE: make this a separate function.
2338 Also make use of new 'sentinal' feature to avoid need for
2339 tokenization.
2340 */
anthony805a2d42011-09-25 08:25:12 +00002341 p=(char *) args;
2342 for (x=0; *p != '\0'; x++)
2343 {
2344 GetMagickToken(p,&p,token);
2345 if (*token == ',')
2346 GetMagickToken(p,&p,token);
2347 }
2348 number_arguments=(size_t) x;
2349 arguments=(double *) AcquireQuantumMemory(number_arguments,
2350 sizeof(*arguments));
2351 if (arguments == (double *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002352 CLIWandExceptionBreak(ResourceLimitFatalError,
2353 "MemoryAllocationFailed",option);
anthony805a2d42011-09-25 08:25:12 +00002354 (void) ResetMagickMemory(arguments,0,number_arguments*
anthonyebb73a22012-03-22 14:25:52 +00002355 sizeof(*arguments));
anthony805a2d42011-09-25 08:25:12 +00002356 p=(char *) args;
2357 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2358 {
2359 GetMagickToken(p,&p,token);
2360 if (*token == ',')
2361 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002362 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002363 }
2364 args=DestroyString(args);
anthony2a0ec8c2012-03-24 04:35:56 +00002365 new_image=DistortImage(_image,(DistortImageMethod) parse,
2366 number_arguments,arguments,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002367 arguments=(double *) RelinquishMagickMemory(arguments);
2368 break;
2369 }
anthonyafa3dfc2012-03-03 11:31:30 +00002370 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002371 {
anthony92c93bd2012-03-19 14:02:47 +00002372 (void) CloneString(&_draw_info->primitive,arg1);
2373 (void) DrawImage(_image,_draw_info,_exception);
2374 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002375 break;
2376 }
anthonyebb73a22012-03-22 14:25:52 +00002377 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002378 }
2379 case 'e':
2380 {
anthonyafa3dfc2012-03-03 11:31:30 +00002381 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002382 {
anthony7bcfe7f2012-03-30 14:01:22 +00002383 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002384 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002385 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002386 if ((flags & SigmaValue) == 0)
2387 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002388 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2389 _exception);
anthony805a2d42011-09-25 08:25:12 +00002390 break;
2391 }
anthonyafa3dfc2012-03-03 11:31:30 +00002392 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002393 {
anthony7bcfe7f2012-03-30 14:01:22 +00002394 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002395 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002396 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002397 if ((flags & SigmaValue) == 0)
2398 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002399 new_image=EmbossImage(_image,geometry_info.rho,
2400 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002401 break;
2402 }
anthonyafa3dfc2012-03-03 11:31:30 +00002403 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002404 {
2405 StringInfo
2406 *passkey;
2407
anthony92c93bd2012-03-19 14:02:47 +00002408 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002409 if (passkey != (StringInfo *) NULL)
2410 {
anthony92c93bd2012-03-19 14:02:47 +00002411 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002412 passkey=DestroyStringInfo(passkey);
2413 }
2414 break;
2415 }
anthonyafa3dfc2012-03-03 11:31:30 +00002416 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002417 {
anthony92c93bd2012-03-19 14:02:47 +00002418 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002419 break;
2420 }
anthonyafa3dfc2012-03-03 11:31:30 +00002421 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002422 {
anthony92c93bd2012-03-19 14:02:47 +00002423 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002424 break;
2425 }
anthonyafa3dfc2012-03-03 11:31:30 +00002426 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002427 {
2428 double
2429 constant;
2430
anthony2a0ec8c2012-03-24 04:35:56 +00002431 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2432 if ( parse < 0 )
2433 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2434 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002435 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002436 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002437 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002438 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2439 _exception);
anthony805a2d42011-09-25 08:25:12 +00002440 break;
2441 }
anthonyafa3dfc2012-03-03 11:31:30 +00002442 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002443 {
anthony7bcfe7f2012-03-30 14:01:22 +00002444 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002445 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002446 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002447 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002448 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002449 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002450 geometry.height=_image->rows;
2451 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002452 break;
2453 }
anthonyebb73a22012-03-22 14:25:52 +00002454 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002455 }
2456 case 'f':
2457 {
anthonyafa3dfc2012-03-03 11:31:30 +00002458 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002459 {
anthony31f1bf72012-01-30 12:37:22 +00002460 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002461 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002462 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002463 break;
2464 }
anthony92c93bd2012-03-19 14:02:47 +00002465 (void) SetImageArtifact(_image,"identify:features","true");
2466 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002467 break;
2468 }
anthonyafa3dfc2012-03-03 11:31:30 +00002469 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002470 {
anthony92c93bd2012-03-19 14:02:47 +00002471 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002472 break;
2473 }
anthonyafa3dfc2012-03-03 11:31:30 +00002474 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002475 {
anthony92c93bd2012-03-19 14:02:47 +00002476 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002477 break;
2478 }
anthonyafa3dfc2012-03-03 11:31:30 +00002479 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002480 {
2481 PixelInfo
2482 target;
2483
anthony7bcfe7f2012-03-30 14:01:22 +00002484 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002485 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002486 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2487 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2488 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2489 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002490 break;
2491 }
anthonyafa3dfc2012-03-03 11:31:30 +00002492 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002493 {
2494 FrameInfo
2495 frame_info;
2496
anthony31f1bf72012-01-30 12:37:22 +00002497 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002498 compose;
2499
2500 const char*
2501 value;
2502
anthony92c93bd2012-03-19 14:02:47 +00002503 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002504 if (value != (const char *) NULL)
2505 compose=(CompositeOperator) ParseCommandOption(
2506 MagickComposeOptions,MagickFalse,value);
2507 else
anthony92c93bd2012-03-19 14:02:47 +00002508 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002509
anthony7bcfe7f2012-03-30 14:01:22 +00002510 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002511 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002512 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002513 frame_info.width=geometry.width;
2514 frame_info.height=geometry.height;
2515 if ((flags & HeightValue) == 0)
2516 frame_info.height=geometry.width;
2517 frame_info.outer_bevel=geometry.x;
2518 frame_info.inner_bevel=geometry.y;
2519 frame_info.x=(ssize_t) frame_info.width;
2520 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002521 frame_info.width=_image->columns+2*frame_info.width;
2522 frame_info.height=_image->rows+2*frame_info.height;
2523 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002524 break;
2525 }
anthonyafa3dfc2012-03-03 11:31:30 +00002526 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002527 {
2528 char
2529 *arguments,
2530 token[MaxTextExtent];
2531
2532 const char
2533 *p;
2534
2535 double
2536 *parameters;
2537
anthony805a2d42011-09-25 08:25:12 +00002538 register ssize_t
2539 x;
2540
2541 size_t
2542 number_parameters;
2543
cristy947cb4c2011-10-20 18:41:46 +00002544 /*
2545 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002546 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002547 */
anthony2a0ec8c2012-03-24 04:35:56 +00002548 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2549 if ( parse < 0 )
2550 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2551 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002552 arguments=InterpretImageProperties(_image_info,_image,arg2,
2553 _exception);
anthony805a2d42011-09-25 08:25:12 +00002554 if (arguments == (char *) NULL)
anthony2a0ec8c2012-03-24 04:35:56 +00002555 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony805a2d42011-09-25 08:25:12 +00002556 p=(char *) arguments;
2557 for (x=0; *p != '\0'; x++)
2558 {
2559 GetMagickToken(p,&p,token);
2560 if (*token == ',')
2561 GetMagickToken(p,&p,token);
2562 }
2563 number_parameters=(size_t) x;
2564 parameters=(double *) AcquireQuantumMemory(number_parameters,
2565 sizeof(*parameters));
2566 if (parameters == (double *) NULL)
2567 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002568 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002569 (void) ResetMagickMemory(parameters,0,number_parameters*
2570 sizeof(*parameters));
2571 p=(char *) arguments;
anthony2a0ec8c2012-03-24 04:35:56 +00002572 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++) {
anthony805a2d42011-09-25 08:25:12 +00002573 GetMagickToken(p,&p,token);
2574 if (*token == ',')
2575 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002576 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002577 }
2578 arguments=DestroyString(arguments);
anthony2a0ec8c2012-03-24 04:35:56 +00002579 (void) FunctionImage(_image,(MagickFunction)parse,number_parameters,
2580 parameters,_exception);
anthony805a2d42011-09-25 08:25:12 +00002581 parameters=(double *) RelinquishMagickMemory(parameters);
2582 break;
2583 }
anthonyebb73a22012-03-22 14:25:52 +00002584 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002585 }
2586 case 'g':
2587 {
anthonyafa3dfc2012-03-03 11:31:30 +00002588 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002589 {
anthony7bcfe7f2012-03-30 14:01:22 +00002590 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002591 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafa3dfc2012-03-03 11:31:30 +00002592 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002593 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2594 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002595 else
anthony92c93bd2012-03-19 14:02:47 +00002596 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002597 break;
2598 }
anthonyafa3dfc2012-03-03 11:31:30 +00002599 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2600 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002601 {
anthony7bcfe7f2012-03-30 14:01:22 +00002602 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002603 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002604 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002605 if ((flags & SigmaValue) == 0)
2606 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002607 new_image=GaussianBlurImage(_image,geometry_info.rho,
2608 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002609 break;
2610 }
anthonyafa3dfc2012-03-03 11:31:30 +00002611 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002612 {
anthonyfd706f92012-01-19 04:22:02 +00002613 /*
anthony31f1bf72012-01-30 12:37:22 +00002614 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002615 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002616 FUTURE: Why if no 'offset' does this resize ALL images?
2617 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002618 */
anthonyafa3dfc2012-03-03 11:31:30 +00002619 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002620 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002621 if (_image->geometry != (char *) NULL)
2622 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002623 break;
2624 }
anthony7bcfe7f2012-03-30 14:01:22 +00002625 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002626 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002627 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002628 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002629 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002630 else
anthony92c93bd2012-03-19 14:02:47 +00002631 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002632 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002633 break;
2634 }
anthonyebb73a22012-03-22 14:25:52 +00002635 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002636 }
2637 case 'h':
2638 {
anthonyafa3dfc2012-03-03 11:31:30 +00002639 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002640 {
anthony92c93bd2012-03-19 14:02:47 +00002641 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002642 break;
2643 }
anthonyebb73a22012-03-22 14:25:52 +00002644 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002645 }
2646 case 'i':
2647 {
anthonyafa3dfc2012-03-03 11:31:30 +00002648 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002649 {
anthony31f1bf72012-01-30 12:37:22 +00002650 const char
2651 *format,
anthony805a2d42011-09-25 08:25:12 +00002652 *text;
2653
anthony92c93bd2012-03-19 14:02:47 +00002654 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002655 if (format == (char *) NULL)
2656 {
anthony92c93bd2012-03-19 14:02:47 +00002657 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2658 _exception);
anthony805a2d42011-09-25 08:25:12 +00002659 break;
2660 }
anthony92c93bd2012-03-19 14:02:47 +00002661 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002662 if (text == (char *) NULL)
2663 break;
2664 (void) fputs(text,stdout);
2665 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002666 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002667 break;
2668 }
anthonyafa3dfc2012-03-03 11:31:30 +00002669 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002670 {
anthony7bcfe7f2012-03-30 14:01:22 +00002671 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002672 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002673 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002674 new_image=ImplodeImage(_image,geometry_info.rho,
2675 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002676 break;
2677 }
anthonyafa3dfc2012-03-03 11:31:30 +00002678 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002679 {
anthonyfe1aa782012-03-24 13:43:04 +00002680 /* FUTURE: New to IMv7
2681 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002682 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002683 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002684 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2685 new_image=InterpolativeResizeImage(_image,geometry.width,
2686 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002687 break;
2688 }
anthonyebb73a22012-03-22 14:25:52 +00002689 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002690 }
2691 case 'l':
2692 {
anthonyafa3dfc2012-03-03 11:31:30 +00002693 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002694 {
anthony7bcfe7f2012-03-30 14:01:22 +00002695 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002696 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002697 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002698 if ((flags & PercentValue) != 0)
2699 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002700 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002701 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002702 _exception);
anthony805a2d42011-09-25 08:25:12 +00002703 break;
2704 }
anthonyafa3dfc2012-03-03 11:31:30 +00002705 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002706 {
2707 MagickRealType
2708 black_point,
2709 gamma,
2710 white_point;
2711
2712 MagickStatusType
2713 flags;
2714
anthony7bcfe7f2012-03-30 14:01:22 +00002715 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002716 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002717 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002718 black_point=geometry_info.rho;
2719 white_point=(MagickRealType) QuantumRange;
2720 if ((flags & SigmaValue) != 0)
2721 white_point=geometry_info.sigma;
2722 gamma=1.0;
2723 if ((flags & XiValue) != 0)
2724 gamma=geometry_info.xi;
2725 if ((flags & PercentValue) != 0)
2726 {
2727 black_point*=(MagickRealType) (QuantumRange/100.0);
2728 white_point*=(MagickRealType) (QuantumRange/100.0);
2729 }
2730 if ((flags & SigmaValue) == 0)
2731 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002732 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002733 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002734 else
anthony92c93bd2012-03-19 14:02:47 +00002735 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002736 break;
2737 }
anthonyafa3dfc2012-03-03 11:31:30 +00002738 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002739 {
2740 char
2741 token[MaxTextExtent];
2742
2743 const char
2744 *p;
2745
2746 PixelInfo
2747 black_point,
2748 white_point;
2749
anthonyfd706f92012-01-19 04:22:02 +00002750 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002751 GetMagickToken(p,&p,token); /* get black point color */
2752 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002753 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002754 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002755 else
cristy269c9412011-10-13 23:41:15 +00002756 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002757 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002758 if (isalpha((int) token[0]) || (token[0] == '#'))
2759 GetMagickToken(p,&p,token);
2760 if (*token == '\0')
2761 white_point=black_point; /* set everything to that color */
2762 else
2763 {
2764 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2765 GetMagickToken(p,&p,token); /* Get white point color. */
2766 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002767 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002768 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002769 else
cristy269c9412011-10-13 23:41:15 +00002770 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002771 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002772 }
anthony92c93bd2012-03-19 14:02:47 +00002773 (void) LevelImageColors(_image,&black_point,&white_point,
2774 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002775 break;
2776 }
anthonyafa3dfc2012-03-03 11:31:30 +00002777 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002778 {
2779 double
2780 black_point,
2781 white_point;
2782
2783 MagickStatusType
2784 flags;
2785
anthony7bcfe7f2012-03-30 14:01:22 +00002786 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002787 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002788 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002789 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002790 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002791 if ((flags & SigmaValue) != 0)
2792 white_point=geometry_info.sigma;
2793 if ((flags & PercentValue) != 0)
2794 {
anthony92c93bd2012-03-19 14:02:47 +00002795 black_point*=(double) _image->columns*_image->rows/100.0;
2796 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002797 }
2798 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002799 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002800 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002801 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002802 break;
2803 }
anthonyafa3dfc2012-03-03 11:31:30 +00002804 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002805 {
anthonyfe1aa782012-03-24 13:43:04 +00002806 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002807 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002808 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002809 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002810 if ((flags & XValue) == 0)
2811 geometry.x=1;
2812 if ((flags & YValue) == 0)
2813 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002814 new_image=LiquidRescaleImage(_image,geometry.width,
2815 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002816 break;
2817 }
anthonyafa3dfc2012-03-03 11:31:30 +00002818 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002819 {
anthony92c93bd2012-03-19 14:02:47 +00002820 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002821 break;
2822 }
anthonyebb73a22012-03-22 14:25:52 +00002823 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002824 }
2825 case 'm':
2826 {
anthonyafa3dfc2012-03-03 11:31:30 +00002827 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002828 {
2829 Image
2830 *remap_image;
2831
anthony31f1bf72012-01-30 12:37:22 +00002832 /* DEPRECIATED use -remap */
anthony92c93bd2012-03-19 14:02:47 +00002833 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002834 if (remap_image == (Image *) NULL)
2835 break;
anthony92c93bd2012-03-19 14:02:47 +00002836 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002837 remap_image=DestroyImage(remap_image);
2838 break;
2839 }
anthonyafa3dfc2012-03-03 11:31:30 +00002840 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002841 {
2842 Image
2843 *mask;
2844
anthonyafa3dfc2012-03-03 11:31:30 +00002845 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002846 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002847 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002848 break;
2849 }
anthony5330ae02012-03-20 14:17:01 +00002850 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002851 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002852 if (mask == (Image *) NULL)
2853 break;
anthony92c93bd2012-03-19 14:02:47 +00002854 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002855 mask=DestroyImage(mask);
2856 break;
2857 }
anthonyafa3dfc2012-03-03 11:31:30 +00002858 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002859 {
anthony31f1bf72012-01-30 12:37:22 +00002860 /* DEPRECIATED */
anthony92c93bd2012-03-19 14:02:47 +00002861 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2862 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002863 break;
2864 }
anthonya3ef4ed2012-03-17 06:52:53 +00002865 if (LocaleCompare("median",option+1) == 0)
2866 {
2867 /* DEPRECIATED - use -statistic Median */
anthony7bcfe7f2012-03-30 14:01:22 +00002868 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002869 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya3ef4ed2012-03-17 06:52:53 +00002870 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2871 break;
2872 }
anthonyafa3dfc2012-03-03 11:31:30 +00002873 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002874 {
anthony7bcfe7f2012-03-30 14:01:22 +00002875 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002876 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002877 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002878 if ((flags & SigmaValue) == 0)
2879 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002880 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2881 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002882 break;
2883 }
anthonyafa3dfc2012-03-03 11:31:30 +00002884 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002885 {
anthony7bcfe7f2012-03-30 14:01:22 +00002886 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002887 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002888 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002889 break;
2890 }
anthonyafa3dfc2012-03-03 11:31:30 +00002891 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002892 {
anthony92c93bd2012-03-19 14:02:47 +00002893 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002894 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002895 break;
2896 }
anthonyafa3dfc2012-03-03 11:31:30 +00002897 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002898 {
anthony92c93bd2012-03-19 14:02:47 +00002899 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002900 break;
2901 }
anthonyafa3dfc2012-03-03 11:31:30 +00002902 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002903 {
2904 char
2905 token[MaxTextExtent];
2906
2907 const char
2908 *p;
2909
2910 KernelInfo
2911 *kernel;
2912
anthony805a2d42011-09-25 08:25:12 +00002913 ssize_t
2914 iterations;
2915
anthonyfd706f92012-01-19 04:22:02 +00002916 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002917 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002918 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2919 if ( parse < 0 )
2920 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2921 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002922 iterations=1L;
2923 GetMagickToken(p,&p,token);
2924 if ((*p == ':') || (*p == ','))
2925 GetMagickToken(p,&p,token);
2926 if ((*p != '\0'))
2927 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002928 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002929 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002930 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2931 option,arg2);
2932 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2933 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002934 kernel=DestroyKernelInfo(kernel);
2935 break;
2936 }
anthonyafa3dfc2012-03-03 11:31:30 +00002937 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002938 {
anthony7bcfe7f2012-03-30 14:01:22 +00002939 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002940 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002941 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002942 if ((flags & SigmaValue) == 0)
2943 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002944 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002945 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002946 break;
2947 }
anthonyebb73a22012-03-22 14:25:52 +00002948 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002949 }
2950 case 'n':
2951 {
anthonyafa3dfc2012-03-03 11:31:30 +00002952 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002953 {
anthony92c93bd2012-03-19 14:02:47 +00002954 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002955 break;
2956 }
anthonyafa3dfc2012-03-03 11:31:30 +00002957 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002958 {
anthonyafa3dfc2012-03-03 11:31:30 +00002959 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002960 {
anthony7bcfe7f2012-03-30 14:01:22 +00002961 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002962 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002963 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002964 if ((flags & SigmaValue) == 0)
2965 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002966 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2967 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002968 }
2969 else
2970 {
anthony31f1bf72012-01-30 12:37:22 +00002971 double
2972 attenuate;
2973
2974 const char*
2975 value;
2976
anthony7bc87992012-03-25 02:32:51 +00002977 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2978 if ( parse < 0 )
2979 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2980 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002981 value=GetImageOption(_image_info,"attenuate");
anthony31f1bf72012-01-30 12:37:22 +00002982 if (value != (const char *) NULL)
2983 attenuate=StringToDouble(value,(char **) NULL);
2984 else
2985 attenuate=1.0;
2986
anthony7bc87992012-03-25 02:32:51 +00002987 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2988 _exception);
anthony805a2d42011-09-25 08:25:12 +00002989 }
2990 break;
2991 }
anthonyafa3dfc2012-03-03 11:31:30 +00002992 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002993 {
anthony92c93bd2012-03-19 14:02:47 +00002994 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002995 break;
2996 }
anthonyebb73a22012-03-22 14:25:52 +00002997 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002998 }
2999 case 'o':
3000 {
anthonyafa3dfc2012-03-03 11:31:30 +00003001 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003002 {
3003 PixelInfo
3004 target;
3005
anthony92c93bd2012-03-19 14:02:47 +00003006 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3007 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
3008 _exception);
anthony805a2d42011-09-25 08:25:12 +00003009 break;
3010 }
anthonyafa3dfc2012-03-03 11:31:30 +00003011 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003012 {
anthony92c93bd2012-03-19 14:02:47 +00003013 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003014 break;
3015 }
anthonyebb73a22012-03-22 14:25:52 +00003016 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003017 }
3018 case 'p':
3019 {
anthonyafa3dfc2012-03-03 11:31:30 +00003020 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003021 {
anthonyfd706f92012-01-19 04:22:02 +00003022 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003023 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
3024 _exception);
anthony805a2d42011-09-25 08:25:12 +00003025 break;
3026 }
anthonyafa3dfc2012-03-03 11:31:30 +00003027 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003028 {
cristye9e3d382011-12-14 01:50:13 +00003029 const char
3030 *caption;
3031
anthony805a2d42011-09-25 08:25:12 +00003032 double
3033 angle;
3034
anthony7bc87992012-03-25 02:32:51 +00003035 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00003036 RandomInfo
3037 *random_info;
anthony805a2d42011-09-25 08:25:12 +00003038
anthonyf42014d2012-03-25 09:53:06 +00003039 random_info=AcquireRandomInfo();
3040 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
3041 random_info=DestroyRandomInfo(random_info);
3042 }
anthony7bc87992012-03-25 02:32:51 +00003043 else {
anthony7bcfe7f2012-03-30 14:01:22 +00003044 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003045 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3046 flags=ParseGeometry(arg1,&geometry_info);
3047 angle=geometry_info.rho;
3048 }
anthony92c93bd2012-03-19 14:02:47 +00003049 caption=GetImageProperty(_image,"caption",_exception);
3050 new_image=PolaroidImage(_image,_draw_info,caption,angle,
3051 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003052 break;
3053 }
anthonyafa3dfc2012-03-03 11:31:30 +00003054 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003055 {
anthony7bcfe7f2012-03-30 14:01:22 +00003056 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00003057 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003058 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003059 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
3060 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00003061 break;
3062 }
anthonyafa3dfc2012-03-03 11:31:30 +00003063 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003064 {
anthony31f1bf72012-01-30 12:37:22 +00003065 /* FUTURE: should be a 'Genesis' option?
3066 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00003067 Why???
cristy947cb4c2011-10-20 18:41:46 +00003068 */
anthony7bc87992012-03-25 02:32:51 +00003069 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
3070 if ( parse < 0 )
3071 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
3072 option,arg1);
3073 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003074 break;
3075 }
anthonyafa3dfc2012-03-03 11:31:30 +00003076 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003077 {
3078 const char
3079 *name;
3080
3081 const StringInfo
3082 *profile;
3083
3084 Image
3085 *profile_image;
3086
3087 ImageInfo
3088 *profile_info;
3089
anthonyafa3dfc2012-03-03 11:31:30 +00003090 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00003091 { /* Remove a profile from the _image. */
3092 (void) ProfileImage(_image,arg1,(const unsigned char *)
3093 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003094 break;
3095 }
anthony92c93bd2012-03-19 14:02:47 +00003096 /* Associate a profile with the _image. */
3097 profile_info=CloneImageInfo(_image_info);
3098 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00003099 if (profile != (StringInfo *) NULL)
3100 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00003101 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003102 profile_info=DestroyImageInfo(profile_info);
3103 if (profile_image == (Image *) NULL)
3104 {
3105 StringInfo
3106 *profile;
3107
anthony92c93bd2012-03-19 14:02:47 +00003108 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00003109 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00003110 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00003111 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003112 if (profile != (StringInfo *) NULL)
3113 {
anthony92c93bd2012-03-19 14:02:47 +00003114 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00003115 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00003116 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003117 profile=DestroyStringInfo(profile);
3118 }
3119 profile_info=DestroyImageInfo(profile_info);
3120 break;
3121 }
3122 ResetImageProfileIterator(profile_image);
3123 name=GetNextImageProfile(profile_image);
3124 while (name != (const char *) NULL)
3125 {
3126 profile=GetImageProfile(profile_image,name);
3127 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003128 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3129 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003130 name=GetNextImageProfile(profile_image);
3131 }
3132 profile_image=DestroyImage(profile_image);
3133 break;
3134 }
anthonyebb73a22012-03-22 14:25:52 +00003135 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003136 }
anthony805a2d42011-09-25 08:25:12 +00003137 case 'r':
3138 {
anthonyafa3dfc2012-03-03 11:31:30 +00003139 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003140 {
anthony7bcfe7f2012-03-30 14:01:22 +00003141 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003142 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003143 flags=ParseGeometry(arg1,&geometry_info);
cristyaa2c16c2012-03-25 22:21:35 +00003144 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003145 break;
3146 }
anthonyafa3dfc2012-03-03 11:31:30 +00003147 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003148 {
anthony7bcfe7f2012-03-30 14:01:22 +00003149 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003150 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003151 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003152 if ((flags & SigmaValue) == 0)
3153 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00003154 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003155 break;
3156 }
anthonyafa3dfc2012-03-03 11:31:30 +00003157 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003158 {
anthony7bcfe7f2012-03-30 14:01:22 +00003159 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003160 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003161 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003162 break;
3163 }
anthonyafa3dfc2012-03-03 11:31:30 +00003164 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003165 {
3166 Image
3167 *remap_image;
3168
anthony92c93bd2012-03-19 14:02:47 +00003169 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003170 if (remap_image == (Image *) NULL)
3171 break;
anthony92c93bd2012-03-19 14:02:47 +00003172 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003173 remap_image=DestroyImage(remap_image);
3174 break;
3175 }
anthonyafa3dfc2012-03-03 11:31:30 +00003176 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003177 {
anthonyafa3dfc2012-03-03 11:31:30 +00003178 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00003179 {
anthony7bcfe7f2012-03-30 14:01:22 +00003180 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00003181 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3182 arg1);
3183 (void) ResetImagePage(_image,arg1);
3184 }
anthony31f1bf72012-01-30 12:37:22 +00003185 else
anthony92c93bd2012-03-19 14:02:47 +00003186 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003187 break;
3188 }
anthonyafa3dfc2012-03-03 11:31:30 +00003189 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003190 {
anthonyf46d4262012-03-26 03:30:34 +00003191 /* FUTURE: Roll into a resize special operation */
anthony7bcfe7f2012-03-30 14:01:22 +00003192 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003193 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003194 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003195 if ((flags & SigmaValue) == 0)
3196 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003197 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003198 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003199 break;
3200 }
anthonyafa3dfc2012-03-03 11:31:30 +00003201 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003202 {
anthony7bcfe7f2012-03-30 14:01:22 +00003203 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003204 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003205 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3206 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003207 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003208 break;
3209 }
anthonyafa3dfc2012-03-03 11:31:30 +00003210 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003211 {
anthony7bcfe7f2012-03-30 14:01:22 +00003212 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003213 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003214 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3215 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003216 break;
3217 }
anthonyafa3dfc2012-03-03 11:31:30 +00003218 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003219 {
anthony7bcfe7f2012-03-30 14:01:22 +00003220 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003221 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003222 if (strchr(arg1,'>') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003223 if (_image->columns <= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003224 break;
anthonyfd706f92012-01-19 04:22:02 +00003225 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003226 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003227 break;
anthonyfd706f92012-01-19 04:22:02 +00003228 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003229 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003230 break;
3231 }
anthonyebb73a22012-03-22 14:25:52 +00003232 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003233 }
3234 case 's':
3235 {
anthonyafa3dfc2012-03-03 11:31:30 +00003236 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003237 {
anthonyfe1aa782012-03-24 13:43:04 +00003238 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003239 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003240 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003241 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3242 new_image=SampleImage(_image,geometry.width,geometry.height,
3243 _exception);
anthony805a2d42011-09-25 08:25:12 +00003244 break;
3245 }
anthonyafa3dfc2012-03-03 11:31:30 +00003246 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003247 {
anthonyfe1aa782012-03-24 13:43:04 +00003248 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003249 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003250 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003251 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3252 new_image=ScaleImage(_image,geometry.width,geometry.height,
3253 _exception);
anthony805a2d42011-09-25 08:25:12 +00003254 break;
3255 }
anthonyf42014d2012-03-25 09:53:06 +00003256 if (LocaleCompare("segment",option+1) == 0)
3257 {
anthony7bcfe7f2012-03-30 14:01:22 +00003258 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003259 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3260 flags=ParseGeometry(arg1,&geometry_info);
3261 if ((flags & SigmaValue) == 0)
3262 geometry_info.sigma=1.0;
3263 (void) SegmentImage(_image,_image->colorspace,
3264 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3265 _exception);
3266 break;
3267 }
anthonyafa3dfc2012-03-03 11:31:30 +00003268 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003269 {
anthony7bcfe7f2012-03-30 14:01:22 +00003270 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003271 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003272 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003273 if ((flags & PercentValue) != 0)
3274 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003275 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003276 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003277 break;
3278 }
anthonyafa3dfc2012-03-03 11:31:30 +00003279 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003280 {
anthony31f1bf72012-01-30 12:37:22 +00003281 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003282 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003283 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003284 break;
3285 }
anthonyafa3dfc2012-03-03 11:31:30 +00003286 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003287 {
anthony7bcfe7f2012-03-30 14:01:22 +00003288 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003289 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3290 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3291 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003292 break;
3293 }
anthonyafa3dfc2012-03-03 11:31:30 +00003294 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003295 {
3296 char
3297 *value;
3298
anthonyf42014d2012-03-25 09:53:06 +00003299 if (IfPlusOp) {
anthonyfd706f92012-01-19 04:22:02 +00003300 if (LocaleNCompare(arg1,"registry:",9) == 0)
3301 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003302 else
anthony31f1bf72012-01-30 12:37:22 +00003303 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003304 {
anthony92c93bd2012-03-19 14:02:47 +00003305 (void) DeleteImageOption(_image_info,arg1+7);
3306 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003307 }
3308 else
anthony92c93bd2012-03-19 14:02:47 +00003309 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003310 break;
3311 }
anthonyf42014d2012-03-25 09:53:06 +00003312 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003313 if (value == (char *) NULL)
3314 break;
anthonyfd706f92012-01-19 04:22:02 +00003315 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003316 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003317 else
anthonyfd706f92012-01-19 04:22:02 +00003318 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003319 {
anthony92c93bd2012-03-19 14:02:47 +00003320 (void) SetImageOption(_image_info,arg1+7,value);
3321 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003322 }
3323 else
anthony92c93bd2012-03-19 14:02:47 +00003324 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003325 value=DestroyString(value);
3326 break;
3327 }
anthonyafa3dfc2012-03-03 11:31:30 +00003328 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003329 {
anthony7bcfe7f2012-03-30 14:01:22 +00003330 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003331 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003332 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003333 if ((flags & SigmaValue) == 0)
3334 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003335 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3336 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003337 break;
3338 }
anthonyafa3dfc2012-03-03 11:31:30 +00003339 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003340 {
anthony7bcfe7f2012-03-30 14:01:22 +00003341 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003342 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003343 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003344 if ((flags & SigmaValue) == 0)
3345 geometry_info.sigma=1.0;
3346 if ((flags & XiValue) == 0)
3347 geometry_info.xi=4.0;
3348 if ((flags & PsiValue) == 0)
3349 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003350 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3351 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3352 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003353 break;
3354 }
anthonyafa3dfc2012-03-03 11:31:30 +00003355 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003356 {
anthony7bcfe7f2012-03-30 14:01:22 +00003357 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003358 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003359 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003360 if ((flags & SigmaValue) == 0)
3361 geometry_info.sigma=1.0;
3362 if ((flags & XiValue) == 0)
3363 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003364 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3365 _exception);
anthony805a2d42011-09-25 08:25:12 +00003366 break;
3367 }
anthonyafa3dfc2012-03-03 11:31:30 +00003368 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003369 {
anthony7bcfe7f2012-03-30 14:01:22 +00003370 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003371 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003372 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3373 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003374 break;
3375 }
anthonyafa3dfc2012-03-03 11:31:30 +00003376 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003377 {
anthony7bcfe7f2012-03-30 14:01:22 +00003378 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003379 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003380 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003381 if ((flags & SigmaValue) == 0)
3382 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003383 new_image=ShearImage(_image,geometry_info.rho,
3384 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003385 break;
3386 }
anthonyafa3dfc2012-03-03 11:31:30 +00003387 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003388 {
anthony7bcfe7f2012-03-30 14:01:22 +00003389 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003390 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003391 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003392 if ((flags & SigmaValue) == 0)
3393 geometry_info.sigma=(double) QuantumRange/2.0;
3394 if ((flags & PercentValue) != 0)
3395 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3396 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003397 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003398 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003399 _exception);
anthony805a2d42011-09-25 08:25:12 +00003400 break;
3401 }
anthonyafa3dfc2012-03-03 11:31:30 +00003402 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003403 {
anthony7bcfe7f2012-03-30 14:01:22 +00003404 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003405 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003406 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003407 if ((flags & SigmaValue) == 0)
3408 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003409 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003410 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003411 break;
3412 }
anthonyafa3dfc2012-03-03 11:31:30 +00003413 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003414 {
anthony7bcfe7f2012-03-30 14:01:22 +00003415 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003416 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003417 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3418 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003419 break;
3420 }
anthonyafa3dfc2012-03-03 11:31:30 +00003421 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003422 {
anthony805a2d42011-09-25 08:25:12 +00003423 char
3424 *arguments;
3425
anthonyf42014d2012-03-25 09:53:06 +00003426 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3427 if ( parse < 0 )
3428 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3429 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003430 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003431 if (arguments == (char *) NULL)
anthonyf42014d2012-03-25 09:53:06 +00003432 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3433 new_image=SparseColorOption(_image,(SparseColorMethod)parse,
3434 arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003435 arguments=DestroyString(arguments);
3436 break;
3437 }
anthonyafa3dfc2012-03-03 11:31:30 +00003438 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003439 {
anthony7bcfe7f2012-03-30 14:01:22 +00003440 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003441 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003442 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3443 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003444 break;
3445 }
anthonyafa3dfc2012-03-03 11:31:30 +00003446 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003447 {
anthony7bcfe7f2012-03-30 14:01:22 +00003448 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003449 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003450 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003451 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3452 _exception);
anthony805a2d42011-09-25 08:25:12 +00003453 break;
3454 }
anthonyafa3dfc2012-03-03 11:31:30 +00003455 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003456 {
anthony7bc87992012-03-25 02:32:51 +00003457 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3458 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003459 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003460 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00003461 if (IfMagickFalse(IsGeometry(arg2)))
anthony7bc87992012-03-25 02:32:51 +00003462 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00003463 (void) ParseGeometry(arg2,&geometry_info);
anthony7bc87992012-03-25 02:32:51 +00003464 new_image=StatisticImage(_image,(StatisticType)parse,
3465 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3466 _exception);
anthony805a2d42011-09-25 08:25:12 +00003467 break;
3468 }
anthonyafa3dfc2012-03-03 11:31:30 +00003469 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003470 {
anthony92c93bd2012-03-19 14:02:47 +00003471 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003472 break;
3473 }
anthonyafa3dfc2012-03-03 11:31:30 +00003474 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003475 {
anthony7bcfe7f2012-03-30 14:01:22 +00003476 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003477 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003478 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003479 new_image=SwirlImage(_image,geometry_info.rho,
3480 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003481 break;
3482 }
anthonyebb73a22012-03-22 14:25:52 +00003483 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003484 }
3485 case 't':
3486 {
anthonyafa3dfc2012-03-03 11:31:30 +00003487 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003488 {
3489 double
3490 threshold;
3491
anthony52bef752012-03-27 13:54:47 +00003492 threshold=(double) QuantumRange/2;
3493 if (normal_op) {
anthony7bcfe7f2012-03-30 14:01:22 +00003494 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003495 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003496 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003497 }
anthony92c93bd2012-03-19 14:02:47 +00003498 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003499 break;
3500 }
anthonyafa3dfc2012-03-03 11:31:30 +00003501 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003502 {
anthony7bcfe7f2012-03-30 14:01:22 +00003503 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003504 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003505 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3506 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3507 _exception);
anthony805a2d42011-09-25 08:25:12 +00003508 break;
3509 }
anthonyafa3dfc2012-03-03 11:31:30 +00003510 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003511 {
anthony7bcfe7f2012-03-30 14:01:22 +00003512 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003513 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003514 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003515 break;
3516 }
anthonyafa3dfc2012-03-03 11:31:30 +00003517 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003518 {
anthonya3ef4ed2012-03-17 06:52:53 +00003519 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony52bef752012-03-27 13:54:47 +00003520 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003521 break;
3522 }
anthonyafa3dfc2012-03-03 11:31:30 +00003523 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003524 {
3525 PixelInfo
3526 target;
3527
anthony92c93bd2012-03-19 14:02:47 +00003528 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3529 (void) TransparentPaintImage(_image,&target,(Quantum)
3530 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003531 break;
3532 }
anthonyafa3dfc2012-03-03 11:31:30 +00003533 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003534 {
anthony92c93bd2012-03-19 14:02:47 +00003535 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003536 break;
3537 }
anthonyafa3dfc2012-03-03 11:31:30 +00003538 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003539 {
anthony92c93bd2012-03-19 14:02:47 +00003540 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003541 break;
3542 }
anthonyafa3dfc2012-03-03 11:31:30 +00003543 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003544 {
anthony92c93bd2012-03-19 14:02:47 +00003545 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003546 break;
3547 }
anthonyafa3dfc2012-03-03 11:31:30 +00003548 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003549 {
anthonyab3a50c2011-10-27 11:48:57 +00003550 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003551 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003552 break;
3553 }
anthonyebb73a22012-03-22 14:25:52 +00003554 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003555 }
3556 case 'u':
3557 {
anthonyafa3dfc2012-03-03 11:31:30 +00003558 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003559 {
anthony52bef752012-03-27 13:54:47 +00003560 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3561 Option is not documented, bt appears to be for "identify".
3562 We may need a identify specific verbose!
3563 */
3564 if (plus_alt_op) {
anthony92c93bd2012-03-19 14:02:47 +00003565 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003566 break;
3567 }
anthony92c93bd2012-03-19 14:02:47 +00003568 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3569 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003570 break;
3571 }
anthonyafa3dfc2012-03-03 11:31:30 +00003572 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003573 {
anthony92c93bd2012-03-19 14:02:47 +00003574 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003575 break;
3576 }
anthonyafa3dfc2012-03-03 11:31:30 +00003577 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003578 {
anthony7bcfe7f2012-03-30 14:01:22 +00003579 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003580 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003581 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003582 if ((flags & SigmaValue) == 0)
3583 geometry_info.sigma=1.0;
3584 if ((flags & XiValue) == 0)
3585 geometry_info.xi=1.0;
3586 if ((flags & PsiValue) == 0)
3587 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003588 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3589 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003590 break;
3591 }
anthonyebb73a22012-03-22 14:25:52 +00003592 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003593 }
3594 case 'v':
3595 {
anthonyafa3dfc2012-03-03 11:31:30 +00003596 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003597 {
anthonyafa3dfc2012-03-03 11:31:30 +00003598 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003599 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003600 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003601 */
anthony92c93bd2012-03-19 14:02:47 +00003602 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003603 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003604 break;
3605 }
anthonyafa3dfc2012-03-03 11:31:30 +00003606 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003607 {
anthony7bcfe7f2012-03-30 14:01:22 +00003608 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003609 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003610 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003611 if ((flags & SigmaValue) == 0)
3612 geometry_info.sigma=1.0;
3613 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003614 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003615 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003616 geometry_info.psi=0.1*_image->rows;
3617 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003618 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3619 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003620 break;
3621 }
anthonyebb73a22012-03-22 14:25:52 +00003622 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003623 }
3624 case 'w':
3625 {
anthonyafa3dfc2012-03-03 11:31:30 +00003626 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003627 {
anthony7bcfe7f2012-03-30 14:01:22 +00003628 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003629 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003630 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003631 if ((flags & SigmaValue) == 0)
3632 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003633 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3634 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003635 break;
3636 }
anthonyafa3dfc2012-03-03 11:31:30 +00003637 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003638 {
anthony7bcfe7f2012-03-30 14:01:22 +00003639 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003640 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003641 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003642 break;
3643 }
anthonyebb73a22012-03-22 14:25:52 +00003644 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003645 }
3646 default:
anthonyebb73a22012-03-22 14:25:52 +00003647 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003648 }
3649 /*
3650 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003651 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003652 */
3653 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003654 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003655
anthony31f1bf72012-01-30 12:37:22 +00003656 return;
anthony92c93bd2012-03-19 14:02:47 +00003657#undef _image_info
3658#undef _draw_info
3659#undef _quantize_info
3660#undef _image
3661#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003662#undef IfNormalOp
3663#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003664#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003665#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003666}
anthonyfd706f92012-01-19 04:22:02 +00003667
anthony43f425d2012-02-26 12:58:58 +00003668WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003669 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003670{
3671 size_t
anthony43f425d2012-02-26 12:58:58 +00003672 n,
anthony31f1bf72012-01-30 12:37:22 +00003673 i;
3674
anthony43f425d2012-02-26 12:58:58 +00003675 assert(cli_wand != (MagickCLI *) NULL);
3676 assert(cli_wand->signature == WandSignature);
3677 assert(cli_wand->wand.signature == WandSignature);
3678 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003679 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003680 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003681
anthonyafa3dfc2012-03-03 11:31:30 +00003682#if !USE_WAND_METHODS
3683 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003684 i=0;
anthony43f425d2012-02-26 12:58:58 +00003685 n=GetImageListLength(cli_wand->wand.images);
3686 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003687 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003688 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003689 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003690 if ( cli_wand->wand.images->next == (Image *) NULL )
3691 break;
3692 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003693 }
anthony43f425d2012-02-26 12:58:58 +00003694 assert( i == n );
3695 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003696#else
3697 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003698 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
anthonyafa3dfc2012-03-03 11:31:30 +00003699 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3700 MagickResetIterator(&cli_wand->wand);
3701#endif
anthony31f1bf72012-01-30 12:37:22 +00003702 return;
anthony805a2d42011-09-25 08:25:12 +00003703}
3704
3705/*
3706%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3707% %
3708% %
3709% %
anthony43f425d2012-02-26 12:58:58 +00003710+ 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 +00003711% %
3712% %
3713% %
3714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3715%
anthony43f425d2012-02-26 12:58:58 +00003716% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003717% entire image list as a whole. The result is often a complete replacment
3718% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003719%
3720% The format of the MogrifyImage method is:
3721%
anthony43f425d2012-02-26 12:58:58 +00003722% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003723% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003724%
3725% A description of each parameter follows:
3726%
anthony43f425d2012-02-26 12:58:58 +00003727% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003728%
anthony36a8c2c2012-02-10 00:08:44 +00003729% o option: The option string for the operation
3730%
anthony31f1bf72012-01-30 12:37:22 +00003731% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003732%
anthonyfe1aa782012-03-24 13:43:04 +00003733% NOTE: only "limit" uses two arguments.
anthony8b10b462012-02-08 12:32:44 +00003734%
3735% Example usage...
3736%
anthonyafa3dfc2012-03-03 11:31:30 +00003737% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3738% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003739%
anthony24aa8822012-03-11 00:56:06 +00003740% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003741%
anthony43f425d2012-02-26 12:58:58 +00003742% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003743% argc,argv
3744% i=index in argv
3745%
anthony2052d272012-02-28 12:48:29 +00003746% option_info = GetCommandOptionInfo(argv[i]);
3747% count=option_info->type;
3748% option_type=option_info->flags;
3749%
3750% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003751% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003752% count>=1 ? argv[i+1] : (char *)NULL,
3753% count>=2 ? argv[i+2] : (char *)NULL );
3754% i += count+1;
3755%
anthony805a2d42011-09-25 08:25:12 +00003756*/
anthony43f425d2012-02-26 12:58:58 +00003757WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003758 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003759{
anthony2a0ec8c2012-03-24 04:35:56 +00003760 ssize_t
3761 parse;
3762
anthony31f1bf72012-01-30 12:37:22 +00003763 Image
3764 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003765
anthony2e4501b2012-03-30 04:41:54 +00003766#define _image_info (cli_wand->wand.image_info)
3767#define _images (cli_wand->wand.images)
3768#define _exception (cli_wand->wand.exception)
3769#define _draw_info (cli_wand->draw_info)
3770#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003771#define IfNormalOp (*option=='-')
3772#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00003773#define normal_op IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003774
anthony43f425d2012-02-26 12:58:58 +00003775 assert(cli_wand != (MagickCLI *) NULL);
3776 assert(cli_wand->signature == WandSignature);
3777 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003778 assert(_images != (Image *) NULL); /* _images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003779 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003780 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003781
anthony92c93bd2012-03-19 14:02:47 +00003782 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003783
3784 new_images=NewImageList();
3785
anthonyafa3dfc2012-03-03 11:31:30 +00003786 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003787 {
3788 case 'a':
3789 {
anthonyafa3dfc2012-03-03 11:31:30 +00003790 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003791 {
anthony92c93bd2012-03-19 14:02:47 +00003792 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003793 break;
3794 }
anthonyafa3dfc2012-03-03 11:31:30 +00003795 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003796 {
anthony31f1bf72012-01-30 12:37:22 +00003797 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003798 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003799 break;
3800 }
anthonyebb73a22012-03-22 14:25:52 +00003801 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003802 }
3803 case 'c':
3804 {
cristy5f257b22012-03-07 00:27:29 +00003805 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003806 {
anthony92c93bd2012-03-19 14:02:47 +00003807 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003808 break;
3809 }
anthonyafa3dfc2012-03-03 11:31:30 +00003810 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003811 {
anthony805a2d42011-09-25 08:25:12 +00003812 Image
anthony31f1bf72012-01-30 12:37:22 +00003813 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003814
anthonyafa3dfc2012-03-03 11:31:30 +00003815 /* FUTURE - make this a compose option, and thus can be used
3816 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003817 _images.
cristy87c02f42012-02-24 00:19:10 +00003818 */
anthony92c93bd2012-03-19 14:02:47 +00003819 new_images=RemoveFirstImageFromList(&_images);
3820 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003821 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003822 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003823 break;
anthony92c93bd2012-03-19 14:02:47 +00003824 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003825 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003826 break;
3827 }
anthonyafa3dfc2012-03-03 11:31:30 +00003828 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003829 {
anthony92c93bd2012-03-19 14:02:47 +00003830 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003831 break;
3832 }
anthonyafa3dfc2012-03-03 11:31:30 +00003833 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003834 {
anthony43f425d2012-02-26 12:58:58 +00003835 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003836 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003837 break;
3838 }
anthonyafa3dfc2012-03-03 11:31:30 +00003839 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003840 {
cristyfeb3e962012-03-29 17:25:55 +00003841 CompositeOperator
3842 compose;
3843
3844 const char*
3845 value;
3846
3847 MagickBooleanType
3848 clip_to_self;
3849
anthony805a2d42011-09-25 08:25:12 +00003850 Image
3851 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003852 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003853
3854 RectangleInfo
3855 geometry;
3856
anthony7bcfe7f2012-03-30 14:01:22 +00003857 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003858 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00003859 if (value != (const char *) NULL)
3860 compose=(CompositeOperator) ParseCommandOption(
3861 MagickComposeOptions,MagickFalse,value);
3862 else
anthony31f1bf72012-01-30 12:37:22 +00003863 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003864
anthony7bcfe7f2012-03-30 14:01:22 +00003865 /* Get "clip-to-self" expert setting (false is normal) */
anthony2e4501b2012-03-30 04:41:54 +00003866 clip_to_self=IsStringTrue(GetImageOption(_image_info,
anthony7bcfe7f2012-03-30 14:01:22 +00003867 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003868 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003869 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003870 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003871 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003872 }
3873
anthony92c93bd2012-03-19 14:02:47 +00003874 new_images=RemoveFirstImageFromList(&_images);
3875 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003876 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003877 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003878
anthony31f1bf72012-01-30 12:37:22 +00003879 /* FUTURE - this should not be here! - should be part of -geometry */
3880 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003881 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003882
anthony31f1bf72012-01-30 12:37:22 +00003883 SetGeometry(source_image,&geometry);
3884 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3885 GravityAdjustGeometry(new_images->columns,new_images->rows,
3886 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003887
anthony92c93bd2012-03-19 14:02:47 +00003888 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003889 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003890 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003891 if ((compose == DisplaceCompositeOp) ||
anthony7bcfe7f2012-03-30 14:01:22 +00003892 (compose == DistortCompositeOp)) {
3893 /* Merge Y displacement into X displace/distort map. */
3894 (void) CompositeImage(source_image,mask_image,
3895 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3896 mask_image=DestroyImage(mask_image);
3897 }
3898 else {
3899 /* Set a blending mask for the composition. */
3900 (void) NegateImage(mask_image,MagickFalse,_exception);
3901 (void) SetImageMask(new_images,mask_image,_exception);
3902 mask_image=DestroyImage(mask_image);
3903 }
anthony805a2d42011-09-25 08:25:12 +00003904 }
cristyfeb3e962012-03-29 17:25:55 +00003905 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3906 geometry.x,geometry.y,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003907 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003908 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003909 break;
3910 }
anthonyebb73a22012-03-22 14:25:52 +00003911 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003912 }
3913 case 'd':
3914 {
anthonyafa3dfc2012-03-03 11:31:30 +00003915 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003916 {
anthony31f1bf72012-01-30 12:37:22 +00003917 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003918 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003919 break;
3920 }
anthonyafa3dfc2012-03-03 11:31:30 +00003921 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003922 {
anthonyafa3dfc2012-03-03 11:31:30 +00003923 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003924 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003925 else
anthony92c93bd2012-03-19 14:02:47 +00003926 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003927 break;
3928 }
anthonyafa3dfc2012-03-03 11:31:30 +00003929 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003930 {
anthonyafa3dfc2012-03-03 11:31:30 +00003931 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003932 {
3933 const char
3934 *p;
3935
3936 size_t
3937 number_duplicates;
3938
anthony7bcfe7f2012-03-30 14:01:22 +00003939 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003940 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3941 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003942 number_duplicates=(size_t) StringToLong(arg1);
3943 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003944 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003945 new_images=DuplicateImages(_images,number_duplicates,"-1",
3946 _exception);
anthony805a2d42011-09-25 08:25:12 +00003947 else
anthony92c93bd2012-03-19 14:02:47 +00003948 new_images=DuplicateImages(_images,number_duplicates,p,
3949 _exception);
anthony805a2d42011-09-25 08:25:12 +00003950 }
anthonyafa3dfc2012-03-03 11:31:30 +00003951 else
anthony92c93bd2012-03-19 14:02:47 +00003952 new_images=DuplicateImages(_images,1,"-1",_exception);
3953 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003954 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003955 break;
3956 }
anthonyebb73a22012-03-22 14:25:52 +00003957 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003958 }
3959 case 'e':
3960 {
anthonyafa3dfc2012-03-03 11:31:30 +00003961 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003962 {
anthony2a0ec8c2012-03-24 04:35:56 +00003963 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3964 if ( parse < 0 )
3965 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3966 option,arg1);
3967 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3968 _exception);
anthony805a2d42011-09-25 08:25:12 +00003969 break;
3970 }
anthonyebb73a22012-03-22 14:25:52 +00003971 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003972 }
3973 case 'f':
3974 {
anthonyafa3dfc2012-03-03 11:31:30 +00003975 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003976 {
anthony92c93bd2012-03-19 14:02:47 +00003977 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003978 break;
3979 }
anthonyafa3dfc2012-03-03 11:31:30 +00003980 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003981 {
anthony319dac62012-03-06 04:12:44 +00003982 /* REDIRECTED to use -layers flatten instead */
anthony2e4501b2012-03-30 04:41:54 +00003983 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003984 break;
3985 }
anthonyafa3dfc2012-03-03 11:31:30 +00003986 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003987 {
anthony92c93bd2012-03-19 14:02:47 +00003988 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003989 break;
3990 }
anthonyebb73a22012-03-22 14:25:52 +00003991 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003992 }
3993 case 'h':
3994 {
anthonyafa3dfc2012-03-03 11:31:30 +00003995 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003996 {
anthony31f1bf72012-01-30 12:37:22 +00003997 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003998 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003999 */
anthony805a2d42011-09-25 08:25:12 +00004000 Image
anthony31f1bf72012-01-30 12:37:22 +00004001 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00004002
anthony92c93bd2012-03-19 14:02:47 +00004003 new_images=RemoveFirstImageFromList(&_images);
4004 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004005 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004006 break;
anthony92c93bd2012-03-19 14:02:47 +00004007 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00004008 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00004009 break;
4010 }
anthonyebb73a22012-03-22 14:25:52 +00004011 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004012 }
4013 case 'i':
4014 {
anthonyafa3dfc2012-03-03 11:31:30 +00004015 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004016 {
4017 Image
anthony805a2d42011-09-25 08:25:12 +00004018 *magnitude_image,
4019 *phase_image;
4020
anthony92c93bd2012-03-19 14:02:47 +00004021 magnitude_image=RemoveFirstImageFromList(&_images);
4022 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00004023 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00004024 if (phase_image == (Image *) NULL)
4025 break;
4026 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00004027 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004028 magnitude_image=DestroyImage(magnitude_image);
4029 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00004030 break;
4031 }
anthonyafa3dfc2012-03-03 11:31:30 +00004032 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004033 {
4034 Image
anthony31f1bf72012-01-30 12:37:22 +00004035 *insert_image,
4036 *index_image;
4037
4038 ssize_t
4039 index;
anthony805a2d42011-09-25 08:25:12 +00004040
anthony7bcfe7f2012-03-30 14:01:22 +00004041 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00004042 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004043 index=0;
anthony92c93bd2012-03-19 14:02:47 +00004044 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00004045 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00004046 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00004047 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00004048 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00004049 PrependImageToList(&_images,insert_image);
4050 else if (index == (ssize_t) GetImageListLength(_images))
4051 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00004052 else
anthony43f425d2012-02-26 12:58:58 +00004053 {
anthony92c93bd2012-03-19 14:02:47 +00004054 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00004055 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00004056 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004057 InsertImageInList(&index_image,insert_image);
4058 }
anthony92c93bd2012-03-19 14:02:47 +00004059 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00004060 break;
4061 }
anthonyebb73a22012-03-22 14:25:52 +00004062 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004063 }
4064 case 'l':
4065 {
anthonyafa3dfc2012-03-03 11:31:30 +00004066 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004067 {
anthonyfe1aa782012-03-24 13:43:04 +00004068 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4069 if ( parse < 0 )
4070 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4071 option,arg1);
4072 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00004073 {
4074 case CoalesceLayer:
4075 {
anthony92c93bd2012-03-19 14:02:47 +00004076 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004077 break;
4078 }
4079 case CompareAnyLayer:
4080 case CompareClearLayer:
4081 case CompareOverlayLayer:
4082 default:
4083 {
anthonyfe1aa782012-03-24 13:43:04 +00004084 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
4085 _exception);
anthony805a2d42011-09-25 08:25:12 +00004086 break;
4087 }
4088 case MergeLayer:
4089 case FlattenLayer:
4090 case MosaicLayer:
4091 case TrimBoundsLayer:
4092 {
anthonyfe1aa782012-03-24 13:43:04 +00004093 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
4094 _exception);
anthony805a2d42011-09-25 08:25:12 +00004095 break;
4096 }
4097 case DisposeLayer:
4098 {
anthony92c93bd2012-03-19 14:02:47 +00004099 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004100 break;
4101 }
4102 case OptimizeImageLayer:
4103 {
anthony92c93bd2012-03-19 14:02:47 +00004104 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004105 break;
4106 }
4107 case OptimizePlusLayer:
4108 {
anthony92c93bd2012-03-19 14:02:47 +00004109 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004110 break;
4111 }
4112 case OptimizeTransLayer:
4113 {
anthony92c93bd2012-03-19 14:02:47 +00004114 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004115 break;
4116 }
4117 case RemoveDupsLayer:
4118 {
anthony92c93bd2012-03-19 14:02:47 +00004119 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004120 break;
4121 }
4122 case RemoveZeroLayer:
4123 {
anthony92c93bd2012-03-19 14:02:47 +00004124 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004125 break;
4126 }
4127 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004128 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004129 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004130 if (new_images == (Image *) NULL)
4131 break;
anthony92c93bd2012-03-19 14:02:47 +00004132 _images=DestroyImageList(_images);
4133 _images=OptimizeImageLayers(new_images,_exception);
4134 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004135 break;
4136 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004137 OptimizeImageTransparency(_images,_exception);
4138 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4139 _exception);
anthony805a2d42011-09-25 08:25:12 +00004140 break;
4141 }
4142 case CompositeLayer:
4143 {
anthony805a2d42011-09-25 08:25:12 +00004144 Image
4145 *source;
4146
4147 RectangleInfo
4148 geometry;
4149
anthony31f1bf72012-01-30 12:37:22 +00004150 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004151 compose;
4152
4153 const char*
4154 value;
4155
anthony92c93bd2012-03-19 14:02:47 +00004156 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004157 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004158 if (value != (const char *) NULL)
4159 compose=(CompositeOperator) ParseCommandOption(
4160 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004161
anthony31f1bf72012-01-30 12:37:22 +00004162 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004163 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004164 while (source != (Image *) NULL)
4165 {
4166 source=GetNextImageInList(source);
4167 if ((source != (Image *) NULL) &&
4168 (LocaleCompare(source->magick,"NULL") == 0))
4169 break;
4170 }
4171 if (source != (Image *) NULL)
4172 {
4173 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4174 (GetNextImageInList(source) == (Image *) NULL))
4175 source=(Image *) NULL;
4176 else
anthony31f1bf72012-01-30 12:37:22 +00004177 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004178 source=SplitImageList(source->previous);
4179 DeleteImageFromList(&source);
4180 }
4181 }
4182 if (source == (Image *) NULL)
4183 {
anthony92c93bd2012-03-19 14:02:47 +00004184 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004185 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004186 break;
4187 }
anthony31f1bf72012-01-30 12:37:22 +00004188 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004189 SetGeometry(_images,&geometry);
4190 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004191 geometry.width=source->page.width != 0 ?
4192 source->page.width : source->columns;
4193 geometry.height=source->page.height != 0 ?
4194 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004195 GravityAdjustGeometry(_images->page.width != 0 ?
4196 _images->page.width : _images->columns,
4197 _images->page.height != 0 ? _images->page.height :
4198 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004199
anthony31f1bf72012-01-30 12:37:22 +00004200 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004201 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4202 _exception);
anthony805a2d42011-09-25 08:25:12 +00004203 source=DestroyImageList(source);
4204 break;
4205 }
4206 }
anthony805a2d42011-09-25 08:25:12 +00004207 break;
4208 }
anthonyafa3dfc2012-03-03 11:31:30 +00004209 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00004210 {
4211 MagickSizeType
4212 limit;
4213
anthony72feaa62012-01-17 06:46:23 +00004214 limit=MagickResourceInfinity;
anthonyfe1aa782012-03-24 13:43:04 +00004215 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
4216 if ( parse < 0 )
4217 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
4218 option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004219 if (LocaleCompare("unlimited",arg2) != 0)
4220 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthonyfe1aa782012-03-24 13:43:04 +00004221 (void) SetMagickResourceLimit((ResourceType)parse,limit);
anthony72feaa62012-01-17 06:46:23 +00004222 break;
4223 }
anthonyebb73a22012-03-22 14:25:52 +00004224 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004225 }
4226 case 'm':
4227 {
anthonyafa3dfc2012-03-03 11:31:30 +00004228 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004229 {
anthony31f1bf72012-01-30 12:37:22 +00004230 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004231 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004232 break;
4233 }
anthonyafa3dfc2012-03-03 11:31:30 +00004234 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004235 {
4236 Image
4237 *morph_image;
4238
anthony7bcfe7f2012-03-30 14:01:22 +00004239 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004240 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004241 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4242 _exception);
anthony805a2d42011-09-25 08:25:12 +00004243 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004244 break;
anthony92c93bd2012-03-19 14:02:47 +00004245 _images=DestroyImageList(_images);
4246 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004247 break;
4248 }
anthonyafa3dfc2012-03-03 11:31:30 +00004249 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004250 {
anthony319dac62012-03-06 04:12:44 +00004251 /* REDIRECTED to use -layers mosaic instead */
anthony2e4501b2012-03-30 04:41:54 +00004252 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004253 break;
4254 }
anthonyebb73a22012-03-22 14:25:52 +00004255 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004256 }
4257 case 'p':
4258 {
anthonyafa3dfc2012-03-03 11:31:30 +00004259 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004260 {
4261 char
4262 *string;
4263
anthony92c93bd2012-03-19 14:02:47 +00004264 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004265 if (string == (char *) NULL)
4266 break;
4267 (void) FormatLocaleFile(stdout,"%s",string);
4268 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004269 break;
anthony805a2d42011-09-25 08:25:12 +00004270 }
anthonyafa3dfc2012-03-03 11:31:30 +00004271 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004272 {
4273 char
4274 **arguments;
4275
4276 int
4277 j,
4278 number_arguments;
4279
anthony31f1bf72012-01-30 12:37:22 +00004280 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004281 if (arguments == (char **) NULL)
4282 break;
anthony31f1bf72012-01-30 12:37:22 +00004283 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004284 {
4285 char
4286 breaker,
4287 quote,
4288 *token;
4289
4290 const char
4291 *arguments;
4292
4293 int
4294 next,
4295 status;
4296
4297 size_t
4298 length;
4299
4300 TokenInfo
4301 *token_info;
4302
4303 /*
anthony24aa8822012-03-11 00:56:06 +00004304 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004305 */
anthony31f1bf72012-01-30 12:37:22 +00004306 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004307 token=(char *) NULL;
4308 if (~length >= (MaxTextExtent-1))
4309 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4310 sizeof(*token));
4311 if (token == (char *) NULL)
4312 break;
4313 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004314 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004315 token_info=AcquireTokenInfo();
4316 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4317 "\"",'\0',&breaker,&next,&quote);
4318 token_info=DestroyTokenInfo(token_info);
4319 if (status == 0)
4320 {
4321 const char
4322 *argv;
4323
4324 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004325 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4326 _exception);
anthony805a2d42011-09-25 08:25:12 +00004327 }
4328 token=DestroyString(token);
4329 break;
4330 }
4331 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004332 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4333 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004334 for (j=0; j < number_arguments; j++)
4335 arguments[j]=DestroyString(arguments[j]);
4336 arguments=(char **) RelinquishMagickMemory(arguments);
4337 break;
4338 }
anthonyebb73a22012-03-22 14:25:52 +00004339 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004340 }
4341 case 'r':
4342 {
anthonyafa3dfc2012-03-03 11:31:30 +00004343 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004344 {
anthony92c93bd2012-03-19 14:02:47 +00004345 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004346 break;
4347 }
anthonyafa3dfc2012-03-03 11:31:30 +00004348 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004349 {
anthony92c93bd2012-03-19 14:02:47 +00004350 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004351 break;
4352 }
anthonyebb73a22012-03-22 14:25:52 +00004353 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004354 }
4355 case 's':
4356 {
anthonyafa3dfc2012-03-03 11:31:30 +00004357 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004358 {
4359 Image
4360 *smush_image;
4361
4362 ssize_t
4363 offset;
4364
anthony7bcfe7f2012-03-30 14:01:22 +00004365 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004366 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004367 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004368 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004369 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004370 break;
anthony92c93bd2012-03-19 14:02:47 +00004371 _images=DestroyImageList(_images);
4372 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004373 break;
4374 }
anthony0ea037a2012-04-03 12:14:39 +00004375 if (LocaleCompare("swap",option+1) == 0) {
4376 Image
4377 *p,
4378 *q,
4379 *swap;
anthony805a2d42011-09-25 08:25:12 +00004380
anthony0ea037a2012-04-03 12:14:39 +00004381 ssize_t
4382 index,
4383 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004384
anthony0ea037a2012-04-03 12:14:39 +00004385 index=-1;
4386 swap_index=-2;
4387 if (IfNormalOp) {
4388 GeometryInfo
4389 geometry_info;
4390
4391 MagickStatusType
4392 flags;
4393
4394 swap_index=(-1);
anthony7bcfe7f2012-03-30 14:01:22 +00004395 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004396 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004397 flags=ParseGeometry(arg1,&geometry_info);
4398 index=(ssize_t) geometry_info.rho;
4399 if ((flags & SigmaValue) != 0)
4400 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004401 }
anthony0ea037a2012-04-03 12:14:39 +00004402 p=GetImageFromList(_images,index);
4403 q=GetImageFromList(_images,swap_index);
4404 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4405 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
4406 if (p == q)
4407 break; /* same image - no-op - not an error */
4408 swap=CloneImage(p,0,0,MagickTrue,_exception);
4409 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4410 ReplaceImageInList(&q,swap);
4411 _images=GetFirstImageInList(q);
4412 break;
4413 }
anthonyebb73a22012-03-22 14:25:52 +00004414 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004415 }
4416 case 'w':
4417 {
anthonyafa3dfc2012-03-03 11:31:30 +00004418 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004419 {
4420 char
4421 key[MaxTextExtent];
4422
4423 Image
4424 *write_images;
4425
4426 ImageInfo
4427 *write_info;
4428
anthony31f1bf72012-01-30 12:37:22 +00004429 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004430 (void) DeleteImageRegistry(key);
anthony92c93bd2012-03-19 14:02:47 +00004431 write_images=_images;
anthonyafa3dfc2012-03-03 11:31:30 +00004432 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00004433 write_images=CloneImageList(_images,_exception);
4434 write_info=CloneImageInfo(_image_info);
4435 (void) WriteImages(write_info,write_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004436 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004437 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004438 write_images=DestroyImageList(write_images);
4439 break;
4440 }
anthonyebb73a22012-03-22 14:25:52 +00004441 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004442 }
4443 default:
anthonyebb73a22012-03-22 14:25:52 +00004444 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004445 }
anthony31f1bf72012-01-30 12:37:22 +00004446 if (new_images == (Image *) NULL)
4447 return;
anthony805a2d42011-09-25 08:25:12 +00004448
anthony92c93bd2012-03-19 14:02:47 +00004449 if (_images != (Image *) NULL)
4450 _images=DestroyImageList(_images);
4451 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004452 return;
4453
anthony92c93bd2012-03-19 14:02:47 +00004454#undef _image_info
4455#undef _images
4456#undef _exception
4457#undef _draw_info
4458#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004459#undef IfNormalOp
4460#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004461#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004462}
anthony43f425d2012-02-26 12:58:58 +00004463
4464/*
4465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4466% %
4467% %
4468% %
4469+ C L I S p e c i a l O p e r a t i o n s %
4470% %
4471% %
4472% %
4473%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4474%
4475% CLISpecialOption() Applies operations that may involve empty image lists
4476% and or stacks of image lists or image_info settings.
4477%
anthonyafa3dfc2012-03-03 11:31:30 +00004478% The classic operators of this type is -read, and image stack operators,
4479% which can be applied to empty image lists.
4480%
4481% Note: unlike other Operators, these may involve other special 'option'
4482% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004483%
4484% The format of the CLISpecialOption method is:
4485%
4486% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004487% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004488%
4489% A description of each parameter follows:
4490%
4491% o cli_wand: the main CLI Wand to use.
4492%
4493% o option: The special option (with any switch char) to process
4494%
anthony24aa8822012-03-11 00:56:06 +00004495% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004496%
anthony2052d272012-02-28 12:48:29 +00004497% Example Usage...
4498%
anthonyce8dcb32012-03-21 13:20:31 +00004499% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004500%
anthony24aa8822012-03-11 00:56:06 +00004501% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004502%
4503% cli_wand
4504% argc,argv
4505% i=index in argv
4506%
4507% option_info = GetCommandOptionInfo(argv[i]);
4508% count=option_info->type;
4509% option_type=option_info->flags;
4510%
4511% if ( (option_type & SpecialOptionFlag) != 0 )
4512% CLISpecialOperator(cli_wand,argv[i],
4513% count>=1 ? argv[i+1] : (char *)NULL);
4514% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004515%
4516*/
4517
anthony43f425d2012-02-26 12:58:58 +00004518WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004519 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004520{
anthony92c93bd2012-03-19 14:02:47 +00004521#define _exception (cli_wand->wand.exception)
anthony43f425d2012-02-26 12:58:58 +00004522
4523 assert(cli_wand != (MagickCLI *) NULL);
4524 assert(cli_wand->signature == WandSignature);
4525 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +00004526 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00004527 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4528
anthony24aa8822012-03-11 00:56:06 +00004529 if(cli_wand->wand.images != (Image *)NULL)
4530 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
anthony92c93bd2012-03-19 14:02:47 +00004531 _exception);
anthony24aa8822012-03-11 00:56:06 +00004532
anthony52bef752012-03-27 13:54:47 +00004533 /*
4534 No-op options
4535 */
4536 if (LocaleCompare("noop",option+1) == 0)
4537 return;
4538 if (LocaleCompare("sans",option+1) == 0)
4539 return;
4540 if (LocaleCompare("sans0",option+1) == 0)
4541 return;
4542 if (LocaleCompare("sans2",option+1) == 0)
4543 return;
4544 /*
4545 Image Reading
4546 */
4547 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthony0ea037a2012-04-03 12:14:39 +00004548 ( LocaleCompare("--",option) == 0 ) ) {
4549 int
4550 argc;
4551 char
4552 **argv;
anthony52bef752012-03-27 13:54:47 +00004553
anthony0ea037a2012-04-03 12:14:39 +00004554 ssize_t
4555 i;
4556
4557 /* Expand the filename argument (meta-characters or "@filelist" ) */
4558 argc = 1;
4559 argv = &arg1;
4560 MagickBooleanType
4561 status=ExpandFilenames(&argc,&argv);
4562
4563 if (IfMagickFalse(status))
4564 CLIWandExceptArgReturn(ResourceLimitError,"MemoryAllocationFailed",
4565 option,GetExceptionMessage(errno));
4566
4567 /* loop over expanded list reading images */
4568 for (i=0; i<argc; i++) {
anthony52bef752012-03-27 13:54:47 +00004569#if !USE_WAND_METHODS
4570 Image *
4571 new_images;
anthony7bcfe7f2012-03-30 14:01:22 +00004572 if (IfMagickTrue(cli_wand->wand.image_info->ping))
anthony0ea037a2012-04-03 12:14:39 +00004573 new_images=PingImages(cli_wand->wand.image_info,argv[i],_exception);
anthony52bef752012-03-27 13:54:47 +00004574 else
anthony0ea037a2012-04-03 12:14:39 +00004575 new_images=ReadImages(cli_wand->wand.image_info,argv[i],_exception);
anthony52bef752012-03-27 13:54:47 +00004576 AppendImageToList(&cli_wand->wand.images, new_images);
4577#else
4578 /* read images using MagickWand method - no ping */
4579 /* This is not working! - it locks up in a CPU loop! */
4580 MagickSetLastIterator(&cli_wand->wand);
4581 MagickReadImage(&cli_wand->wand,arg1);
4582 MagickSetFirstIterator(&cli_wand->wand);
4583#endif
anthony52bef752012-03-27 13:54:47 +00004584 }
anthony0ea037a2012-04-03 12:14:39 +00004585 /* FUTURE: how do I free the expanded filename arguments??? */
4586
4587 return;
4588 }
anthony52bef752012-03-27 13:54:47 +00004589 /*
4590 Parenthesis and Brace operations
4591 */
anthonyce8dcb32012-03-21 13:20:31 +00004592 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
anthonyf42014d2012-03-25 09:53:06 +00004593 /* link image and setting stacks - option is itself saved on stack! */
anthonyce8dcb32012-03-21 13:20:31 +00004594 (void) SetImageOption(cli_wand->wand.image_info,option+1,
4595 *option == '-' ? "true" : (char *) NULL);
4596 return;
4597 }
4598 if (LocaleCompare("(",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004599 /* stack 'push' images */
4600 Stack
4601 *node;
4602
4603 size_t
4604 size;
4605
anthony43f425d2012-02-26 12:58:58 +00004606 size=0;
4607 node=cli_wand->image_list_stack;
4608 for ( ; node != (Stack *)NULL; node=node->next)
4609 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004610 if ( size >= MAX_STACK_DEPTH )
anthony92c93bd2012-03-19 14:02:47 +00004611 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004612 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4613 if (node == (Stack *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004614 CLIWandExceptionReturn(ResourceLimitFatalError,
4615 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004616 node->data = (void *)cli_wand->wand.images;
4617 cli_wand->wand.images = NewImageList();
4618 node->next = cli_wand->image_list_stack;
4619 cli_wand->image_list_stack = node;
4620
4621 /* handle respect-parenthesis */
anthony7bcfe7f2012-03-30 14:01:22 +00004622 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
anthony2e4501b2012-03-30 04:41:54 +00004623 "respect-parenthesis"))))
anthonyf42014d2012-03-25 09:53:06 +00004624 option="{"; /* fall-thru so as to push image settings too */
anthony43f425d2012-02-26 12:58:58 +00004625 else
4626 return;
4627 }
anthonyce8dcb32012-03-21 13:20:31 +00004628 if (LocaleCompare("{",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004629 /* stack 'push' of image_info settings */
4630 Stack
4631 *node;
4632
4633 size_t
4634 size;
4635
4636 size=0;
4637 node=cli_wand->image_info_stack;
4638 for ( ; node != (Stack *)NULL; node=node->next)
4639 size++;
anthony92c93bd2012-03-19 14:02:47 +00004640 if ( size >= MAX_STACK_DEPTH )
anthony4d4f2c72012-03-22 03:22:03 +00004641 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004642 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthony92c93bd2012-03-19 14:02:47 +00004643 if (node == (Stack *) NULL)
4644 CLIWandExceptionReturn(ResourceLimitFatalError,
4645 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004646
4647 node->data = (void *)cli_wand->wand.image_info;
4648 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004649 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
anthony92c93bd2012-03-19 14:02:47 +00004650 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4651 option);
anthonyafa3dfc2012-03-03 11:31:30 +00004652 cli_wand->wand.image_info = (ImageInfo *)node->data;
4653 node = (Stack *)RelinquishMagickMemory(node);
4654 return;
4655 }
anthony43f425d2012-02-26 12:58:58 +00004656
4657 node->next = cli_wand->image_info_stack;
4658 cli_wand->image_info_stack = node;
4659
4660 return;
4661 }
anthonyce8dcb32012-03-21 13:20:31 +00004662 if (LocaleCompare(")",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004663 /* pop images from stack */
4664 Stack
4665 *node;
4666
cristyaa2c16c2012-03-25 22:21:35 +00004667 node = (Stack *)cli_wand->image_list_stack;
anthony43f425d2012-02-26 12:58:58 +00004668 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004669 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004670 cli_wand->image_list_stack = node->next;
4671
4672 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4673 cli_wand->wand.images= (Image *)node->data;
4674 node = (Stack *)RelinquishMagickMemory(node);
4675
anthony4d4f2c72012-03-22 03:22:03 +00004676 /* handle respect-parenthesis - of the previous 'pushed' settings */
anthony43f425d2012-02-26 12:58:58 +00004677 node = cli_wand->image_info_stack;
4678 if ( node != (Stack *)NULL)
4679 {
anthony7bcfe7f2012-03-30 14:01:22 +00004680 if (IfMagickTrue(IsStringTrue(GetImageOption(
4681 cli_wand->wand.image_info,"respect-parenthesis"))))
anthonyf42014d2012-03-25 09:53:06 +00004682 option="}"; /* fall-thru so as to pop image settings too */
anthony43f425d2012-02-26 12:58:58 +00004683 else
4684 return;
4685 }
4686 else
4687 return;
4688 }
anthonyce8dcb32012-03-21 13:20:31 +00004689 if (LocaleCompare("}",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004690 /* pop image_info settings from stack */
4691 Stack
4692 *node;
4693
cristyaa2c16c2012-03-25 22:21:35 +00004694 node = (Stack *)cli_wand->image_info_stack;
anthony43f425d2012-02-26 12:58:58 +00004695 if ( node == (Stack *)NULL)
anthony4d4f2c72012-03-22 03:22:03 +00004696 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
anthony43f425d2012-02-26 12:58:58 +00004697 cli_wand->image_info_stack = node->next;
4698
4699 (void) DestroyImageInfo(cli_wand->wand.image_info);
4700 cli_wand->wand.image_info = (ImageInfo *)node->data;
4701 node = (Stack *)RelinquishMagickMemory(node);
4702
4703 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4704 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4705 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4706
4707 return;
4708 }
anthonyce8dcb32012-03-21 13:20:31 +00004709 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004710 Image
4711 *new_images;
4712
4713 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004714 arg1="-1";
anthony7bcfe7f2012-03-30 14:01:22 +00004715 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
anthony92c93bd2012-03-19 14:02:47 +00004716 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004717 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004718 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004719 new_images = (Image *)cli_wand->image_list_stack->data;
4720 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004721 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4722 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004723 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004724 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony43f425d2012-02-26 12:58:58 +00004725 AppendImageToList(&cli_wand->wand.images,new_images);
4726 return;
4727 }
anthony52bef752012-03-27 13:54:47 +00004728 /*
4729 Informational Operations
4730 */
anthony0ea037a2012-04-03 12:14:39 +00004731 if (LocaleCompare("version",option+1) == 0) {
anthony52bef752012-03-27 13:54:47 +00004732 (void) FormatLocaleFile(stdout,"Version: %s\n",
4733 GetMagickVersion((size_t *) NULL));
4734 (void) FormatLocaleFile(stdout,"Copyright: %s\n",
4735 GetMagickCopyright());
4736 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
4737 GetMagickFeatures());
anthony43f425d2012-02-26 12:58:58 +00004738 return;
4739 }
anthonyce8dcb32012-03-21 13:20:31 +00004740 if (LocaleCompare("list",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004741 /* FUTURE: This should really be built into the MagickCore
4742 It does not actually require any wand or images at all!
4743 */
4744 ssize_t
4745 list;
4746
anthony2e4501b2012-03-30 04:41:54 +00004747 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
anthonyfe1aa782012-03-24 13:43:04 +00004748 if ( list < 0 ) {
4749 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
4750 return;
4751 }
anthony43f425d2012-02-26 12:58:58 +00004752 switch (list)
4753 {
4754 case MagickCoderOptions:
4755 {
anthony92c93bd2012-03-19 14:02:47 +00004756 (void) ListCoderInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004757 break;
4758 }
4759 case MagickColorOptions:
4760 {
anthony92c93bd2012-03-19 14:02:47 +00004761 (void) ListColorInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004762 break;
4763 }
4764 case MagickConfigureOptions:
4765 {
anthony92c93bd2012-03-19 14:02:47 +00004766 (void) ListConfigureInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004767 break;
4768 }
4769 case MagickDelegateOptions:
4770 {
anthony92c93bd2012-03-19 14:02:47 +00004771 (void) ListDelegateInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004772 break;
4773 }
4774 case MagickFontOptions:
4775 {
anthony92c93bd2012-03-19 14:02:47 +00004776 (void) ListTypeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004777 break;
4778 }
4779 case MagickFormatOptions:
anthony92c93bd2012-03-19 14:02:47 +00004780 (void) ListMagickInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004781 break;
4782 case MagickLocaleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004783 (void) ListLocaleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004784 break;
4785 case MagickLogOptions:
anthony92c93bd2012-03-19 14:02:47 +00004786 (void) ListLogInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004787 break;
4788 case MagickMagicOptions:
anthony92c93bd2012-03-19 14:02:47 +00004789 (void) ListMagicInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004790 break;
4791 case MagickMimeOptions:
anthony92c93bd2012-03-19 14:02:47 +00004792 (void) ListMimeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004793 break;
4794 case MagickModuleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004795 (void) ListModuleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004796 break;
4797 case MagickPolicyOptions:
anthony92c93bd2012-03-19 14:02:47 +00004798 (void) ListPolicyInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004799 break;
4800 case MagickResourceOptions:
anthony92c93bd2012-03-19 14:02:47 +00004801 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004802 break;
4803 case MagickThresholdOptions:
anthony92c93bd2012-03-19 14:02:47 +00004804 (void) ListThresholdMaps((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004805 break;
4806 default:
4807 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
anthony92c93bd2012-03-19 14:02:47 +00004808 _exception);
anthony43f425d2012-02-26 12:58:58 +00004809 break;
4810 }
4811 return;
4812 }
4813
4814#if 0
4815 // adjust stack handling
4816 // Other 'special' options this should handle
4817 // "region" "list" "version"
4818 // It does not do "exit" however as due to its side-effect requirements
4819#endif
4820#if 0
4821 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
anthony43f425d2012-02-26 12:58:58 +00004822#endif
anthonyebb73a22012-03-22 14:25:52 +00004823 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony43f425d2012-02-26 12:58:58 +00004824
anthony92c93bd2012-03-19 14:02:47 +00004825#undef _exception
anthony43f425d2012-02-26 12:58:58 +00004826}