blob: 3f33f0bf6afb8ef76279d2beb0b5b2f3b74fbee1 [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");
cristy542a95b2012-04-03 19:30:58 +00003859 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003860 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003861 else
3862 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3863 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003864
anthony7bcfe7f2012-03-30 14:01:22 +00003865 /* Get "clip-to-self" expert setting (false is normal) */
cristy542a95b2012-04-03 19:30:58 +00003866 value=GetImageOption(_image_info,"compose:clip-to-self");
3867 if (value == (const char *) NULL)
3868 clip_to_self=MagickTrue;
3869 else
3870 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3871 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003872 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003873 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003874 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003875 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003876 }
3877
anthony92c93bd2012-03-19 14:02:47 +00003878 new_images=RemoveFirstImageFromList(&_images);
3879 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003880 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003881 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003882
anthony31f1bf72012-01-30 12:37:22 +00003883 /* FUTURE - this should not be here! - should be part of -geometry */
3884 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003885 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003886
anthony31f1bf72012-01-30 12:37:22 +00003887 SetGeometry(source_image,&geometry);
3888 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3889 GravityAdjustGeometry(new_images->columns,new_images->rows,
3890 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003891
anthony92c93bd2012-03-19 14:02:47 +00003892 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003893 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003894 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003895 if ((compose == DisplaceCompositeOp) ||
anthony7bcfe7f2012-03-30 14:01:22 +00003896 (compose == DistortCompositeOp)) {
3897 /* Merge Y displacement into X displace/distort map. */
3898 (void) CompositeImage(source_image,mask_image,
3899 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3900 mask_image=DestroyImage(mask_image);
3901 }
3902 else {
3903 /* Set a blending mask for the composition. */
3904 (void) NegateImage(mask_image,MagickFalse,_exception);
3905 (void) SetImageMask(new_images,mask_image,_exception);
3906 mask_image=DestroyImage(mask_image);
3907 }
anthony805a2d42011-09-25 08:25:12 +00003908 }
cristyfeb3e962012-03-29 17:25:55 +00003909 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3910 geometry.x,geometry.y,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003911 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003912 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003913 break;
3914 }
anthonyebb73a22012-03-22 14:25:52 +00003915 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003916 }
3917 case 'd':
3918 {
anthonyafa3dfc2012-03-03 11:31:30 +00003919 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003920 {
anthony31f1bf72012-01-30 12:37:22 +00003921 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003922 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003923 break;
3924 }
anthonyafa3dfc2012-03-03 11:31:30 +00003925 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003926 {
anthonyafa3dfc2012-03-03 11:31:30 +00003927 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003928 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003929 else
anthony92c93bd2012-03-19 14:02:47 +00003930 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003931 break;
3932 }
anthonyafa3dfc2012-03-03 11:31:30 +00003933 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003934 {
anthonyafa3dfc2012-03-03 11:31:30 +00003935 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003936 {
3937 const char
3938 *p;
3939
3940 size_t
3941 number_duplicates;
3942
anthony7bcfe7f2012-03-30 14:01:22 +00003943 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003944 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3945 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003946 number_duplicates=(size_t) StringToLong(arg1);
3947 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003948 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003949 new_images=DuplicateImages(_images,number_duplicates,"-1",
3950 _exception);
anthony805a2d42011-09-25 08:25:12 +00003951 else
anthony92c93bd2012-03-19 14:02:47 +00003952 new_images=DuplicateImages(_images,number_duplicates,p,
3953 _exception);
anthony805a2d42011-09-25 08:25:12 +00003954 }
anthonyafa3dfc2012-03-03 11:31:30 +00003955 else
anthony92c93bd2012-03-19 14:02:47 +00003956 new_images=DuplicateImages(_images,1,"-1",_exception);
3957 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003958 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003959 break;
3960 }
anthonyebb73a22012-03-22 14:25:52 +00003961 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003962 }
3963 case 'e':
3964 {
anthonyafa3dfc2012-03-03 11:31:30 +00003965 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003966 {
anthony2a0ec8c2012-03-24 04:35:56 +00003967 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3968 if ( parse < 0 )
3969 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3970 option,arg1);
3971 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3972 _exception);
anthony805a2d42011-09-25 08:25:12 +00003973 break;
3974 }
anthonyebb73a22012-03-22 14:25:52 +00003975 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003976 }
3977 case 'f':
3978 {
anthonyafa3dfc2012-03-03 11:31:30 +00003979 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003980 {
anthony92c93bd2012-03-19 14:02:47 +00003981 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003982 break;
3983 }
anthonyafa3dfc2012-03-03 11:31:30 +00003984 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003985 {
anthony319dac62012-03-06 04:12:44 +00003986 /* REDIRECTED to use -layers flatten instead */
anthony2e4501b2012-03-30 04:41:54 +00003987 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003988 break;
3989 }
anthonyafa3dfc2012-03-03 11:31:30 +00003990 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003991 {
anthony92c93bd2012-03-19 14:02:47 +00003992 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003993 break;
3994 }
anthonyebb73a22012-03-22 14:25:52 +00003995 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003996 }
3997 case 'h':
3998 {
anthonyafa3dfc2012-03-03 11:31:30 +00003999 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004000 {
anthony31f1bf72012-01-30 12:37:22 +00004001 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00004002 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00004003 */
anthony805a2d42011-09-25 08:25:12 +00004004 Image
anthony31f1bf72012-01-30 12:37:22 +00004005 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00004006
anthony92c93bd2012-03-19 14:02:47 +00004007 new_images=RemoveFirstImageFromList(&_images);
4008 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004009 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004010 break;
anthony92c93bd2012-03-19 14:02:47 +00004011 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00004012 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00004013 break;
4014 }
anthonyebb73a22012-03-22 14:25:52 +00004015 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004016 }
4017 case 'i':
4018 {
anthonyafa3dfc2012-03-03 11:31:30 +00004019 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004020 {
4021 Image
anthony805a2d42011-09-25 08:25:12 +00004022 *magnitude_image,
4023 *phase_image;
4024
anthony92c93bd2012-03-19 14:02:47 +00004025 magnitude_image=RemoveFirstImageFromList(&_images);
4026 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00004027 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00004028 if (phase_image == (Image *) NULL)
4029 break;
4030 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00004031 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004032 magnitude_image=DestroyImage(magnitude_image);
4033 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00004034 break;
4035 }
anthonyafa3dfc2012-03-03 11:31:30 +00004036 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004037 {
4038 Image
anthony31f1bf72012-01-30 12:37:22 +00004039 *insert_image,
4040 *index_image;
4041
4042 ssize_t
4043 index;
anthony805a2d42011-09-25 08:25:12 +00004044
anthony7bcfe7f2012-03-30 14:01:22 +00004045 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00004046 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004047 index=0;
anthony92c93bd2012-03-19 14:02:47 +00004048 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00004049 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00004050 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00004051 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00004052 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00004053 PrependImageToList(&_images,insert_image);
4054 else if (index == (ssize_t) GetImageListLength(_images))
4055 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00004056 else
anthony43f425d2012-02-26 12:58:58 +00004057 {
anthony92c93bd2012-03-19 14:02:47 +00004058 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00004059 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00004060 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004061 InsertImageInList(&index_image,insert_image);
4062 }
anthony92c93bd2012-03-19 14:02:47 +00004063 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00004064 break;
4065 }
anthonyebb73a22012-03-22 14:25:52 +00004066 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004067 }
4068 case 'l':
4069 {
anthonyafa3dfc2012-03-03 11:31:30 +00004070 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004071 {
anthonyfe1aa782012-03-24 13:43:04 +00004072 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4073 if ( parse < 0 )
4074 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4075 option,arg1);
4076 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00004077 {
4078 case CoalesceLayer:
4079 {
anthony92c93bd2012-03-19 14:02:47 +00004080 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004081 break;
4082 }
4083 case CompareAnyLayer:
4084 case CompareClearLayer:
4085 case CompareOverlayLayer:
4086 default:
4087 {
anthonyfe1aa782012-03-24 13:43:04 +00004088 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
4089 _exception);
anthony805a2d42011-09-25 08:25:12 +00004090 break;
4091 }
4092 case MergeLayer:
4093 case FlattenLayer:
4094 case MosaicLayer:
4095 case TrimBoundsLayer:
4096 {
anthonyfe1aa782012-03-24 13:43:04 +00004097 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
4098 _exception);
anthony805a2d42011-09-25 08:25:12 +00004099 break;
4100 }
4101 case DisposeLayer:
4102 {
anthony92c93bd2012-03-19 14:02:47 +00004103 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004104 break;
4105 }
4106 case OptimizeImageLayer:
4107 {
anthony92c93bd2012-03-19 14:02:47 +00004108 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004109 break;
4110 }
4111 case OptimizePlusLayer:
4112 {
anthony92c93bd2012-03-19 14:02:47 +00004113 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004114 break;
4115 }
4116 case OptimizeTransLayer:
4117 {
anthony92c93bd2012-03-19 14:02:47 +00004118 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004119 break;
4120 }
4121 case RemoveDupsLayer:
4122 {
anthony92c93bd2012-03-19 14:02:47 +00004123 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004124 break;
4125 }
4126 case RemoveZeroLayer:
4127 {
anthony92c93bd2012-03-19 14:02:47 +00004128 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004129 break;
4130 }
4131 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004132 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004133 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004134 if (new_images == (Image *) NULL)
4135 break;
anthony92c93bd2012-03-19 14:02:47 +00004136 _images=DestroyImageList(_images);
4137 _images=OptimizeImageLayers(new_images,_exception);
4138 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004139 break;
4140 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004141 OptimizeImageTransparency(_images,_exception);
4142 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4143 _exception);
anthony805a2d42011-09-25 08:25:12 +00004144 break;
4145 }
4146 case CompositeLayer:
4147 {
anthony805a2d42011-09-25 08:25:12 +00004148 Image
4149 *source;
4150
4151 RectangleInfo
4152 geometry;
4153
anthony31f1bf72012-01-30 12:37:22 +00004154 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004155 compose;
4156
4157 const char*
4158 value;
4159
anthony92c93bd2012-03-19 14:02:47 +00004160 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004161 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004162 if (value != (const char *) NULL)
4163 compose=(CompositeOperator) ParseCommandOption(
4164 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004165
anthony31f1bf72012-01-30 12:37:22 +00004166 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004167 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004168 while (source != (Image *) NULL)
4169 {
4170 source=GetNextImageInList(source);
4171 if ((source != (Image *) NULL) &&
4172 (LocaleCompare(source->magick,"NULL") == 0))
4173 break;
4174 }
4175 if (source != (Image *) NULL)
4176 {
4177 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4178 (GetNextImageInList(source) == (Image *) NULL))
4179 source=(Image *) NULL;
4180 else
anthony31f1bf72012-01-30 12:37:22 +00004181 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004182 source=SplitImageList(source->previous);
4183 DeleteImageFromList(&source);
4184 }
4185 }
4186 if (source == (Image *) NULL)
4187 {
anthony92c93bd2012-03-19 14:02:47 +00004188 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004189 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004190 break;
4191 }
anthony31f1bf72012-01-30 12:37:22 +00004192 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004193 SetGeometry(_images,&geometry);
4194 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004195 geometry.width=source->page.width != 0 ?
4196 source->page.width : source->columns;
4197 geometry.height=source->page.height != 0 ?
4198 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004199 GravityAdjustGeometry(_images->page.width != 0 ?
4200 _images->page.width : _images->columns,
4201 _images->page.height != 0 ? _images->page.height :
4202 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004203
anthony31f1bf72012-01-30 12:37:22 +00004204 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004205 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4206 _exception);
anthony805a2d42011-09-25 08:25:12 +00004207 source=DestroyImageList(source);
4208 break;
4209 }
4210 }
anthony805a2d42011-09-25 08:25:12 +00004211 break;
4212 }
anthonyafa3dfc2012-03-03 11:31:30 +00004213 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00004214 {
4215 MagickSizeType
4216 limit;
4217
anthony72feaa62012-01-17 06:46:23 +00004218 limit=MagickResourceInfinity;
anthonyfe1aa782012-03-24 13:43:04 +00004219 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
4220 if ( parse < 0 )
4221 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
4222 option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004223 if (LocaleCompare("unlimited",arg2) != 0)
4224 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthonyfe1aa782012-03-24 13:43:04 +00004225 (void) SetMagickResourceLimit((ResourceType)parse,limit);
anthony72feaa62012-01-17 06:46:23 +00004226 break;
4227 }
anthonyebb73a22012-03-22 14:25:52 +00004228 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004229 }
4230 case 'm':
4231 {
anthonyafa3dfc2012-03-03 11:31:30 +00004232 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004233 {
anthony31f1bf72012-01-30 12:37:22 +00004234 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004235 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004236 break;
4237 }
anthonyafa3dfc2012-03-03 11:31:30 +00004238 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004239 {
4240 Image
4241 *morph_image;
4242
anthony7bcfe7f2012-03-30 14:01:22 +00004243 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004244 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004245 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4246 _exception);
anthony805a2d42011-09-25 08:25:12 +00004247 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004248 break;
anthony92c93bd2012-03-19 14:02:47 +00004249 _images=DestroyImageList(_images);
4250 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004251 break;
4252 }
anthonyafa3dfc2012-03-03 11:31:30 +00004253 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004254 {
anthony319dac62012-03-06 04:12:44 +00004255 /* REDIRECTED to use -layers mosaic instead */
anthony2e4501b2012-03-30 04:41:54 +00004256 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004257 break;
4258 }
anthonyebb73a22012-03-22 14:25:52 +00004259 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004260 }
4261 case 'p':
4262 {
anthonyafa3dfc2012-03-03 11:31:30 +00004263 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004264 {
4265 char
4266 *string;
4267
anthony92c93bd2012-03-19 14:02:47 +00004268 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004269 if (string == (char *) NULL)
4270 break;
4271 (void) FormatLocaleFile(stdout,"%s",string);
4272 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004273 break;
anthony805a2d42011-09-25 08:25:12 +00004274 }
anthonyafa3dfc2012-03-03 11:31:30 +00004275 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004276 {
4277 char
4278 **arguments;
4279
4280 int
4281 j,
4282 number_arguments;
4283
anthony31f1bf72012-01-30 12:37:22 +00004284 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004285 if (arguments == (char **) NULL)
4286 break;
anthony31f1bf72012-01-30 12:37:22 +00004287 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004288 {
4289 char
4290 breaker,
4291 quote,
4292 *token;
4293
4294 const char
4295 *arguments;
4296
4297 int
4298 next,
4299 status;
4300
4301 size_t
4302 length;
4303
4304 TokenInfo
4305 *token_info;
4306
4307 /*
anthony24aa8822012-03-11 00:56:06 +00004308 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004309 */
anthony31f1bf72012-01-30 12:37:22 +00004310 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004311 token=(char *) NULL;
4312 if (~length >= (MaxTextExtent-1))
4313 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4314 sizeof(*token));
4315 if (token == (char *) NULL)
4316 break;
4317 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004318 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004319 token_info=AcquireTokenInfo();
4320 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4321 "\"",'\0',&breaker,&next,&quote);
4322 token_info=DestroyTokenInfo(token_info);
4323 if (status == 0)
4324 {
4325 const char
4326 *argv;
4327
4328 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004329 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4330 _exception);
anthony805a2d42011-09-25 08:25:12 +00004331 }
4332 token=DestroyString(token);
4333 break;
4334 }
4335 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004336 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4337 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004338 for (j=0; j < number_arguments; j++)
4339 arguments[j]=DestroyString(arguments[j]);
4340 arguments=(char **) RelinquishMagickMemory(arguments);
4341 break;
4342 }
anthonyebb73a22012-03-22 14:25:52 +00004343 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004344 }
4345 case 'r':
4346 {
anthonyafa3dfc2012-03-03 11:31:30 +00004347 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004348 {
anthony92c93bd2012-03-19 14:02:47 +00004349 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004350 break;
4351 }
anthonyafa3dfc2012-03-03 11:31:30 +00004352 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004353 {
anthony92c93bd2012-03-19 14:02:47 +00004354 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004355 break;
4356 }
anthonyebb73a22012-03-22 14:25:52 +00004357 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004358 }
4359 case 's':
4360 {
anthonyafa3dfc2012-03-03 11:31:30 +00004361 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004362 {
4363 Image
4364 *smush_image;
4365
4366 ssize_t
4367 offset;
4368
anthony7bcfe7f2012-03-30 14:01:22 +00004369 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004370 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004371 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004372 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004373 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004374 break;
anthony92c93bd2012-03-19 14:02:47 +00004375 _images=DestroyImageList(_images);
4376 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004377 break;
4378 }
anthony0ea037a2012-04-03 12:14:39 +00004379 if (LocaleCompare("swap",option+1) == 0) {
4380 Image
4381 *p,
4382 *q,
4383 *swap;
anthony805a2d42011-09-25 08:25:12 +00004384
anthony0ea037a2012-04-03 12:14:39 +00004385 ssize_t
4386 index,
4387 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004388
anthony0ea037a2012-04-03 12:14:39 +00004389 index=-1;
4390 swap_index=-2;
4391 if (IfNormalOp) {
4392 GeometryInfo
4393 geometry_info;
4394
4395 MagickStatusType
4396 flags;
4397
4398 swap_index=(-1);
anthony7bcfe7f2012-03-30 14:01:22 +00004399 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004400 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004401 flags=ParseGeometry(arg1,&geometry_info);
4402 index=(ssize_t) geometry_info.rho;
4403 if ((flags & SigmaValue) != 0)
4404 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004405 }
anthony0ea037a2012-04-03 12:14:39 +00004406 p=GetImageFromList(_images,index);
4407 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004408 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4409 if (IfNormalOp)
4410 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4411 else
4412 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4413 }
anthony0ea037a2012-04-03 12:14:39 +00004414 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004415 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004416 swap=CloneImage(p,0,0,MagickTrue,_exception);
4417 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4418 ReplaceImageInList(&q,swap);
4419 _images=GetFirstImageInList(q);
4420 break;
4421 }
anthonyebb73a22012-03-22 14:25:52 +00004422 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004423 }
anthony805a2d42011-09-25 08:25:12 +00004424 default:
anthonyebb73a22012-03-22 14:25:52 +00004425 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004426 }
anthony31f1bf72012-01-30 12:37:22 +00004427 if (new_images == (Image *) NULL)
4428 return;
anthony805a2d42011-09-25 08:25:12 +00004429
anthony92c93bd2012-03-19 14:02:47 +00004430 if (_images != (Image *) NULL)
4431 _images=DestroyImageList(_images);
4432 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004433 return;
4434
anthony92c93bd2012-03-19 14:02:47 +00004435#undef _image_info
4436#undef _images
4437#undef _exception
4438#undef _draw_info
4439#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004440#undef IfNormalOp
4441#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004442#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004443}
anthony43f425d2012-02-26 12:58:58 +00004444
4445/*
4446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4447% %
4448% %
4449% %
4450+ C L I S p e c i a l O p e r a t i o n s %
4451% %
4452% %
4453% %
4454%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4455%
4456% CLISpecialOption() Applies operations that may involve empty image lists
4457% and or stacks of image lists or image_info settings.
4458%
anthonyafa3dfc2012-03-03 11:31:30 +00004459% The classic operators of this type is -read, and image stack operators,
4460% which can be applied to empty image lists.
4461%
4462% Note: unlike other Operators, these may involve other special 'option'
4463% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004464%
4465% The format of the CLISpecialOption method is:
4466%
4467% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004468% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004469%
4470% A description of each parameter follows:
4471%
4472% o cli_wand: the main CLI Wand to use.
4473%
4474% o option: The special option (with any switch char) to process
4475%
anthony24aa8822012-03-11 00:56:06 +00004476% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004477%
anthony2052d272012-02-28 12:48:29 +00004478% Example Usage...
4479%
anthonyce8dcb32012-03-21 13:20:31 +00004480% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004481%
anthony24aa8822012-03-11 00:56:06 +00004482% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004483%
4484% cli_wand
4485% argc,argv
4486% i=index in argv
4487%
4488% option_info = GetCommandOptionInfo(argv[i]);
4489% count=option_info->type;
4490% option_type=option_info->flags;
4491%
4492% if ( (option_type & SpecialOptionFlag) != 0 )
4493% CLISpecialOperator(cli_wand,argv[i],
4494% count>=1 ? argv[i+1] : (char *)NULL);
4495% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004496%
4497*/
4498
anthony43f425d2012-02-26 12:58:58 +00004499WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004500 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004501{
anthony8226e722012-04-05 14:25:46 +00004502#define _image_info (cli_wand->wand.image_info)
4503#define _images (cli_wand->wand.images)
4504#define _exception (cli_wand->wand.exception)
4505#define IfNormalOp (*option=='-')
4506#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004507
4508 assert(cli_wand != (MagickCLI *) NULL);
4509 assert(cli_wand->signature == WandSignature);
4510 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +00004511 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00004512 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4513
anthony8226e722012-04-05 14:25:46 +00004514 if(_images != (Image *)NULL)
4515 (void) SyncImagesSettings(cli_wand->wand.image_info,_images,_exception);
anthony24aa8822012-03-11 00:56:06 +00004516
anthony52bef752012-03-27 13:54:47 +00004517 /*
4518 No-op options
4519 */
4520 if (LocaleCompare("noop",option+1) == 0)
4521 return;
4522 if (LocaleCompare("sans",option+1) == 0)
4523 return;
4524 if (LocaleCompare("sans0",option+1) == 0)
4525 return;
4526 if (LocaleCompare("sans2",option+1) == 0)
4527 return;
4528 /*
4529 Image Reading
4530 */
4531 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthony0ea037a2012-04-03 12:14:39 +00004532 ( LocaleCompare("--",option) == 0 ) ) {
4533 int
4534 argc;
4535 char
4536 **argv;
anthony52bef752012-03-27 13:54:47 +00004537
anthony0ea037a2012-04-03 12:14:39 +00004538 ssize_t
4539 i;
4540
4541 /* Expand the filename argument (meta-characters or "@filelist" ) */
4542 argc = 1;
cristye71f2942012-04-04 11:07:05 +00004543 argv = (char **) &arg1;
anthony0ea037a2012-04-03 12:14:39 +00004544 MagickBooleanType
4545 status=ExpandFilenames(&argc,&argv);
4546
4547 if (IfMagickFalse(status))
4548 CLIWandExceptArgReturn(ResourceLimitError,"MemoryAllocationFailed",
4549 option,GetExceptionMessage(errno));
4550
4551 /* loop over expanded list reading images */
4552 for (i=0; i<argc; i++) {
anthony52bef752012-03-27 13:54:47 +00004553#if !USE_WAND_METHODS
4554 Image *
4555 new_images;
anthony8226e722012-04-05 14:25:46 +00004556 if (IfMagickTrue(_image_info->ping))
4557 new_images=PingImages(_image_info,argv[i],_exception);
anthony52bef752012-03-27 13:54:47 +00004558 else
anthony8226e722012-04-05 14:25:46 +00004559 new_images=ReadImages(_image_info,argv[i],_exception);
4560 AppendImageToList(&_images, new_images);
anthony52bef752012-03-27 13:54:47 +00004561#else
4562 /* read images using MagickWand method - no ping */
4563 /* This is not working! - it locks up in a CPU loop! */
4564 MagickSetLastIterator(&cli_wand->wand);
4565 MagickReadImage(&cli_wand->wand,arg1);
4566 MagickSetFirstIterator(&cli_wand->wand);
4567#endif
anthony52bef752012-03-27 13:54:47 +00004568 }
anthony0ea037a2012-04-03 12:14:39 +00004569 /* FUTURE: how do I free the expanded filename arguments??? */
4570
4571 return;
4572 }
anthony52bef752012-03-27 13:54:47 +00004573 /*
anthony8226e722012-04-05 14:25:46 +00004574 Image Writing
4575 */
4576 if (LocaleCompare("write",option+1) == 0) {
4577 char
4578 key[MaxTextExtent];
4579
4580 Image
4581 *write_images;
4582
4583 ImageInfo
4584 *write_info;
4585
4586 /* Need images, unless a "null:" output coder is used */
4587 if ( cli_wand->wand.images == (Image *) NULL ) {
4588 if ( LocaleCompare(option,"null:") == 0 )
4589 return;
4590 CLIWandExceptArgReturn(OptionError,"NoImagesForWrite",option,arg1);
4591 }
4592
4593 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4594 (void) DeleteImageRegistry(key);
4595 write_images=_images;
4596 if (IfPlusOp)
4597 write_images=CloneImageList(_images,_exception);
4598 write_info=CloneImageInfo(_image_info);
4599 (void) WriteImages(write_info,write_images,arg1,_exception);
4600 write_info=DestroyImageInfo(write_info);
4601 if (IfPlusOp)
4602 write_images=DestroyImageList(write_images);
4603 return;
4604 }
4605 /*
anthony52bef752012-03-27 13:54:47 +00004606 Parenthesis and Brace operations
4607 */
anthonyce8dcb32012-03-21 13:20:31 +00004608 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
anthonyf42014d2012-03-25 09:53:06 +00004609 /* link image and setting stacks - option is itself saved on stack! */
anthonyce8dcb32012-03-21 13:20:31 +00004610 (void) SetImageOption(cli_wand->wand.image_info,option+1,
anthony8226e722012-04-05 14:25:46 +00004611 IfNormalOp ? "true" : (char *) NULL);
anthonyce8dcb32012-03-21 13:20:31 +00004612 return;
4613 }
4614 if (LocaleCompare("(",option) == 0) {
anthony8226e722012-04-05 14:25:46 +00004615 /* stack 'push' images */
4616 Stack
4617 *node;
anthony43f425d2012-02-26 12:58:58 +00004618
anthony8226e722012-04-05 14:25:46 +00004619 size_t
4620 size;
anthony43f425d2012-02-26 12:58:58 +00004621
anthony8226e722012-04-05 14:25:46 +00004622 size=0;
4623 node=cli_wand->image_list_stack;
4624 for ( ; node != (Stack *)NULL; node=node->next)
4625 size++;
4626 if ( size >= MAX_STACK_DEPTH )
4627 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
4628 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4629 if (node == (Stack *) NULL)
4630 CLIWandExceptionReturn(ResourceLimitFatalError,
4631 "MemoryAllocationFailed",option);
4632 node->data = (void *)cli_wand->wand.images;
4633 cli_wand->wand.images = NewImageList();
4634 node->next = cli_wand->image_list_stack;
4635 cli_wand->image_list_stack = node;
anthony43f425d2012-02-26 12:58:58 +00004636
anthony8226e722012-04-05 14:25:46 +00004637 /* handle respect-parenthesis */
4638 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4639 "respect-parenthesis"))))
4640 option="{"; /* fall-thru so as to push image settings too */
4641 else
anthony43f425d2012-02-26 12:58:58 +00004642 return;
anthony8226e722012-04-05 14:25:46 +00004643 }
4644 if (LocaleCompare("{",option) == 0) {
4645 /* stack 'push' of image_info settings */
4646 Stack
4647 *node;
anthony43f425d2012-02-26 12:58:58 +00004648
anthony8226e722012-04-05 14:25:46 +00004649 size_t
4650 size;
anthony43f425d2012-02-26 12:58:58 +00004651
anthony8226e722012-04-05 14:25:46 +00004652 size=0;
4653 node=cli_wand->image_info_stack;
4654 for ( ; node != (Stack *)NULL; node=node->next)
4655 size++;
4656 if ( size >= MAX_STACK_DEPTH )
4657 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
4658 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4659 if (node == (Stack *) NULL)
4660 CLIWandExceptionReturn(ResourceLimitFatalError,
4661 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004662
anthony8226e722012-04-05 14:25:46 +00004663 node->data = (void *)cli_wand->wand.image_info;
4664 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4665 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4666 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4667 option);
anthony43f425d2012-02-26 12:58:58 +00004668 cli_wand->wand.image_info = (ImageInfo *)node->data;
4669 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004670 return;
4671 }
anthony8226e722012-04-05 14:25:46 +00004672
4673 node->next = cli_wand->image_info_stack;
4674 cli_wand->image_info_stack = node;
4675
4676 return;
4677 }
4678 if (LocaleCompare(")",option) == 0) {
4679 /* pop images from stack */
4680 Stack
4681 *node;
4682
4683 node = (Stack *)cli_wand->image_list_stack;
4684 if ( node == (Stack *)NULL)
4685 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
4686 cli_wand->image_list_stack = node->next;
4687
4688 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4689 cli_wand->wand.images= (Image *)node->data;
4690 node = (Stack *)RelinquishMagickMemory(node);
4691
4692 /* handle respect-parenthesis - of the previous 'pushed' settings */
4693 node = cli_wand->image_info_stack;
4694 if ( node != (Stack *)NULL)
4695 {
4696 if (IfMagickTrue(IsStringTrue(GetImageOption(
4697 cli_wand->wand.image_info,"respect-parenthesis"))))
4698 option="}"; /* fall-thru so as to pop image settings too */
4699 else
4700 return;
4701 }
4702 else
4703 return;
4704 }
4705 if (LocaleCompare("}",option) == 0) {
4706 /* pop image_info settings from stack */
4707 Stack
4708 *node;
4709
4710 node = (Stack *)cli_wand->image_info_stack;
4711 if ( node == (Stack *)NULL)
4712 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
4713 cli_wand->image_info_stack = node->next;
4714
4715 (void) DestroyImageInfo(cli_wand->wand.image_info);
4716 cli_wand->wand.image_info = (ImageInfo *)node->data;
4717 node = (Stack *)RelinquishMagickMemory(node);
4718
4719 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4720 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4721 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4722
4723 return;
4724 }
anthonyce8dcb32012-03-21 13:20:31 +00004725 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004726 Image
4727 *new_images;
4728
4729 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004730 arg1="-1";
anthony7bcfe7f2012-03-30 14:01:22 +00004731 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
anthony92c93bd2012-03-19 14:02:47 +00004732 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004733 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004734 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004735 new_images = (Image *)cli_wand->image_list_stack->data;
4736 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004737 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4738 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004739 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004740 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony8226e722012-04-05 14:25:46 +00004741 AppendImageToList(&_images,new_images);
anthony43f425d2012-02-26 12:58:58 +00004742 return;
4743 }
anthony52bef752012-03-27 13:54:47 +00004744 /*
4745 Informational Operations
4746 */
anthony0ea037a2012-04-03 12:14:39 +00004747 if (LocaleCompare("version",option+1) == 0) {
anthony8226e722012-04-05 14:25:46 +00004748 (void) FormatLocaleFile(stdout,"Version: %s\n",
4749 GetMagickVersion((size_t *) NULL));
4750 (void) FormatLocaleFile(stdout,"Copyright: %s\n",
4751 GetMagickCopyright());
4752 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
4753 GetMagickFeatures());
4754 return;
4755 }
anthonyce8dcb32012-03-21 13:20:31 +00004756 if (LocaleCompare("list",option+1) == 0) {
anthony8226e722012-04-05 14:25:46 +00004757 /* FUTURE: This should really be built into the MagickCore
4758 It does not actually require a cli-wand or and images!
4759 */
4760 ssize_t
4761 list;
anthony43f425d2012-02-26 12:58:58 +00004762
anthony8226e722012-04-05 14:25:46 +00004763 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4764 if ( list < 0 ) {
4765 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004766 return;
4767 }
anthony8226e722012-04-05 14:25:46 +00004768 switch (list)
4769 {
4770 case MagickCoderOptions:
4771 {
4772 (void) ListCoderInfo((FILE *) NULL,_exception);
4773 break;
4774 }
4775 case MagickColorOptions:
4776 {
4777 (void) ListColorInfo((FILE *) NULL,_exception);
4778 break;
4779 }
4780 case MagickConfigureOptions:
4781 {
4782 (void) ListConfigureInfo((FILE *) NULL,_exception);
4783 break;
4784 }
4785 case MagickDelegateOptions:
4786 {
4787 (void) ListDelegateInfo((FILE *) NULL,_exception);
4788 break;
4789 }
4790 case MagickFontOptions:
4791 {
4792 (void) ListTypeInfo((FILE *) NULL,_exception);
4793 break;
4794 }
4795 case MagickFormatOptions:
4796 (void) ListMagickInfo((FILE *) NULL,_exception);
4797 break;
4798 case MagickLocaleOptions:
4799 (void) ListLocaleInfo((FILE *) NULL,_exception);
4800 break;
4801 case MagickLogOptions:
4802 (void) ListLogInfo((FILE *) NULL,_exception);
4803 break;
4804 case MagickMagicOptions:
4805 (void) ListMagicInfo((FILE *) NULL,_exception);
4806 break;
4807 case MagickMimeOptions:
4808 (void) ListMimeInfo((FILE *) NULL,_exception);
4809 break;
4810 case MagickModuleOptions:
4811 (void) ListModuleInfo((FILE *) NULL,_exception);
4812 break;
4813 case MagickPolicyOptions:
4814 (void) ListPolicyInfo((FILE *) NULL,_exception);
4815 break;
4816 case MagickResourceOptions:
4817 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4818 break;
4819 case MagickThresholdOptions:
4820 (void) ListThresholdMaps((FILE *) NULL,_exception);
4821 break;
4822 default:
4823 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4824 _exception);
4825 break;
4826 }
4827 return;
4828 }
anthony43f425d2012-02-26 12:58:58 +00004829
4830#if 0
anthony43f425d2012-02-26 12:58:58 +00004831 // Other 'special' options this should handle
anthony8226e722012-04-05 14:25:46 +00004832 // "region"
anthony43f425d2012-02-26 12:58:58 +00004833 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
anthony43f425d2012-02-26 12:58:58 +00004834#endif
anthonyebb73a22012-03-22 14:25:52 +00004835 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony43f425d2012-02-26 12:58:58 +00004836
anthony8226e722012-04-05 14:25:46 +00004837#undef _image_info
4838#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004839#undef _exception
anthony8226e722012-04-05 14:25:46 +00004840#undef IfNormalOp
4841#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004842}