blob: fc4c1fc74f97dfc0d7e2ad077cf6e278fe10486c [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 }
cristyb0f7a182012-04-06 23:33:11 +00001387 if (LocaleCompare("regard-warnings",option+1) == 0)
1388 break;
anthonyafa3dfc2012-03-03 11:31:30 +00001389 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001390 {
anthony92c93bd2012-03-19 14:02:47 +00001391 /* _draw_info only setting */
1392 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001393 break;
1394 }
anthonyebb73a22012-03-22 14:25:52 +00001395 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001396 }
1397 case 's':
1398 {
anthonyafa3dfc2012-03-03 11:31:30 +00001399 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001400 {
anthonyafbaed72011-10-26 12:05:04 +00001401 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony7bcfe7f2012-03-30 14:01:22 +00001402 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001403 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001404 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001405 break;
1406 }
anthonyafa3dfc2012-03-03 11:31:30 +00001407 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001408 {
anthonyf42014d2012-03-25 09:53:06 +00001409 /* SyncImageSettings() used to set this as a per-image attribute.
anthony72feaa62012-01-17 06:46:23 +00001410 What ??? Why ????
1411 */
anthony7bcfe7f2012-03-30 14:01:22 +00001412 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001413 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001414 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1415 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001416 break;
1417 }
anthonyafa3dfc2012-03-03 11:31:30 +00001418 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001419 {
anthony7bcfe7f2012-03-30 14:01:22 +00001420 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001421 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafbaed72011-10-26 12:05:04 +00001422 SeedPseudoRandomGenerator(
anthony24aa8822012-03-11 00:56:06 +00001423 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001424 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001425 break;
1426 }
anthonyafa3dfc2012-03-03 11:31:30 +00001427 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001428 {
anthony92c93bd2012-03-19 14:02:47 +00001429 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001430 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001431 */
anthony92c93bd2012-03-19 14:02:47 +00001432 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001433 break;
1434 }
anthonyafa3dfc2012-03-03 11:31:30 +00001435 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001436 {
anthonyf42014d2012-03-25 09:53:06 +00001437 arg1=ArgOption("undefined");
1438 parse = ParseCommandOption(MagickStretchOptions,MagickFalse,arg1);
1439 if (parse < 0)
1440 CLIWandExceptArgBreak(OptionError,"UnrecognizedStretchType",
1441 option,arg1);
1442 _draw_info->stretch=(StretchType) parse;
anthony805a2d42011-09-25 08:25:12 +00001443 break;
1444 }
anthonyafa3dfc2012-03-03 11:31:30 +00001445 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001446 {
anthonyafbaed72011-10-26 12:05:04 +00001447 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001448 UPDATE: ensure stroke color is not destroyed is a pattern
1449 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001450 */
anthony72feaa62012-01-17 06:46:23 +00001451 MagickBooleanType
1452 status;
anthonyafbaed72011-10-26 12:05:04 +00001453
1454 ExceptionInfo
1455 *sans;
1456
anthonyfd706f92012-01-19 04:22:02 +00001457 PixelInfo
1458 color;
1459
anthony2a0ec8c2012-03-24 04:35:56 +00001460 arg1 = ArgOption("none"); /* +fill turns it off! */
1461 (void) SetImageOption(_image_info,option+1,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001462 if (_draw_info->stroke_pattern != (Image *) NULL)
1463 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001464
1465 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001466 sans=AcquireExceptionInfo();
anthony2a0ec8c2012-03-24 04:35:56 +00001467 status=QueryColorCompliance(arg1,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001468 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001469
anthony7bcfe7f2012-03-30 14:01:22 +00001470 if (IfMagickFalse(status))
anthony2a0ec8c2012-03-24 04:35:56 +00001471 _draw_info->stroke_pattern=GetImageCache(_image_info,arg1,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001472 else
anthony92c93bd2012-03-19 14:02:47 +00001473 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001474 break;
1475 }
anthonyafa3dfc2012-03-03 11:31:30 +00001476 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001477 {
anthony7bcfe7f2012-03-30 14:01:22 +00001478 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00001479 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001480 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1481 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001482 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001483 break;
1484 }
anthonyafa3dfc2012-03-03 11:31:30 +00001485 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001486 {
anthonyf42014d2012-03-25 09:53:06 +00001487 arg1=ArgOption("undefined");
1488 parse = ParseCommandOption(MagickStyleOptions,MagickFalse,arg1);
1489 if (parse < 0)
1490 CLIWandExceptArgBreak(OptionError,"UnrecognizedStyleType",
1491 option,arg1);
1492 _draw_info->style=(StyleType) parse;
anthony805a2d42011-09-25 08:25:12 +00001493 break;
1494 }
anthonyafa3dfc2012-03-03 11:31:30 +00001495 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001496 {
anthonyf42014d2012-03-25 09:53:06 +00001497 /* FUTURE: syncronize to storage - but what does that mean? */
anthony92c93bd2012-03-19 14:02:47 +00001498 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001499 break;
1500 }
anthonyebb73a22012-03-22 14:25:52 +00001501 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001502 }
1503 case 't':
1504 {
anthonyafa3dfc2012-03-03 11:31:30 +00001505 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001506 {
anthony72feaa62012-01-17 06:46:23 +00001507 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001508 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001509 break;
1510 }
anthonyafa3dfc2012-03-03 11:31:30 +00001511 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001512 {
anthony52bef752012-03-27 13:54:47 +00001513 /* FUTURE: move _image_info string to option splay-tree
1514 Other than "montage" what uses "texture" ????
1515 */
anthony92c93bd2012-03-19 14:02:47 +00001516 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001517 break;
1518 }
anthonyafa3dfc2012-03-03 11:31:30 +00001519 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001520 {
anthony92c93bd2012-03-19 14:02:47 +00001521 _draw_info->fill_pattern=IfSetOption
1522 ?GetImageCache(_image_info,arg1,_exception)
1523 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001524 break;
1525 }
anthonyafa3dfc2012-03-03 11:31:30 +00001526 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001527 {
anthony72feaa62012-01-17 06:46:23 +00001528 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony52bef752012-03-27 13:54:47 +00001529 arg1=ArgOption("0");
anthony7bcfe7f2012-03-30 14:01:22 +00001530 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001531 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1532 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001533 break;
1534 }
anthonyafa3dfc2012-03-03 11:31:30 +00001535 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001536 {
anthony92c93bd2012-03-19 14:02:47 +00001537 /* FUTURE: both _image_info attribute & ImageOption in use!
1538 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001539 SyncImageSettings() used to set per-image attribute.
1540
anthonyafbaed72011-10-26 12:05:04 +00001541 Note that +transparent-color, means fall-back to image
1542 attribute so ImageOption is deleted, not set to a default.
1543 */
anthony7bcfe7f2012-03-30 14:01:22 +00001544 if (IfSetOption && IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001545 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001546 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001547 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001548 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001549 break;
1550 }
anthonyafa3dfc2012-03-03 11:31:30 +00001551 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001552 {
anthony92c93bd2012-03-19 14:02:47 +00001553 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1554 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001555 break;
1556 }
anthonyafa3dfc2012-03-03 11:31:30 +00001557 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001558 {
anthony72feaa62012-01-17 06:46:23 +00001559 /* SyncImageSettings() used to set per-image attribute. */
anthony52bef752012-03-27 13:54:47 +00001560 parse=ParseCommandOption(MagickTypeOptions,MagickFalse,
1561 ArgOption("undefined"));
1562 if (parse < 0)
1563 CLIWandExceptArgBreak(OptionError,"UnrecognizedImageType",
1564 option,arg1);
1565 _image_info->type=(ImageType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001566 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001567 break;
1568 }
anthonyebb73a22012-03-22 14:25:52 +00001569 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001570 }
1571 case 'u':
1572 {
anthonyafa3dfc2012-03-03 11:31:30 +00001573 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001574 {
anthony92c93bd2012-03-19 14:02:47 +00001575 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001576 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001577 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001578 break;
1579 }
anthonyafa3dfc2012-03-03 11:31:30 +00001580 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001581 {
anthony72feaa62012-01-17 06:46:23 +00001582 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001583 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001584 FUTURE: this probably should be part of the density setting
1585 */
anthony52bef752012-03-27 13:54:47 +00001586 parse=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1587 ArgOption("undefined"));
1588 if (parse < 0)
1589 CLIWandExceptArgBreak(OptionError,"UnrecognizedUnitsType",
1590 option,arg1);
1591 _image_info->units=(ResolutionType) parse;
anthony92c93bd2012-03-19 14:02:47 +00001592 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001593 break;
1594 }
anthonyebb73a22012-03-22 14:25:52 +00001595 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001596 }
1597 case 'v':
1598 {
anthonyafa3dfc2012-03-03 11:31:30 +00001599 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001600 {
anthony24aa8822012-03-11 00:56:06 +00001601 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001602 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001603 */
anthony92c93bd2012-03-19 14:02:47 +00001604 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1605 _image_info->verbose= ArgBoolean;
1606 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001607 break;
1608 }
anthonyafa3dfc2012-03-03 11:31:30 +00001609 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001610 {
anthony92c93bd2012-03-19 14:02:47 +00001611 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001612 Only used by coder FPX
anthony52bef752012-03-27 13:54:47 +00001613 And it only tests existance, not its content!
anthonyab3a50c2011-10-27 11:48:57 +00001614 */
anthony92c93bd2012-03-19 14:02:47 +00001615 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001616 break;
1617 }
anthonyafa3dfc2012-03-03 11:31:30 +00001618 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001619 {
anthonyfd706f92012-01-19 04:22:02 +00001620 /* SyncImageSettings() used to set per-image attribute.
1621 This is VERY deep in the image caching structure.
1622 */
anthony52bef752012-03-27 13:54:47 +00001623 parse=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1624 ArgOption("undefined"));
1625 if (parse < 0)
1626 CLIWandExceptArgBreak(OptionError,"UnrecognizedVirtualPixelMethod",
1627 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001628 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001629 break;
1630 }
anthonyebb73a22012-03-22 14:25:52 +00001631 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001632 }
1633 case 'w':
1634 {
anthonyafa3dfc2012-03-03 11:31:30 +00001635 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001636 {
anthony72feaa62012-01-17 06:46:23 +00001637 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001638 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001639 */
anthony52bef752012-03-27 13:54:47 +00001640 arg1=ArgOption("all");
anthony92c93bd2012-03-19 14:02:47 +00001641 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001642 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001643 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001644 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001645 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001646 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001647 if (_draw_info->weight <= 800)
1648 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001649 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001650 if (_draw_info->weight >= 100)
1651 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001652 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001653 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001654 break;
1655 }
anthonyafa3dfc2012-03-03 11:31:30 +00001656 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001657 {
anthony72feaa62012-01-17 06:46:23 +00001658 /* Used as a image chromaticity setting
1659 SyncImageSettings() used to set per-image attribute.
1660 */
anthony52bef752012-03-27 13:54:47 +00001661 arg1=ArgOption("0.0");
anthony7bcfe7f2012-03-30 14:01:22 +00001662 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00001663 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1664 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00001665 break;
1666 }
anthonyebb73a22012-03-22 14:25:52 +00001667 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001668 }
1669 default:
anthonyebb73a22012-03-22 14:25:52 +00001670 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001671 }
anthony24aa8822012-03-11 00:56:06 +00001672
anthony92c93bd2012-03-19 14:02:47 +00001673#undef _image_info
1674#undef _exception
1675#undef _draw_info
1676#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001677#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001678#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001679#undef ArgBooleanNot
1680#undef ArgBooleanString
1681#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001682
anthony31f1bf72012-01-30 12:37:22 +00001683 return;
anthony805a2d42011-09-25 08:25:12 +00001684}
1685
1686/*
1687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1688% %
1689% %
1690% %
anthony43f425d2012-02-26 12:58:58 +00001691+ 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 +00001692% %
1693% %
1694% %
1695%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1696%
anthony31f1bf72012-01-30 12:37:22 +00001697% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001698% the images in the CLI wand, with the settings that was previously saved in
1699% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001700%
1701% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001702% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001703%
anthonyd1447672012-01-19 05:33:53 +00001704% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001705%
anthony43f425d2012-02-26 12:58:58 +00001706% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001707% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001708%
1709% A description of each parameter follows:
1710%
anthony43f425d2012-02-26 12:58:58 +00001711% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001712%
anthonyfd706f92012-01-19 04:22:02 +00001713% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001714%
anthonyfd706f92012-01-19 04:22:02 +00001715% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001716%
anthony31f1bf72012-01-30 12:37:22 +00001717% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001718%
anthony31f1bf72012-01-30 12:37:22 +00001719% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001720%
anthonyafa3dfc2012-03-03 11:31:30 +00001721% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1722% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1723% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001724%
anthony24aa8822012-03-11 00:56:06 +00001725% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +00001726%
anthony43f425d2012-02-26 12:58:58 +00001727% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001728% argc,argv
1729% i=index in argv
1730%
anthony2052d272012-02-28 12:48:29 +00001731% option_info = GetCommandOptionInfo(argv[i]);
1732% count=option_info->type;
1733% option_type=option_info->flags;
1734%
1735% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001736% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001737% count>=1 ? argv[i+1] : (char *)NULL,
1738% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001739% i += count+1;
1740%
anthony805a2d42011-09-25 08:25:12 +00001741*/
anthony31f1bf72012-01-30 12:37:22 +00001742
1743/*
1744 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001745 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001746
1747 The image in the list may be modified in three different ways...
1748 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1749 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1750 * one image replace by a list of images (-separate and -crop only!)
1751
anthonyafa3dfc2012-03-03 11:31:30 +00001752 In each case the result replaces the single original image in the list, as
1753 well as the pointer to the modified image (last image added if replaced by a
1754 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001755
1756 As the image pointed to may be replaced, the first image in the list may
1757 also change. GetFirstImageInList() should be used by caller if they wish
1758 return the Image pointer to the first image in list.
1759*/
anthony43f425d2012-02-26 12:58:58 +00001760static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001761 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001762{
1763 Image *
1764 new_image;
1765
anthony805a2d42011-09-25 08:25:12 +00001766 GeometryInfo
1767 geometry_info;
1768
1769 RectangleInfo
1770 geometry;
1771
1772 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001773 flags;
1774
anthony92c93bd2012-03-19 14:02:47 +00001775 ssize_t
anthony2a0ec8c2012-03-24 04:35:56 +00001776 parse;
anthony92c93bd2012-03-19 14:02:47 +00001777
anthony2e4501b2012-03-30 04:41:54 +00001778#define _image_info (cli_wand->wand.image_info)
1779#define _image (cli_wand->wand.images)
1780#define _exception (cli_wand->wand.exception)
1781#define _draw_info (cli_wand->draw_info)
1782#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001783#define IfNormalOp (*option=='-')
1784#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00001785#define normal_op IsMagickTrue(IfNormalOp)
1786#define plus_alt_op IsMagickFalse(IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001787
anthony43f425d2012-02-26 12:58:58 +00001788 assert(cli_wand != (MagickCLI *) NULL);
1789 assert(cli_wand->signature == WandSignature);
1790 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001791 assert(_image != (Image *) NULL); /* an image must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00001792 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00001793 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001794
anthony92c93bd2012-03-19 14:02:47 +00001795 (void) SyncImageSettings(_image_info,_image,_exception);
anthony24aa8822012-03-11 00:56:06 +00001796
anthony805a2d42011-09-25 08:25:12 +00001797 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001798
anthony5330ae02012-03-20 14:17:01 +00001799 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001800
anthonyfd706f92012-01-19 04:22:02 +00001801 /* FUTURE: We may need somthing a little more optimized than this!
1802 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1803 */
anthonyafa3dfc2012-03-03 11:31:30 +00001804 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001805 {
1806 case 'a':
1807 {
anthonyafa3dfc2012-03-03 11:31:30 +00001808 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001809 {
anthony7bcfe7f2012-03-30 14:01:22 +00001810 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001811 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001812 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001813 if ((flags & SigmaValue) == 0)
1814 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001815 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001816 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001817 break;
1818 }
anthonyafa3dfc2012-03-03 11:31:30 +00001819 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001820 {
anthonyfe1aa782012-03-24 13:43:04 +00001821 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00001822 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001823 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1824 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1825 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00001826 _exception);
anthony805a2d42011-09-25 08:25:12 +00001827 break;
1828 }
anthonyafa3dfc2012-03-03 11:31:30 +00001829 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001830 {
anthony7bcfe7f2012-03-30 14:01:22 +00001831 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001832 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001833 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001834 if ((flags & SigmaValue) == 0)
1835 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001836 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00001837 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00001838 break;
1839 }
anthonyafa3dfc2012-03-03 11:31:30 +00001840 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001841 {
anthony2a0ec8c2012-03-24 04:35:56 +00001842 parse=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1843 if (parse < 0)
anthony92c93bd2012-03-19 14:02:47 +00001844 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1845 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00001846 (void) SetImageAlphaChannel(_image,(AlphaChannelType)parse,
1847 _exception);
anthony805a2d42011-09-25 08:25:12 +00001848 break;
1849 }
anthonyafa3dfc2012-03-03 11:31:30 +00001850 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001851 {
1852 char
1853 *text,
1854 geometry[MaxTextExtent];
1855
anthony7bcfe7f2012-03-30 14:01:22 +00001856 if (IfMagickFalse(IsGeometry(arg1)))
anthony92c93bd2012-03-19 14:02:47 +00001857 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001858 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001859 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001860 if ((flags & SigmaValue) == 0)
1861 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001862 text=InterpretImageProperties(_image_info,_image,arg2,
1863 _exception);
anthony805a2d42011-09-25 08:25:12 +00001864 if (text == (char *) NULL)
1865 break;
anthony92c93bd2012-03-19 14:02:47 +00001866 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001867 text=DestroyString(text);
1868 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1869 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001870 (void) CloneString(&_draw_info->geometry,geometry);
1871 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001872 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001873 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001874 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001875 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001876 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001877 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001878 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001879 (void) AnnotateImage(_image,_draw_info,_exception);
1880 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001881 break;
1882 }
anthonyafa3dfc2012-03-03 11:31:30 +00001883 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001884 {
anthony92c93bd2012-03-19 14:02:47 +00001885 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001886 break;
1887 }
anthonyafa3dfc2012-03-03 11:31:30 +00001888 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001889 {
anthony92c93bd2012-03-19 14:02:47 +00001890 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001891 break;
1892 }
anthonyafa3dfc2012-03-03 11:31:30 +00001893 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001894 {
anthony5330ae02012-03-20 14:17:01 +00001895 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001896 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001897 {
1898 case TopRightOrientation:
1899 {
anthony92c93bd2012-03-19 14:02:47 +00001900 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001901 break;
1902 }
1903 case BottomRightOrientation:
1904 {
anthony92c93bd2012-03-19 14:02:47 +00001905 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001906 break;
1907 }
1908 case BottomLeftOrientation:
1909 {
anthony92c93bd2012-03-19 14:02:47 +00001910 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001911 break;
1912 }
1913 case LeftTopOrientation:
1914 {
anthony92c93bd2012-03-19 14:02:47 +00001915 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001916 break;
1917 }
1918 case RightTopOrientation:
1919 {
anthony92c93bd2012-03-19 14:02:47 +00001920 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001921 break;
1922 }
1923 case RightBottomOrientation:
1924 {
anthony92c93bd2012-03-19 14:02:47 +00001925 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001926 break;
1927 }
1928 case LeftBottomOrientation:
1929 {
anthony92c93bd2012-03-19 14:02:47 +00001930 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001931 break;
1932 }
1933 default:
1934 break;
1935 }
1936 if (new_image != (Image *) NULL)
1937 new_image->orientation=TopLeftOrientation;
1938 break;
1939 }
anthonyebb73a22012-03-22 14:25:52 +00001940 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00001941 }
1942 case 'b':
1943 {
anthonyafa3dfc2012-03-03 11:31:30 +00001944 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001945 {
anthony7bcfe7f2012-03-30 14:01:22 +00001946 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001947 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001948 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001949 break;
1950 }
anthonyafa3dfc2012-03-03 11:31:30 +00001951 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001952 {
anthony805a2d42011-09-25 08:25:12 +00001953 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001954 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00001955 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001956 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001957 flags=ParseGeometry(arg1,&geometry_info);
anthony5330ae02012-03-20 14:17:01 +00001958 }
anthony92c93bd2012-03-19 14:02:47 +00001959 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001960 break;
1961 }
anthonyafa3dfc2012-03-03 11:31:30 +00001962 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001963 {
anthony7bcfe7f2012-03-30 14:01:22 +00001964 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001965 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001966 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001967 if ((flags & SigmaValue) == 0)
1968 geometry_info.sigma=1.0;
cristyaa2c16c2012-03-25 22:21:35 +00001969 new_image=BlurImage(_image,geometry_info.rho,geometry_info.sigma,
1970 _exception);
anthony805a2d42011-09-25 08:25:12 +00001971 break;
1972 }
anthonyafa3dfc2012-03-03 11:31:30 +00001973 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001974 {
anthony31f1bf72012-01-30 12:37:22 +00001975 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001976 compose;
1977
1978 const char*
anthony5f867ae2011-10-09 10:28:34 +00001979 value;
1980
anthony7bcfe7f2012-03-30 14:01:22 +00001981 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00001982 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1983
anthony92c93bd2012-03-19 14:02:47 +00001984 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001985 if (value != (const char *) NULL)
1986 compose=(CompositeOperator) ParseCommandOption(
1987 MagickComposeOptions,MagickFalse,value);
1988 else
anthony92c93bd2012-03-19 14:02:47 +00001989 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001990
anthony92c93bd2012-03-19 14:02:47 +00001991 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001992 if ((flags & SigmaValue) == 0)
1993 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00001994 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001995 break;
1996 }
anthonyafa3dfc2012-03-03 11:31:30 +00001997 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001998 {
1999 double
2000 brightness,
2001 contrast;
2002
2003 GeometryInfo
2004 geometry_info;
2005
2006 MagickStatusType
2007 flags;
2008
anthony7bcfe7f2012-03-30 14:01:22 +00002009 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002010 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002011 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002012 brightness=geometry_info.rho;
2013 contrast=0.0;
2014 if ((flags & SigmaValue) != 0)
2015 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00002016 (void) BrightnessContrastImage(_image,brightness,contrast,
2017 _exception);
anthony805a2d42011-09-25 08:25:12 +00002018 break;
2019 }
anthonyebb73a22012-03-22 14:25:52 +00002020 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002021 }
2022 case 'c':
2023 {
anthonyafa3dfc2012-03-03 11:31:30 +00002024 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002025 {
2026 char
2027 *color_correction_collection;
2028
2029 /*
2030 Color correct with a color decision list.
2031 */
anthony92c93bd2012-03-19 14:02:47 +00002032 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002033 if (color_correction_collection == (char *) NULL)
2034 break;
anthony92c93bd2012-03-19 14:02:47 +00002035 (void) ColorDecisionListImage(_image,color_correction_collection,
2036 _exception);
anthony805a2d42011-09-25 08:25:12 +00002037 break;
2038 }
anthonyafa3dfc2012-03-03 11:31:30 +00002039 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002040 {
anthony7bcfe7f2012-03-30 14:01:22 +00002041 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002042 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002043 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002044 if ((flags & SigmaValue) == 0)
2045 geometry_info.sigma=1.0;
2046 if ((flags & XiValue) == 0)
2047 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002048 new_image=CharcoalImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002049 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002050 break;
2051 }
anthonyafa3dfc2012-03-03 11:31:30 +00002052 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002053 {
anthony7bcfe7f2012-03-30 14:01:22 +00002054 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002055 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002056 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
2057 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002058 break;
2059 }
anthonyafa3dfc2012-03-03 11:31:30 +00002060 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002061 {
anthony92c93bd2012-03-19 14:02:47 +00002062 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002063 break;
2064 }
anthonyafa3dfc2012-03-03 11:31:30 +00002065 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002066 {
anthonyafa3dfc2012-03-03 11:31:30 +00002067 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002068 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00002069 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002070 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002071 break;
2072 }
anthonyafa3dfc2012-03-03 11:31:30 +00002073 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002074 {
2075 CacheView
2076 *mask_view;
2077
2078 Image
2079 *mask_image;
2080
2081 register Quantum
2082 *restrict q;
2083
2084 register ssize_t
2085 x;
2086
2087 ssize_t
2088 y;
2089
anthonyafa3dfc2012-03-03 11:31:30 +00002090 if (IfPlusOp) {
2091 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00002092 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002093 break;
2094 }
anthony92c93bd2012-03-19 14:02:47 +00002095 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002096 if (mask_image == (Image *) NULL)
2097 break;
anthony7bcfe7f2012-03-30 14:01:22 +00002098 if (IfMagickFalse(SetImageStorageClass(mask_image,DirectClass,_exception)))
anthony31f1bf72012-01-30 12:37:22 +00002099 break;
anthony5330ae02012-03-20 14:17:01 +00002100 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00002101 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00002102 mask_view=AcquireCacheView(mask_image);
2103 for (y=0; y < (ssize_t) mask_image->rows; y++)
2104 {
2105 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00002106 _exception);
anthony805a2d42011-09-25 08:25:12 +00002107 if (q == (Quantum *) NULL)
2108 break;
2109 for (x=0; x < (ssize_t) mask_image->columns; x++)
2110 {
anthony7bcfe7f2012-03-30 14:01:22 +00002111 if (IfMagickFalse(mask_image->matte))
anthony805a2d42011-09-25 08:25:12 +00002112 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2113 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2114 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2115 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2116 q+=GetPixelChannels(mask_image);
2117 }
anthony7bcfe7f2012-03-30 14:01:22 +00002118 if (IfMagickFalse(SyncCacheViewAuthenticPixels(mask_view,_exception)))
anthony805a2d42011-09-25 08:25:12 +00002119 break;
2120 }
anthonyfd706f92012-01-19 04:22:02 +00002121 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002122 mask_view=DestroyCacheView(mask_view);
2123 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002124 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002125 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002126 break;
2127 }
anthonyafa3dfc2012-03-03 11:31:30 +00002128 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002129 {
anthony92c93bd2012-03-19 14:02:47 +00002130 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002131 break;
2132 }
anthonyafa3dfc2012-03-03 11:31:30 +00002133 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002134 {
anthony7bcfe7f2012-03-30 14:01:22 +00002135 if (IfMagickFalse(IsGeometry(arg1)))
anthony5330ae02012-03-20 14:17:01 +00002136 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002137 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002138 break;
2139 }
anthonyafa3dfc2012-03-03 11:31:30 +00002140 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002141 {
2142 KernelInfo
2143 *kernel;
2144
anthonyfd706f92012-01-19 04:22:02 +00002145 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002146 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002147 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002148 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002149 kernel=DestroyKernelInfo(kernel);
2150 break;
2151 }
anthonyafa3dfc2012-03-03 11:31:30 +00002152 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002153 {
anthony5330ae02012-03-20 14:17:01 +00002154 /* Reduce the number of colors in the image.
2155 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002156 */
anthony92c93bd2012-03-19 14:02:47 +00002157 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2158 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002159 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002160 if ((_image->storage_class == DirectClass) ||
2161 _image->colors > _quantize_info->number_colors)
2162 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002163 else
anthony92c93bd2012-03-19 14:02:47 +00002164 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002165 break;
2166 }
anthonyafa3dfc2012-03-03 11:31:30 +00002167 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002168 {
anthony5330ae02012-03-20 14:17:01 +00002169 /* WARNING: this is both a image_info setting (already done)
2170 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002171
2172 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002173 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002174
anthonyd2cdc862011-10-07 14:07:17 +00002175 Note that +colorspace sets "undefined" or no effect on
2176 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002177 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002178 */
anthony92c93bd2012-03-19 14:02:47 +00002179 (void) TransformImageColorspace(_image,
2180 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2181 _exception);
anthony805a2d42011-09-25 08:25:12 +00002182 break;
2183 }
anthonyafa3dfc2012-03-03 11:31:30 +00002184 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002185 {
anthonydcf3a912012-03-22 14:33:17 +00002186 /* DEPRECIATED: The -/+level provides far more controlled form */
anthony92c93bd2012-03-19 14:02:47 +00002187 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002188 break;
2189 }
anthonyafa3dfc2012-03-03 11:31:30 +00002190 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002191 {
2192 double
2193 black_point,
2194 white_point;
2195
2196 MagickStatusType
2197 flags;
2198
anthony7bcfe7f2012-03-30 14:01:22 +00002199 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002200 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002201 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002202 black_point=geometry_info.rho;
2203 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2204 black_point;
anthonyebb73a22012-03-22 14:25:52 +00002205 if ((flags & PercentValue) != 0) {
anthony92c93bd2012-03-19 14:02:47 +00002206 black_point*=(double) _image->columns*_image->rows/100.0;
2207 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002208 }
anthony92c93bd2012-03-19 14:02:47 +00002209 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002210 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002211 (void) ContrastStretchImage(_image,black_point,white_point,
2212 _exception);
anthony805a2d42011-09-25 08:25:12 +00002213 break;
2214 }
anthonyafa3dfc2012-03-03 11:31:30 +00002215 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002216 {
2217 KernelInfo
2218 *kernel_info;
2219
anthonyfd706f92012-01-19 04:22:02 +00002220 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002221 if (kernel_info == (KernelInfo *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002222 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyf46d4262012-03-26 03:30:34 +00002223 /* kernel_info->bias=_image->bias; -- FUTURE: check this path! */
cristy38419ba2012-04-05 23:47:05 +00002224 ScaleKernelInfo(kernel_info,1.0,NormalizeValue); /* normalize */
anthony92c93bd2012-03-19 14:02:47 +00002225 new_image=ConvolveImage(_image,kernel_info,_exception);
anthony805a2d42011-09-25 08:25:12 +00002226 kernel_info=DestroyKernelInfo(kernel_info);
2227 break;
2228 }
anthonyafa3dfc2012-03-03 11:31:30 +00002229 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002230 {
anthony31f1bf72012-01-30 12:37:22 +00002231 /* WARNING: This can generate multiple images! */
anthony7bcfe7f2012-03-30 14:01:22 +00002232 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002233 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002234 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002235 break;
2236 }
anthonyafa3dfc2012-03-03 11:31:30 +00002237 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002238 {
anthony7bcfe7f2012-03-30 14:01:22 +00002239 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002240 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002241 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2242 _exception);
anthony805a2d42011-09-25 08:25:12 +00002243 break;
2244 }
anthonyebb73a22012-03-22 14:25:52 +00002245 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002246 }
2247 case 'd':
2248 {
anthonyafa3dfc2012-03-03 11:31:30 +00002249 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002250 {
2251 StringInfo
2252 *passkey;
2253
anthony92c93bd2012-03-19 14:02:47 +00002254 passkey=FileToStringInfo(arg1,~0,_exception);
anthonyebb73a22012-03-22 14:25:52 +00002255 if (passkey == (StringInfo *) NULL)
2256 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
2257
2258 (void) PasskeyDecipherImage(_image,passkey,_exception);
2259 passkey=DestroyStringInfo(passkey);
anthony805a2d42011-09-25 08:25:12 +00002260 break;
2261 }
anthonyafa3dfc2012-03-03 11:31:30 +00002262 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002263 {
anthony92c93bd2012-03-19 14:02:47 +00002264 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002265 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002266
anthonydcf510d2011-10-30 13:51:40 +00002267 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2268 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002269
anthonyfd706f92012-01-19 04:22:02 +00002270 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002271 */
anthony92c93bd2012-03-19 14:02:47 +00002272 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002273 break;
2274 }
anthonyafa3dfc2012-03-03 11:31:30 +00002275 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002276 {
2277 double
2278 threshold;
2279
anthonyebb73a22012-03-22 14:25:52 +00002280 if (IfNormalOp) {
anthony7bcfe7f2012-03-30 14:01:22 +00002281 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00002282 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002283 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyebb73a22012-03-22 14:25:52 +00002284 }
anthonyafa3dfc2012-03-03 11:31:30 +00002285 else
2286 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002287 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002288 break;
2289 }
anthonyafa3dfc2012-03-03 11:31:30 +00002290 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002291 {
anthony92c93bd2012-03-19 14:02:47 +00002292 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002293 break;
2294 }
anthonyafa3dfc2012-03-03 11:31:30 +00002295 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002296 {
2297 char
2298 *args,
2299 token[MaxTextExtent];
2300
2301 const char
2302 *p;
2303
anthony805a2d42011-09-25 08:25:12 +00002304 double
2305 *arguments;
2306
2307 register ssize_t
2308 x;
2309
2310 size_t
2311 number_arguments;
2312
anthony2a0ec8c2012-03-24 04:35:56 +00002313 parse = ParseCommandOption(MagickDistortOptions,MagickFalse,arg1);
2314 if ( parse < 0 )
anthonyebb73a22012-03-22 14:25:52 +00002315 CLIWandExceptArgBreak(OptionError,"UnrecognizedDistortMethod",
2316 option,arg1);
anthony2a0ec8c2012-03-24 04:35:56 +00002317 if ((DistortImageMethod) parse == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002318 {
anthony80c37752012-01-16 01:03:11 +00002319 double
2320 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002321 /* Special Case - Argument is actually a resize geometry!
2322 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002323 ** FUTURE: make a separate special resize operator
anthonyfe1aa782012-03-24 13:43:04 +00002324 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002325 if (IfMagickFalse(IsGeometry(arg2)))
anthonyebb73a22012-03-22 14:25:52 +00002326 CLIWandExceptArgBreak(OptionError,"InvalidGeometry",
2327 option,arg2);
2328 (void) ParseRegionGeometry(_image,arg2,&geometry,_exception);
anthony80c37752012-01-16 01:03:11 +00002329 resize_args[0]=(double) geometry.width;
2330 resize_args[1]=(double) geometry.height;
anthony2a0ec8c2012-03-24 04:35:56 +00002331 new_image=DistortImage(_image,(DistortImageMethod) parse,
2332 (size_t)2,resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002333 break;
2334 }
anthonyfd706f92012-01-19 04:22:02 +00002335 /* handle percent arguments */
anthonyebb73a22012-03-22 14:25:52 +00002336 args=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00002337 if (args == (char *) NULL)
2338 break;
anthonyfd706f92012-01-19 04:22:02 +00002339 /* convert arguments into an array of doubles
2340 FUTURE: make this a separate function.
2341 Also make use of new 'sentinal' feature to avoid need for
2342 tokenization.
2343 */
anthony805a2d42011-09-25 08:25:12 +00002344 p=(char *) args;
2345 for (x=0; *p != '\0'; x++)
2346 {
2347 GetMagickToken(p,&p,token);
2348 if (*token == ',')
2349 GetMagickToken(p,&p,token);
2350 }
2351 number_arguments=(size_t) x;
2352 arguments=(double *) AcquireQuantumMemory(number_arguments,
2353 sizeof(*arguments));
2354 if (arguments == (double *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00002355 CLIWandExceptionBreak(ResourceLimitFatalError,
2356 "MemoryAllocationFailed",option);
anthony805a2d42011-09-25 08:25:12 +00002357 (void) ResetMagickMemory(arguments,0,number_arguments*
anthonyebb73a22012-03-22 14:25:52 +00002358 sizeof(*arguments));
anthony805a2d42011-09-25 08:25:12 +00002359 p=(char *) args;
2360 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2361 {
2362 GetMagickToken(p,&p,token);
2363 if (*token == ',')
2364 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002365 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002366 }
2367 args=DestroyString(args);
anthony2a0ec8c2012-03-24 04:35:56 +00002368 new_image=DistortImage(_image,(DistortImageMethod) parse,
2369 number_arguments,arguments,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002370 arguments=(double *) RelinquishMagickMemory(arguments);
2371 break;
2372 }
anthonyafa3dfc2012-03-03 11:31:30 +00002373 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002374 {
anthony92c93bd2012-03-19 14:02:47 +00002375 (void) CloneString(&_draw_info->primitive,arg1);
2376 (void) DrawImage(_image,_draw_info,_exception);
2377 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002378 break;
2379 }
anthonyebb73a22012-03-22 14:25:52 +00002380 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002381 }
2382 case 'e':
2383 {
anthonyafa3dfc2012-03-03 11:31:30 +00002384 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002385 {
anthony7bcfe7f2012-03-30 14:01:22 +00002386 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002387 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002388 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002389 if ((flags & SigmaValue) == 0)
2390 geometry_info.sigma=1.0;
anthony2a0ec8c2012-03-24 04:35:56 +00002391 new_image=EdgeImage(_image,geometry_info.rho,geometry_info.sigma,
2392 _exception);
anthony805a2d42011-09-25 08:25:12 +00002393 break;
2394 }
anthonyafa3dfc2012-03-03 11:31:30 +00002395 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002396 {
anthony7bcfe7f2012-03-30 14:01:22 +00002397 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002398 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002399 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002400 if ((flags & SigmaValue) == 0)
2401 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002402 new_image=EmbossImage(_image,geometry_info.rho,
2403 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002404 break;
2405 }
anthonyafa3dfc2012-03-03 11:31:30 +00002406 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002407 {
2408 StringInfo
2409 *passkey;
2410
anthony92c93bd2012-03-19 14:02:47 +00002411 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002412 if (passkey != (StringInfo *) NULL)
2413 {
anthony92c93bd2012-03-19 14:02:47 +00002414 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002415 passkey=DestroyStringInfo(passkey);
2416 }
2417 break;
2418 }
anthonyafa3dfc2012-03-03 11:31:30 +00002419 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002420 {
anthony92c93bd2012-03-19 14:02:47 +00002421 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002422 break;
2423 }
anthonyafa3dfc2012-03-03 11:31:30 +00002424 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002425 {
anthony92c93bd2012-03-19 14:02:47 +00002426 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002427 break;
2428 }
anthonyafa3dfc2012-03-03 11:31:30 +00002429 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002430 {
2431 double
2432 constant;
2433
anthony2a0ec8c2012-03-24 04:35:56 +00002434 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
2435 if ( parse < 0 )
2436 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
2437 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00002438 if (IfMagickFalse(IsGeometry(arg2)))
anthony2a0ec8c2012-03-24 04:35:56 +00002439 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00002440 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony2a0ec8c2012-03-24 04:35:56 +00002441 (void) EvaluateImage(_image,(MagickEvaluateOperator)parse,constant,
2442 _exception);
anthony805a2d42011-09-25 08:25:12 +00002443 break;
2444 }
anthonyafa3dfc2012-03-03 11:31:30 +00002445 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002446 {
anthony7bcfe7f2012-03-30 14:01:22 +00002447 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002448 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002449 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002450 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002451 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002452 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002453 geometry.height=_image->rows;
2454 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002455 break;
2456 }
anthonyebb73a22012-03-22 14:25:52 +00002457 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002458 }
2459 case 'f':
2460 {
anthonyafa3dfc2012-03-03 11:31:30 +00002461 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002462 {
anthony31f1bf72012-01-30 12:37:22 +00002463 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002464 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002465 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002466 break;
2467 }
anthony92c93bd2012-03-19 14:02:47 +00002468 (void) SetImageArtifact(_image,"identify:features","true");
2469 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002470 break;
2471 }
anthonyafa3dfc2012-03-03 11:31:30 +00002472 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002473 {
anthony92c93bd2012-03-19 14:02:47 +00002474 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002475 break;
2476 }
anthonyafa3dfc2012-03-03 11:31:30 +00002477 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002478 {
anthony92c93bd2012-03-19 14:02:47 +00002479 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002480 break;
2481 }
anthonyafa3dfc2012-03-03 11:31:30 +00002482 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002483 {
2484 PixelInfo
2485 target;
2486
anthony7bcfe7f2012-03-30 14:01:22 +00002487 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002488 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002489 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2490 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2491 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2492 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002493 break;
2494 }
anthonyafa3dfc2012-03-03 11:31:30 +00002495 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002496 {
2497 FrameInfo
2498 frame_info;
2499
anthony31f1bf72012-01-30 12:37:22 +00002500 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002501 compose;
2502
2503 const char*
2504 value;
2505
anthony92c93bd2012-03-19 14:02:47 +00002506 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002507 if (value != (const char *) NULL)
2508 compose=(CompositeOperator) ParseCommandOption(
2509 MagickComposeOptions,MagickFalse,value);
2510 else
anthony92c93bd2012-03-19 14:02:47 +00002511 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002512
anthony7bcfe7f2012-03-30 14:01:22 +00002513 if (IfMagickFalse(IsGeometry(arg1)))
anthony2a0ec8c2012-03-24 04:35:56 +00002514 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002515 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002516 frame_info.width=geometry.width;
2517 frame_info.height=geometry.height;
2518 if ((flags & HeightValue) == 0)
2519 frame_info.height=geometry.width;
2520 frame_info.outer_bevel=geometry.x;
2521 frame_info.inner_bevel=geometry.y;
2522 frame_info.x=(ssize_t) frame_info.width;
2523 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002524 frame_info.width=_image->columns+2*frame_info.width;
2525 frame_info.height=_image->rows+2*frame_info.height;
2526 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002527 break;
2528 }
anthonyafa3dfc2012-03-03 11:31:30 +00002529 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002530 {
2531 char
2532 *arguments,
2533 token[MaxTextExtent];
2534
2535 const char
2536 *p;
2537
2538 double
2539 *parameters;
2540
anthony805a2d42011-09-25 08:25:12 +00002541 register ssize_t
2542 x;
2543
2544 size_t
2545 number_parameters;
2546
cristy947cb4c2011-10-20 18:41:46 +00002547 /*
2548 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002549 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002550 */
anthony2a0ec8c2012-03-24 04:35:56 +00002551 parse=ParseCommandOption(MagickFunctionOptions,MagickFalse,arg1);
2552 if ( parse < 0 )
2553 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2554 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002555 arguments=InterpretImageProperties(_image_info,_image,arg2,
2556 _exception);
anthony805a2d42011-09-25 08:25:12 +00002557 if (arguments == (char *) NULL)
anthony2a0ec8c2012-03-24 04:35:56 +00002558 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthony805a2d42011-09-25 08:25:12 +00002559 p=(char *) arguments;
2560 for (x=0; *p != '\0'; x++)
2561 {
2562 GetMagickToken(p,&p,token);
2563 if (*token == ',')
2564 GetMagickToken(p,&p,token);
2565 }
2566 number_parameters=(size_t) x;
2567 parameters=(double *) AcquireQuantumMemory(number_parameters,
2568 sizeof(*parameters));
2569 if (parameters == (double *) NULL)
2570 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002571 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002572 (void) ResetMagickMemory(parameters,0,number_parameters*
2573 sizeof(*parameters));
2574 p=(char *) arguments;
anthony2a0ec8c2012-03-24 04:35:56 +00002575 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++) {
anthony805a2d42011-09-25 08:25:12 +00002576 GetMagickToken(p,&p,token);
2577 if (*token == ',')
2578 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002579 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002580 }
2581 arguments=DestroyString(arguments);
anthony2a0ec8c2012-03-24 04:35:56 +00002582 (void) FunctionImage(_image,(MagickFunction)parse,number_parameters,
2583 parameters,_exception);
anthony805a2d42011-09-25 08:25:12 +00002584 parameters=(double *) RelinquishMagickMemory(parameters);
2585 break;
2586 }
anthonyebb73a22012-03-22 14:25:52 +00002587 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002588 }
2589 case 'g':
2590 {
anthonyafa3dfc2012-03-03 11:31:30 +00002591 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002592 {
anthony7bcfe7f2012-03-30 14:01:22 +00002593 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002594 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyafa3dfc2012-03-03 11:31:30 +00002595 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002596 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2597 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002598 else
anthony92c93bd2012-03-19 14:02:47 +00002599 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002600 break;
2601 }
anthonyafa3dfc2012-03-03 11:31:30 +00002602 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2603 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002604 {
anthony7bcfe7f2012-03-30 14:01:22 +00002605 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002606 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002607 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002608 if ((flags & SigmaValue) == 0)
2609 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002610 new_image=GaussianBlurImage(_image,geometry_info.rho,
2611 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002612 break;
2613 }
anthonyafa3dfc2012-03-03 11:31:30 +00002614 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002615 {
anthonyfd706f92012-01-19 04:22:02 +00002616 /*
anthony31f1bf72012-01-30 12:37:22 +00002617 Record Image offset for composition. (A Setting)
anthonyfe1aa782012-03-24 13:43:04 +00002618 Resize last _image. (ListOperator) -- DEPRECIATE
anthony31f1bf72012-01-30 12:37:22 +00002619 FUTURE: Why if no 'offset' does this resize ALL images?
2620 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002621 */
anthonyafa3dfc2012-03-03 11:31:30 +00002622 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002623 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002624 if (_image->geometry != (char *) NULL)
2625 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002626 break;
2627 }
anthony7bcfe7f2012-03-30 14:01:22 +00002628 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002629 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002630 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002631 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002632 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002633 else
anthony92c93bd2012-03-19 14:02:47 +00002634 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00002635 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00002636 break;
2637 }
anthonyebb73a22012-03-22 14:25:52 +00002638 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002639 }
2640 case 'h':
2641 {
anthonyafa3dfc2012-03-03 11:31:30 +00002642 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002643 {
anthony92c93bd2012-03-19 14:02:47 +00002644 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002645 break;
2646 }
anthonyebb73a22012-03-22 14:25:52 +00002647 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002648 }
2649 case 'i':
2650 {
anthonyafa3dfc2012-03-03 11:31:30 +00002651 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002652 {
anthony31f1bf72012-01-30 12:37:22 +00002653 const char
2654 *format,
anthony805a2d42011-09-25 08:25:12 +00002655 *text;
2656
anthony92c93bd2012-03-19 14:02:47 +00002657 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002658 if (format == (char *) NULL)
2659 {
anthony92c93bd2012-03-19 14:02:47 +00002660 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2661 _exception);
anthony805a2d42011-09-25 08:25:12 +00002662 break;
2663 }
anthony92c93bd2012-03-19 14:02:47 +00002664 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002665 if (text == (char *) NULL)
2666 break;
2667 (void) fputs(text,stdout);
2668 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002669 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002670 break;
2671 }
anthonyafa3dfc2012-03-03 11:31:30 +00002672 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002673 {
anthony7bcfe7f2012-03-30 14:01:22 +00002674 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002675 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002676 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002677 new_image=ImplodeImage(_image,geometry_info.rho,
2678 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002679 break;
2680 }
anthonyafa3dfc2012-03-03 11:31:30 +00002681 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002682 {
anthonyfe1aa782012-03-24 13:43:04 +00002683 /* FUTURE: New to IMv7
2684 Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002685 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002686 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002687 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2688 new_image=InterpolativeResizeImage(_image,geometry.width,
2689 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002690 break;
2691 }
anthonyebb73a22012-03-22 14:25:52 +00002692 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002693 }
2694 case 'l':
2695 {
anthonyafa3dfc2012-03-03 11:31:30 +00002696 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002697 {
anthony7bcfe7f2012-03-30 14:01:22 +00002698 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002699 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002700 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002701 if ((flags & PercentValue) != 0)
2702 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002703 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002704 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002705 _exception);
anthony805a2d42011-09-25 08:25:12 +00002706 break;
2707 }
anthonyafa3dfc2012-03-03 11:31:30 +00002708 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002709 {
2710 MagickRealType
2711 black_point,
2712 gamma,
2713 white_point;
2714
2715 MagickStatusType
2716 flags;
2717
anthony7bcfe7f2012-03-30 14:01:22 +00002718 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002719 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002720 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002721 black_point=geometry_info.rho;
2722 white_point=(MagickRealType) QuantumRange;
2723 if ((flags & SigmaValue) != 0)
2724 white_point=geometry_info.sigma;
2725 gamma=1.0;
2726 if ((flags & XiValue) != 0)
2727 gamma=geometry_info.xi;
2728 if ((flags & PercentValue) != 0)
2729 {
2730 black_point*=(MagickRealType) (QuantumRange/100.0);
2731 white_point*=(MagickRealType) (QuantumRange/100.0);
2732 }
2733 if ((flags & SigmaValue) == 0)
2734 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002735 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002736 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002737 else
anthony92c93bd2012-03-19 14:02:47 +00002738 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002739 break;
2740 }
anthonyafa3dfc2012-03-03 11:31:30 +00002741 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002742 {
2743 char
2744 token[MaxTextExtent];
2745
2746 const char
2747 *p;
2748
2749 PixelInfo
2750 black_point,
2751 white_point;
2752
anthonyfd706f92012-01-19 04:22:02 +00002753 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002754 GetMagickToken(p,&p,token); /* get black point color */
2755 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002756 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002757 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002758 else
cristy269c9412011-10-13 23:41:15 +00002759 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002760 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002761 if (isalpha((int) token[0]) || (token[0] == '#'))
2762 GetMagickToken(p,&p,token);
2763 if (*token == '\0')
2764 white_point=black_point; /* set everything to that color */
2765 else
2766 {
2767 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2768 GetMagickToken(p,&p,token); /* Get white point color. */
2769 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002770 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002771 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002772 else
cristy269c9412011-10-13 23:41:15 +00002773 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002774 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002775 }
anthony92c93bd2012-03-19 14:02:47 +00002776 (void) LevelImageColors(_image,&black_point,&white_point,
2777 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002778 break;
2779 }
anthonyafa3dfc2012-03-03 11:31:30 +00002780 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002781 {
2782 double
2783 black_point,
2784 white_point;
2785
2786 MagickStatusType
2787 flags;
2788
anthony7bcfe7f2012-03-30 14:01:22 +00002789 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002790 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002791 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002792 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002793 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002794 if ((flags & SigmaValue) != 0)
2795 white_point=geometry_info.sigma;
2796 if ((flags & PercentValue) != 0)
2797 {
anthony92c93bd2012-03-19 14:02:47 +00002798 black_point*=(double) _image->columns*_image->rows/100.0;
2799 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002800 }
2801 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002802 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002803 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002804 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002805 break;
2806 }
anthonyafa3dfc2012-03-03 11:31:30 +00002807 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002808 {
anthonyfe1aa782012-03-24 13:43:04 +00002809 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00002810 if (IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00002811 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002812 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002813 if ((flags & XValue) == 0)
2814 geometry.x=1;
2815 if ((flags & YValue) == 0)
2816 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002817 new_image=LiquidRescaleImage(_image,geometry.width,
2818 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002819 break;
2820 }
anthonyafa3dfc2012-03-03 11:31:30 +00002821 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002822 {
anthony92c93bd2012-03-19 14:02:47 +00002823 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002824 break;
2825 }
anthonyebb73a22012-03-22 14:25:52 +00002826 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002827 }
2828 case 'm':
2829 {
anthonyafa3dfc2012-03-03 11:31:30 +00002830 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002831 {
2832 Image
2833 *remap_image;
2834
anthony31f1bf72012-01-30 12:37:22 +00002835 /* DEPRECIATED use -remap */
anthony92c93bd2012-03-19 14:02:47 +00002836 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002837 if (remap_image == (Image *) NULL)
2838 break;
anthony92c93bd2012-03-19 14:02:47 +00002839 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002840 remap_image=DestroyImage(remap_image);
2841 break;
2842 }
anthonyafa3dfc2012-03-03 11:31:30 +00002843 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002844 {
2845 Image
2846 *mask;
2847
anthonyafa3dfc2012-03-03 11:31:30 +00002848 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002849 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002850 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002851 break;
2852 }
anthony5330ae02012-03-20 14:17:01 +00002853 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002854 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002855 if (mask == (Image *) NULL)
2856 break;
anthony92c93bd2012-03-19 14:02:47 +00002857 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002858 mask=DestroyImage(mask);
2859 break;
2860 }
anthonyafa3dfc2012-03-03 11:31:30 +00002861 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002862 {
anthony31f1bf72012-01-30 12:37:22 +00002863 /* DEPRECIATED */
anthony92c93bd2012-03-19 14:02:47 +00002864 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2865 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002866 break;
2867 }
anthonya3ef4ed2012-03-17 06:52:53 +00002868 if (LocaleCompare("median",option+1) == 0)
2869 {
2870 /* DEPRECIATED - use -statistic Median */
anthony7bcfe7f2012-03-30 14:01:22 +00002871 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002872 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonya3ef4ed2012-03-17 06:52:53 +00002873 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2874 break;
2875 }
anthonyafa3dfc2012-03-03 11:31:30 +00002876 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002877 {
anthony7bcfe7f2012-03-30 14:01:22 +00002878 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002879 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002880 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002881 if ((flags & SigmaValue) == 0)
2882 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002883 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2884 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002885 break;
2886 }
anthonyafa3dfc2012-03-03 11:31:30 +00002887 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002888 {
anthony7bcfe7f2012-03-30 14:01:22 +00002889 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002890 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002891 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002892 break;
2893 }
anthonyafa3dfc2012-03-03 11:31:30 +00002894 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002895 {
anthony92c93bd2012-03-19 14:02:47 +00002896 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002897 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002898 break;
2899 }
anthonyafa3dfc2012-03-03 11:31:30 +00002900 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002901 {
anthony92c93bd2012-03-19 14:02:47 +00002902 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002903 break;
2904 }
anthonyafa3dfc2012-03-03 11:31:30 +00002905 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002906 {
2907 char
2908 token[MaxTextExtent];
2909
2910 const char
2911 *p;
2912
2913 KernelInfo
2914 *kernel;
2915
anthony805a2d42011-09-25 08:25:12 +00002916 ssize_t
2917 iterations;
2918
anthonyfd706f92012-01-19 04:22:02 +00002919 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002920 GetMagickToken(p,&p,token);
anthony7bc87992012-03-25 02:32:51 +00002921 parse=ParseCommandOption(MagickMorphologyOptions,MagickFalse,token);
2922 if ( parse < 0 )
2923 CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction",
2924 option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002925 iterations=1L;
2926 GetMagickToken(p,&p,token);
2927 if ((*p == ':') || (*p == ','))
2928 GetMagickToken(p,&p,token);
2929 if ((*p != '\0'))
2930 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002931 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002932 if (kernel == (KernelInfo *) NULL)
anthony7bc87992012-03-25 02:32:51 +00002933 CLIWandExceptArgBreak(OptionError,"UnabletoParseKernel",
2934 option,arg2);
2935 new_image=MorphologyImage(_image,(MorphologyMethod)parse,
2936 iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002937 kernel=DestroyKernelInfo(kernel);
2938 break;
2939 }
anthonyafa3dfc2012-03-03 11:31:30 +00002940 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002941 {
anthony7bcfe7f2012-03-30 14:01:22 +00002942 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002943 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002944 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002945 if ((flags & SigmaValue) == 0)
2946 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002947 new_image=MotionBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00002948 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00002949 break;
2950 }
anthonyebb73a22012-03-22 14:25:52 +00002951 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00002952 }
2953 case 'n':
2954 {
anthonyafa3dfc2012-03-03 11:31:30 +00002955 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002956 {
anthony92c93bd2012-03-19 14:02:47 +00002957 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002958 break;
2959 }
anthonyafa3dfc2012-03-03 11:31:30 +00002960 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002961 {
anthonyafa3dfc2012-03-03 11:31:30 +00002962 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002963 {
anthony7bcfe7f2012-03-30 14:01:22 +00002964 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00002965 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00002966 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002967 if ((flags & SigmaValue) == 0)
2968 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002969 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2970 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002971 }
2972 else
2973 {
anthony31f1bf72012-01-30 12:37:22 +00002974 double
2975 attenuate;
2976
2977 const char*
2978 value;
2979
anthony7bc87992012-03-25 02:32:51 +00002980 parse=ParseCommandOption(MagickNoiseOptions,MagickFalse,arg1);
2981 if ( parse < 0 )
2982 CLIWandExceptArgBreak(OptionError,"UnrecognizedNoiseType",
2983 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002984 value=GetImageOption(_image_info,"attenuate");
anthony31f1bf72012-01-30 12:37:22 +00002985 if (value != (const char *) NULL)
2986 attenuate=StringToDouble(value,(char **) NULL);
2987 else
2988 attenuate=1.0;
2989
anthony7bc87992012-03-25 02:32:51 +00002990 new_image=AddNoiseImage(_image,(NoiseType)parse,attenuate,
2991 _exception);
anthony805a2d42011-09-25 08:25:12 +00002992 }
2993 break;
2994 }
anthonyafa3dfc2012-03-03 11:31:30 +00002995 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002996 {
anthony92c93bd2012-03-19 14:02:47 +00002997 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002998 break;
2999 }
anthonyebb73a22012-03-22 14:25:52 +00003000 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003001 }
3002 case 'o':
3003 {
anthonyafa3dfc2012-03-03 11:31:30 +00003004 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003005 {
3006 PixelInfo
3007 target;
3008
anthony92c93bd2012-03-19 14:02:47 +00003009 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3010 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
3011 _exception);
anthony805a2d42011-09-25 08:25:12 +00003012 break;
3013 }
anthonyafa3dfc2012-03-03 11:31:30 +00003014 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003015 {
anthony92c93bd2012-03-19 14:02:47 +00003016 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003017 break;
3018 }
anthonyebb73a22012-03-22 14:25:52 +00003019 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003020 }
3021 case 'p':
3022 {
anthonyafa3dfc2012-03-03 11:31:30 +00003023 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003024 {
anthonyfd706f92012-01-19 04:22:02 +00003025 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003026 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
3027 _exception);
anthony805a2d42011-09-25 08:25:12 +00003028 break;
3029 }
anthonyafa3dfc2012-03-03 11:31:30 +00003030 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003031 {
cristye9e3d382011-12-14 01:50:13 +00003032 const char
3033 *caption;
3034
anthony805a2d42011-09-25 08:25:12 +00003035 double
3036 angle;
3037
anthony7bc87992012-03-25 02:32:51 +00003038 if (IfPlusOp) {
anthonyf42014d2012-03-25 09:53:06 +00003039 RandomInfo
3040 *random_info;
anthony805a2d42011-09-25 08:25:12 +00003041
anthonyf42014d2012-03-25 09:53:06 +00003042 random_info=AcquireRandomInfo();
3043 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
3044 random_info=DestroyRandomInfo(random_info);
3045 }
anthony7bc87992012-03-25 02:32:51 +00003046 else {
anthony7bcfe7f2012-03-30 14:01:22 +00003047 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003048 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3049 flags=ParseGeometry(arg1,&geometry_info);
3050 angle=geometry_info.rho;
3051 }
anthony92c93bd2012-03-19 14:02:47 +00003052 caption=GetImageProperty(_image,"caption",_exception);
3053 new_image=PolaroidImage(_image,_draw_info,caption,angle,
3054 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003055 break;
3056 }
anthonyafa3dfc2012-03-03 11:31:30 +00003057 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003058 {
anthony7bcfe7f2012-03-30 14:01:22 +00003059 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00003060 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003061 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003062 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
3063 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00003064 break;
3065 }
anthonyafa3dfc2012-03-03 11:31:30 +00003066 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003067 {
anthony31f1bf72012-01-30 12:37:22 +00003068 /* FUTURE: should be a 'Genesis' option?
3069 Option however is also in WandSettingOptionInfo()
anthony7bc87992012-03-25 02:32:51 +00003070 Why???
cristy947cb4c2011-10-20 18:41:46 +00003071 */
anthony7bc87992012-03-25 02:32:51 +00003072 parse=ParseCommandOption(MagickPreviewOptions, MagickFalse,arg1);
3073 if ( parse < 0 )
3074 CLIWandExceptArgBreak(OptionError,"UnrecognizedPreviewType",
3075 option,arg1);
3076 new_image=PreviewImage(_image,(PreviewType)parse,_exception);
anthony805a2d42011-09-25 08:25:12 +00003077 break;
3078 }
anthonyafa3dfc2012-03-03 11:31:30 +00003079 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003080 {
3081 const char
3082 *name;
3083
3084 const StringInfo
3085 *profile;
3086
3087 Image
3088 *profile_image;
3089
3090 ImageInfo
3091 *profile_info;
3092
anthonyafa3dfc2012-03-03 11:31:30 +00003093 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00003094 { /* Remove a profile from the _image. */
3095 (void) ProfileImage(_image,arg1,(const unsigned char *)
3096 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003097 break;
3098 }
anthony92c93bd2012-03-19 14:02:47 +00003099 /* Associate a profile with the _image. */
3100 profile_info=CloneImageInfo(_image_info);
3101 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00003102 if (profile != (StringInfo *) NULL)
3103 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00003104 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003105 profile_info=DestroyImageInfo(profile_info);
3106 if (profile_image == (Image *) NULL)
3107 {
3108 StringInfo
3109 *profile;
3110
anthony92c93bd2012-03-19 14:02:47 +00003111 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00003112 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00003113 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00003114 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003115 if (profile != (StringInfo *) NULL)
3116 {
anthony92c93bd2012-03-19 14:02:47 +00003117 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00003118 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00003119 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003120 profile=DestroyStringInfo(profile);
3121 }
3122 profile_info=DestroyImageInfo(profile_info);
3123 break;
3124 }
3125 ResetImageProfileIterator(profile_image);
3126 name=GetNextImageProfile(profile_image);
3127 while (name != (const char *) NULL)
3128 {
3129 profile=GetImageProfile(profile_image,name);
3130 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003131 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
3132 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00003133 name=GetNextImageProfile(profile_image);
3134 }
3135 profile_image=DestroyImage(profile_image);
3136 break;
3137 }
anthonyebb73a22012-03-22 14:25:52 +00003138 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003139 }
anthony805a2d42011-09-25 08:25:12 +00003140 case 'r':
3141 {
anthonyafa3dfc2012-03-03 11:31:30 +00003142 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003143 {
anthony7bcfe7f2012-03-30 14:01:22 +00003144 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003145 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003146 flags=ParseGeometry(arg1,&geometry_info);
cristyaa2c16c2012-03-25 22:21:35 +00003147 new_image=RadialBlurImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003148 break;
3149 }
anthonyafa3dfc2012-03-03 11:31:30 +00003150 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003151 {
anthony7bcfe7f2012-03-30 14:01:22 +00003152 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003153 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003154 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003155 if ((flags & SigmaValue) == 0)
3156 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00003157 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003158 break;
3159 }
anthonyafa3dfc2012-03-03 11:31:30 +00003160 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003161 {
anthony7bcfe7f2012-03-30 14:01:22 +00003162 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003163 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003164 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003165 break;
3166 }
anthonyafa3dfc2012-03-03 11:31:30 +00003167 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003168 {
3169 Image
3170 *remap_image;
3171
anthony92c93bd2012-03-19 14:02:47 +00003172 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003173 if (remap_image == (Image *) NULL)
3174 break;
anthony92c93bd2012-03-19 14:02:47 +00003175 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003176 remap_image=DestroyImage(remap_image);
3177 break;
3178 }
anthonyafa3dfc2012-03-03 11:31:30 +00003179 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003180 {
anthonyafa3dfc2012-03-03 11:31:30 +00003181 if (IfNormalOp)
cristy0d0de742012-03-25 19:32:48 +00003182 {
anthony7bcfe7f2012-03-30 14:01:22 +00003183 if (IfMagickFalse(IsGeometry(arg1)))
cristy0d0de742012-03-25 19:32:48 +00003184 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3185 arg1);
3186 (void) ResetImagePage(_image,arg1);
3187 }
anthony31f1bf72012-01-30 12:37:22 +00003188 else
anthony92c93bd2012-03-19 14:02:47 +00003189 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003190 break;
3191 }
anthonyafa3dfc2012-03-03 11:31:30 +00003192 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003193 {
anthonyf46d4262012-03-26 03:30:34 +00003194 /* FUTURE: Roll into a resize special operation */
anthony7bcfe7f2012-03-30 14:01:22 +00003195 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003196 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003197 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003198 if ((flags & SigmaValue) == 0)
3199 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003200 new_image=ResampleImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003201 geometry_info.sigma,_image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003202 break;
3203 }
anthonyafa3dfc2012-03-03 11:31:30 +00003204 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003205 {
anthony7bcfe7f2012-03-30 14:01:22 +00003206 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003207 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003208 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3209 new_image=ResizeImage(_image,geometry.width,geometry.height,
cristyaa2c16c2012-03-25 22:21:35 +00003210 _image->filter,_exception);
anthony805a2d42011-09-25 08:25:12 +00003211 break;
3212 }
anthonyafa3dfc2012-03-03 11:31:30 +00003213 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003214 {
anthony7bcfe7f2012-03-30 14:01:22 +00003215 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003216 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003217 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3218 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003219 break;
3220 }
anthonyafa3dfc2012-03-03 11:31:30 +00003221 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003222 {
anthony7bcfe7f2012-03-30 14:01:22 +00003223 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003224 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
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 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003229 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003230 break;
anthonyfd706f92012-01-19 04:22:02 +00003231 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003232 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003233 break;
3234 }
anthonyebb73a22012-03-22 14:25:52 +00003235 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003236 }
3237 case 's':
3238 {
anthonyafa3dfc2012-03-03 11:31:30 +00003239 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003240 {
anthonyfe1aa782012-03-24 13:43:04 +00003241 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003242 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003243 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003244 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3245 new_image=SampleImage(_image,geometry.width,geometry.height,
3246 _exception);
anthony805a2d42011-09-25 08:25:12 +00003247 break;
3248 }
anthonyafa3dfc2012-03-03 11:31:30 +00003249 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003250 {
anthonyfe1aa782012-03-24 13:43:04 +00003251 /* FUTURE: Roll into a resize special operator */
anthony7bcfe7f2012-03-30 14:01:22 +00003252 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003253 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003254 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3255 new_image=ScaleImage(_image,geometry.width,geometry.height,
3256 _exception);
anthony805a2d42011-09-25 08:25:12 +00003257 break;
3258 }
anthonyf42014d2012-03-25 09:53:06 +00003259 if (LocaleCompare("segment",option+1) == 0)
3260 {
anthony7bcfe7f2012-03-30 14:01:22 +00003261 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003262 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3263 flags=ParseGeometry(arg1,&geometry_info);
3264 if ((flags & SigmaValue) == 0)
3265 geometry_info.sigma=1.0;
3266 (void) SegmentImage(_image,_image->colorspace,
3267 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3268 _exception);
3269 break;
3270 }
anthonyafa3dfc2012-03-03 11:31:30 +00003271 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003272 {
anthony7bcfe7f2012-03-30 14:01:22 +00003273 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003274 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003275 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003276 if ((flags & PercentValue) != 0)
3277 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003278 new_image=SelectiveBlurImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003279 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003280 break;
3281 }
anthonyafa3dfc2012-03-03 11:31:30 +00003282 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003283 {
anthony31f1bf72012-01-30 12:37:22 +00003284 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003285 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003286 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003287 break;
3288 }
anthonyafa3dfc2012-03-03 11:31:30 +00003289 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003290 {
anthony7bcfe7f2012-03-30 14:01:22 +00003291 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003292 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
3293 new_image=SepiaToneImage(_image,StringToDoubleInterval(arg1,
3294 (double) QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003295 break;
3296 }
anthonyafa3dfc2012-03-03 11:31:30 +00003297 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003298 {
3299 char
3300 *value;
3301
anthonyf42014d2012-03-25 09:53:06 +00003302 if (IfPlusOp) {
anthonyfd706f92012-01-19 04:22:02 +00003303 if (LocaleNCompare(arg1,"registry:",9) == 0)
3304 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003305 else
anthony31f1bf72012-01-30 12:37:22 +00003306 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003307 {
anthony92c93bd2012-03-19 14:02:47 +00003308 (void) DeleteImageOption(_image_info,arg1+7);
3309 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003310 }
3311 else
anthony92c93bd2012-03-19 14:02:47 +00003312 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003313 break;
3314 }
anthonyf42014d2012-03-25 09:53:06 +00003315 value=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003316 if (value == (char *) NULL)
3317 break;
anthonyfd706f92012-01-19 04:22:02 +00003318 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthonyf42014d2012-03-25 09:53:06 +00003319 (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003320 else
anthonyfd706f92012-01-19 04:22:02 +00003321 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003322 {
anthony92c93bd2012-03-19 14:02:47 +00003323 (void) SetImageOption(_image_info,arg1+7,value);
3324 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003325 }
3326 else
anthony92c93bd2012-03-19 14:02:47 +00003327 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003328 value=DestroyString(value);
3329 break;
3330 }
anthonyafa3dfc2012-03-03 11:31:30 +00003331 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003332 {
anthony7bcfe7f2012-03-30 14:01:22 +00003333 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003334 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003335 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003336 if ((flags & SigmaValue) == 0)
3337 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003338 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3339 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003340 break;
3341 }
anthonyafa3dfc2012-03-03 11:31:30 +00003342 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003343 {
anthony7bcfe7f2012-03-30 14:01:22 +00003344 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003345 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003346 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003347 if ((flags & SigmaValue) == 0)
3348 geometry_info.sigma=1.0;
3349 if ((flags & XiValue) == 0)
3350 geometry_info.xi=4.0;
3351 if ((flags & PsiValue) == 0)
3352 geometry_info.psi=4.0;
cristyaa2c16c2012-03-25 22:21:35 +00003353 new_image=ShadowImage(_image,geometry_info.rho,geometry_info.sigma,
3354 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3355 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003356 break;
3357 }
anthonyafa3dfc2012-03-03 11:31:30 +00003358 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003359 {
anthony7bcfe7f2012-03-30 14:01:22 +00003360 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003361 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003362 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003363 if ((flags & SigmaValue) == 0)
3364 geometry_info.sigma=1.0;
3365 if ((flags & XiValue) == 0)
3366 geometry_info.xi=0.0;
cristyaa2c16c2012-03-25 22:21:35 +00003367 new_image=SharpenImage(_image,geometry_info.rho,geometry_info.sigma,
3368 _exception);
anthony805a2d42011-09-25 08:25:12 +00003369 break;
3370 }
anthonyafa3dfc2012-03-03 11:31:30 +00003371 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003372 {
anthony7bcfe7f2012-03-30 14:01:22 +00003373 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003374 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003375 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3376 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003377 break;
3378 }
anthonyafa3dfc2012-03-03 11:31:30 +00003379 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003380 {
anthony7bcfe7f2012-03-30 14:01:22 +00003381 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003382 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003383 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003384 if ((flags & SigmaValue) == 0)
3385 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003386 new_image=ShearImage(_image,geometry_info.rho,
3387 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003388 break;
3389 }
anthonyafa3dfc2012-03-03 11:31:30 +00003390 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003391 {
anthony7bcfe7f2012-03-30 14:01:22 +00003392 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003393 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003394 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003395 if ((flags & SigmaValue) == 0)
3396 geometry_info.sigma=(double) QuantumRange/2.0;
3397 if ((flags & PercentValue) != 0)
3398 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3399 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003400 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003401 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003402 _exception);
anthony805a2d42011-09-25 08:25:12 +00003403 break;
3404 }
anthonyafa3dfc2012-03-03 11:31:30 +00003405 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003406 {
anthony7bcfe7f2012-03-30 14:01:22 +00003407 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003408 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003409 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003410 if ((flags & SigmaValue) == 0)
3411 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003412 new_image=SketchImage(_image,geometry_info.rho,
cristyaa2c16c2012-03-25 22:21:35 +00003413 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003414 break;
3415 }
anthonyafa3dfc2012-03-03 11:31:30 +00003416 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003417 {
anthony7bcfe7f2012-03-30 14:01:22 +00003418 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003419 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003420 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3421 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003422 break;
3423 }
anthonyafa3dfc2012-03-03 11:31:30 +00003424 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003425 {
anthony805a2d42011-09-25 08:25:12 +00003426 char
3427 *arguments;
3428
anthonyf42014d2012-03-25 09:53:06 +00003429 parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1);
3430 if ( parse < 0 )
3431 CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod",
3432 option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003433 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003434 if (arguments == (char *) NULL)
anthonyf42014d2012-03-25 09:53:06 +00003435 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
3436 new_image=SparseColorOption(_image,(SparseColorMethod)parse,
3437 arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003438 arguments=DestroyString(arguments);
3439 break;
3440 }
anthonyafa3dfc2012-03-03 11:31:30 +00003441 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003442 {
anthony7bcfe7f2012-03-30 14:01:22 +00003443 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003444 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003445 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3446 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003447 break;
3448 }
anthonyafa3dfc2012-03-03 11:31:30 +00003449 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003450 {
anthony7bcfe7f2012-03-30 14:01:22 +00003451 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003452 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003453 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003454 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3455 _exception);
anthony805a2d42011-09-25 08:25:12 +00003456 break;
3457 }
anthonyafa3dfc2012-03-03 11:31:30 +00003458 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003459 {
anthony7bc87992012-03-25 02:32:51 +00003460 parse=ParseCommandOption(MagickStatisticOptions,MagickFalse,arg1);
3461 if ( parse < 0 )
anthonyf42014d2012-03-25 09:53:06 +00003462 CLIWandExceptArgBreak(OptionError,"UnrecognizedStatisticType",
anthony7bc87992012-03-25 02:32:51 +00003463 option,arg1);
anthony7bcfe7f2012-03-30 14:01:22 +00003464 if (IfMagickFalse(IsGeometry(arg2)))
anthony7bc87992012-03-25 02:32:51 +00003465 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2);
anthonyfd706f92012-01-19 04:22:02 +00003466 (void) ParseGeometry(arg2,&geometry_info);
anthony7bc87992012-03-25 02:32:51 +00003467 new_image=StatisticImage(_image,(StatisticType)parse,
3468 (size_t) geometry_info.rho,(size_t) geometry_info.sigma,
3469 _exception);
anthony805a2d42011-09-25 08:25:12 +00003470 break;
3471 }
anthonyafa3dfc2012-03-03 11:31:30 +00003472 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003473 {
anthony92c93bd2012-03-19 14:02:47 +00003474 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003475 break;
3476 }
anthonyafa3dfc2012-03-03 11:31:30 +00003477 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003478 {
anthony7bcfe7f2012-03-30 14:01:22 +00003479 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00003480 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003481 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003482 new_image=SwirlImage(_image,geometry_info.rho,
3483 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003484 break;
3485 }
anthonyebb73a22012-03-22 14:25:52 +00003486 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003487 }
3488 case 't':
3489 {
anthonyafa3dfc2012-03-03 11:31:30 +00003490 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003491 {
3492 double
3493 threshold;
3494
anthony52bef752012-03-27 13:54:47 +00003495 threshold=(double) QuantumRange/2;
3496 if (normal_op) {
anthony7bcfe7f2012-03-30 14:01:22 +00003497 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003498 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003499 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony52bef752012-03-27 13:54:47 +00003500 }
anthony92c93bd2012-03-19 14:02:47 +00003501 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003502 break;
3503 }
anthonyafa3dfc2012-03-03 11:31:30 +00003504 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003505 {
anthony7bcfe7f2012-03-30 14:01:22 +00003506 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003507 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003508 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3509 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3510 _exception);
anthony805a2d42011-09-25 08:25:12 +00003511 break;
3512 }
anthonyafa3dfc2012-03-03 11:31:30 +00003513 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003514 {
anthony7bcfe7f2012-03-30 14:01:22 +00003515 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003516 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003517 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003518 break;
3519 }
anthonyafa3dfc2012-03-03 11:31:30 +00003520 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003521 {
anthonya3ef4ed2012-03-17 06:52:53 +00003522 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony52bef752012-03-27 13:54:47 +00003523 new_image=AffineTransformImage(_image,&_draw_info->affine,_exception);
anthony805a2d42011-09-25 08:25:12 +00003524 break;
3525 }
anthonyafa3dfc2012-03-03 11:31:30 +00003526 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003527 {
3528 PixelInfo
3529 target;
3530
anthony92c93bd2012-03-19 14:02:47 +00003531 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3532 (void) TransparentPaintImage(_image,&target,(Quantum)
3533 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003534 break;
3535 }
anthonyafa3dfc2012-03-03 11:31:30 +00003536 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003537 {
anthony92c93bd2012-03-19 14:02:47 +00003538 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003539 break;
3540 }
anthonyafa3dfc2012-03-03 11:31:30 +00003541 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003542 {
anthony92c93bd2012-03-19 14:02:47 +00003543 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003544 break;
3545 }
anthonyafa3dfc2012-03-03 11:31:30 +00003546 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003547 {
anthony92c93bd2012-03-19 14:02:47 +00003548 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003549 break;
3550 }
anthonyafa3dfc2012-03-03 11:31:30 +00003551 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003552 {
anthonyab3a50c2011-10-27 11:48:57 +00003553 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003554 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003555 break;
3556 }
anthonyebb73a22012-03-22 14:25:52 +00003557 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003558 }
3559 case 'u':
3560 {
anthonyafa3dfc2012-03-03 11:31:30 +00003561 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003562 {
anthony52bef752012-03-27 13:54:47 +00003563 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3564 Option is not documented, bt appears to be for "identify".
3565 We may need a identify specific verbose!
3566 */
3567 if (plus_alt_op) {
anthony92c93bd2012-03-19 14:02:47 +00003568 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003569 break;
3570 }
anthony92c93bd2012-03-19 14:02:47 +00003571 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3572 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003573 break;
3574 }
anthonyafa3dfc2012-03-03 11:31:30 +00003575 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003576 {
anthony92c93bd2012-03-19 14:02:47 +00003577 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003578 break;
3579 }
anthonyafa3dfc2012-03-03 11:31:30 +00003580 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003581 {
anthony7bcfe7f2012-03-30 14:01:22 +00003582 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003583 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003584 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003585 if ((flags & SigmaValue) == 0)
3586 geometry_info.sigma=1.0;
3587 if ((flags & XiValue) == 0)
3588 geometry_info.xi=1.0;
3589 if ((flags & PsiValue) == 0)
3590 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003591 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3592 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003593 break;
3594 }
anthonyebb73a22012-03-22 14:25:52 +00003595 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003596 }
3597 case 'v':
3598 {
anthonyafa3dfc2012-03-03 11:31:30 +00003599 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003600 {
anthonyafa3dfc2012-03-03 11:31:30 +00003601 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003602 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003603 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003604 */
anthony92c93bd2012-03-19 14:02:47 +00003605 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003606 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003607 break;
3608 }
anthonyafa3dfc2012-03-03 11:31:30 +00003609 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003610 {
anthony7bcfe7f2012-03-30 14:01:22 +00003611 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003612 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003613 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003614 if ((flags & SigmaValue) == 0)
3615 geometry_info.sigma=1.0;
3616 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003617 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003618 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003619 geometry_info.psi=0.1*_image->rows;
3620 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
cristyaa2c16c2012-03-25 22:21:35 +00003621 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3622 ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003623 break;
3624 }
anthonyebb73a22012-03-22 14:25:52 +00003625 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003626 }
3627 case 'w':
3628 {
anthonyafa3dfc2012-03-03 11:31:30 +00003629 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003630 {
anthony7bcfe7f2012-03-30 14:01:22 +00003631 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003632 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00003633 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003634 if ((flags & SigmaValue) == 0)
3635 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003636 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3637 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003638 break;
3639 }
anthonyafa3dfc2012-03-03 11:31:30 +00003640 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003641 {
anthony7bcfe7f2012-03-30 14:01:22 +00003642 if (IfMagickFalse(IsGeometry(arg1)))
anthony52bef752012-03-27 13:54:47 +00003643 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003644 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003645 break;
3646 }
anthonyebb73a22012-03-22 14:25:52 +00003647 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003648 }
3649 default:
anthonyebb73a22012-03-22 14:25:52 +00003650 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003651 }
3652 /*
3653 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003654 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003655 */
3656 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003657 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003658
anthony31f1bf72012-01-30 12:37:22 +00003659 return;
anthony92c93bd2012-03-19 14:02:47 +00003660#undef _image_info
3661#undef _draw_info
3662#undef _quantize_info
3663#undef _image
3664#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003665#undef IfNormalOp
3666#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003667#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003668#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003669}
anthonyfd706f92012-01-19 04:22:02 +00003670
anthony43f425d2012-02-26 12:58:58 +00003671WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003672 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003673{
3674 size_t
anthony43f425d2012-02-26 12:58:58 +00003675 n,
anthony31f1bf72012-01-30 12:37:22 +00003676 i;
3677
anthony43f425d2012-02-26 12:58:58 +00003678 assert(cli_wand != (MagickCLI *) NULL);
3679 assert(cli_wand->signature == WandSignature);
3680 assert(cli_wand->wand.signature == WandSignature);
3681 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003682 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003683 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003684
anthonyafa3dfc2012-03-03 11:31:30 +00003685#if !USE_WAND_METHODS
3686 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003687 i=0;
anthony43f425d2012-02-26 12:58:58 +00003688 n=GetImageListLength(cli_wand->wand.images);
3689 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003690 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003691 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003692 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003693 if ( cli_wand->wand.images->next == (Image *) NULL )
3694 break;
3695 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003696 }
anthony43f425d2012-02-26 12:58:58 +00003697 assert( i == n );
3698 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003699#else
3700 MagickResetIterator(&cli_wand->wand);
anthony7bcfe7f2012-03-30 14:01:22 +00003701 while ( IfMagickTrue(MagickNextImage(&cli_wand->wand)) )
anthonyafa3dfc2012-03-03 11:31:30 +00003702 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3703 MagickResetIterator(&cli_wand->wand);
3704#endif
anthony31f1bf72012-01-30 12:37:22 +00003705 return;
anthony805a2d42011-09-25 08:25:12 +00003706}
3707
3708/*
3709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3710% %
3711% %
3712% %
anthony43f425d2012-02-26 12:58:58 +00003713+ 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 +00003714% %
3715% %
3716% %
3717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3718%
anthony43f425d2012-02-26 12:58:58 +00003719% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003720% entire image list as a whole. The result is often a complete replacment
3721% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003722%
3723% The format of the MogrifyImage method is:
3724%
anthony43f425d2012-02-26 12:58:58 +00003725% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003726% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003727%
3728% A description of each parameter follows:
3729%
anthony43f425d2012-02-26 12:58:58 +00003730% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003731%
anthony36a8c2c2012-02-10 00:08:44 +00003732% o option: The option string for the operation
3733%
anthony31f1bf72012-01-30 12:37:22 +00003734% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003735%
anthonyfe1aa782012-03-24 13:43:04 +00003736% NOTE: only "limit" uses two arguments.
anthony8b10b462012-02-08 12:32:44 +00003737%
3738% Example usage...
3739%
anthonyafa3dfc2012-03-03 11:31:30 +00003740% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3741% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003742%
anthony24aa8822012-03-11 00:56:06 +00003743% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003744%
anthony43f425d2012-02-26 12:58:58 +00003745% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003746% argc,argv
3747% i=index in argv
3748%
anthony2052d272012-02-28 12:48:29 +00003749% option_info = GetCommandOptionInfo(argv[i]);
3750% count=option_info->type;
3751% option_type=option_info->flags;
3752%
3753% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003754% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003755% count>=1 ? argv[i+1] : (char *)NULL,
3756% count>=2 ? argv[i+2] : (char *)NULL );
3757% i += count+1;
3758%
anthony805a2d42011-09-25 08:25:12 +00003759*/
anthony43f425d2012-02-26 12:58:58 +00003760WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003761 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003762{
anthony2a0ec8c2012-03-24 04:35:56 +00003763 ssize_t
3764 parse;
3765
anthony31f1bf72012-01-30 12:37:22 +00003766 Image
3767 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003768
anthony2e4501b2012-03-30 04:41:54 +00003769#define _image_info (cli_wand->wand.image_info)
3770#define _images (cli_wand->wand.images)
3771#define _exception (cli_wand->wand.exception)
3772#define _draw_info (cli_wand->draw_info)
3773#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003774#define IfNormalOp (*option=='-')
3775#define IfPlusOp (*option!='-')
anthony7bcfe7f2012-03-30 14:01:22 +00003776#define normal_op IsMagickTrue(IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003777
anthony43f425d2012-02-26 12:58:58 +00003778 assert(cli_wand != (MagickCLI *) NULL);
3779 assert(cli_wand->signature == WandSignature);
3780 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003781 assert(_images != (Image *) NULL); /* _images must be present */
anthony7bcfe7f2012-03-30 14:01:22 +00003782 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00003783 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003784
anthony92c93bd2012-03-19 14:02:47 +00003785 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003786
3787 new_images=NewImageList();
3788
anthonyafa3dfc2012-03-03 11:31:30 +00003789 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003790 {
3791 case 'a':
3792 {
anthonyafa3dfc2012-03-03 11:31:30 +00003793 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003794 {
anthony92c93bd2012-03-19 14:02:47 +00003795 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003796 break;
3797 }
anthonyafa3dfc2012-03-03 11:31:30 +00003798 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003799 {
anthony31f1bf72012-01-30 12:37:22 +00003800 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003801 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003802 break;
3803 }
anthonyebb73a22012-03-22 14:25:52 +00003804 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003805 }
3806 case 'c':
3807 {
cristy5f257b22012-03-07 00:27:29 +00003808 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003809 {
anthony92c93bd2012-03-19 14:02:47 +00003810 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003811 break;
3812 }
anthonyafa3dfc2012-03-03 11:31:30 +00003813 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003814 {
anthony805a2d42011-09-25 08:25:12 +00003815 Image
anthony31f1bf72012-01-30 12:37:22 +00003816 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003817
anthonyafa3dfc2012-03-03 11:31:30 +00003818 /* FUTURE - make this a compose option, and thus can be used
3819 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003820 _images.
cristy87c02f42012-02-24 00:19:10 +00003821 */
anthony92c93bd2012-03-19 14:02:47 +00003822 new_images=RemoveFirstImageFromList(&_images);
3823 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003824 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003825 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003826 break;
cristye52fb5e2012-04-06 23:30:20 +00003827 (void) ClutImage(new_images,clut_image,new_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003828 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003829 break;
3830 }
anthonyafa3dfc2012-03-03 11:31:30 +00003831 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003832 {
anthony92c93bd2012-03-19 14:02:47 +00003833 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003834 break;
3835 }
anthonyafa3dfc2012-03-03 11:31:30 +00003836 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003837 {
anthony43f425d2012-02-26 12:58:58 +00003838 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003839 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003840 break;
3841 }
anthonyafa3dfc2012-03-03 11:31:30 +00003842 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003843 {
cristyfeb3e962012-03-29 17:25:55 +00003844 CompositeOperator
3845 compose;
3846
3847 const char*
3848 value;
3849
3850 MagickBooleanType
3851 clip_to_self;
3852
anthony805a2d42011-09-25 08:25:12 +00003853 Image
3854 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003855 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003856
3857 RectangleInfo
3858 geometry;
3859
anthony7bcfe7f2012-03-30 14:01:22 +00003860 /* Compose value from "-compose" option only */
anthony92c93bd2012-03-19 14:02:47 +00003861 value=GetImageOption(_image_info,"compose");
cristy542a95b2012-04-03 19:30:58 +00003862 if (value == (const char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003863 compose=OverCompositeOp; /* use Over not source_image->compose */
cristy542a95b2012-04-03 19:30:58 +00003864 else
3865 compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
3866 MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003867
anthony7bcfe7f2012-03-30 14:01:22 +00003868 /* Get "clip-to-self" expert setting (false is normal) */
cristy542a95b2012-04-03 19:30:58 +00003869 value=GetImageOption(_image_info,"compose:clip-to-self");
3870 if (value == (const char *) NULL)
3871 clip_to_self=MagickTrue;
3872 else
3873 clip_to_self=IsStringTrue(GetImageOption(_image_info,
3874 "compose:clip-to-self")); /* if this is true */
anthony2e4501b2012-03-30 04:41:54 +00003875 value=GetImageOption(_image_info,"compose:outside-overlay");
anthony7bcfe7f2012-03-30 14:01:22 +00003876 if (value != (const char *) NULL) { /* or this false */
anthony2e4501b2012-03-30 04:41:54 +00003877 /* FUTURE: depreciate warning for "compose:outside-overlay"*/
anthony7bcfe7f2012-03-30 14:01:22 +00003878 clip_to_self= IsMagickFalse(IsStringNotFalse(value));
anthony2e4501b2012-03-30 04:41:54 +00003879 }
3880
anthony92c93bd2012-03-19 14:02:47 +00003881 new_images=RemoveFirstImageFromList(&_images);
3882 source_image=RemoveFirstImageFromList(&_images);
anthony31f1bf72012-01-30 12:37:22 +00003883 if (source_image == (Image *) NULL)
anthony7bcfe7f2012-03-30 14:01:22 +00003884 break; /* FUTURE - produce Exception, rather than silent fail */
anthonye8f56492012-02-12 12:39:02 +00003885
anthony31f1bf72012-01-30 12:37:22 +00003886 /* FUTURE - this should not be here! - should be part of -geometry */
3887 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003888 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003889
anthony31f1bf72012-01-30 12:37:22 +00003890 SetGeometry(source_image,&geometry);
3891 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3892 GravityAdjustGeometry(new_images->columns,new_images->rows,
3893 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003894
anthony92c93bd2012-03-19 14:02:47 +00003895 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003896 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003897 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003898 if ((compose == DisplaceCompositeOp) ||
anthony7bcfe7f2012-03-30 14:01:22 +00003899 (compose == DistortCompositeOp)) {
3900 /* Merge Y displacement into X displace/distort map. */
3901 (void) CompositeImage(source_image,mask_image,
3902 CopyGreenCompositeOp,MagickTrue,0,0,_exception);
3903 mask_image=DestroyImage(mask_image);
3904 }
3905 else {
3906 /* Set a blending mask for the composition. */
3907 (void) NegateImage(mask_image,MagickFalse,_exception);
3908 (void) SetImageMask(new_images,mask_image,_exception);
3909 mask_image=DestroyImage(mask_image);
3910 }
anthony805a2d42011-09-25 08:25:12 +00003911 }
cristyfeb3e962012-03-29 17:25:55 +00003912 (void) CompositeImage(new_images,source_image,compose,clip_to_self,
3913 geometry.x,geometry.y,_exception);
anthony92c93bd2012-03-19 14:02:47 +00003914 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003915 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003916 break;
3917 }
anthonyebb73a22012-03-22 14:25:52 +00003918 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003919 }
3920 case 'd':
3921 {
anthonyafa3dfc2012-03-03 11:31:30 +00003922 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003923 {
anthony31f1bf72012-01-30 12:37:22 +00003924 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003925 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003926 break;
3927 }
anthonyafa3dfc2012-03-03 11:31:30 +00003928 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003929 {
anthonyafa3dfc2012-03-03 11:31:30 +00003930 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003931 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003932 else
anthony92c93bd2012-03-19 14:02:47 +00003933 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003934 break;
3935 }
anthonyafa3dfc2012-03-03 11:31:30 +00003936 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003937 {
anthonyafa3dfc2012-03-03 11:31:30 +00003938 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003939 {
3940 const char
3941 *p;
3942
3943 size_t
3944 number_duplicates;
3945
anthony7bcfe7f2012-03-30 14:01:22 +00003946 if (IfMagickFalse(IsGeometry(arg1)))
anthonyebb73a22012-03-22 14:25:52 +00003947 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,
3948 arg1);
anthony31f1bf72012-01-30 12:37:22 +00003949 number_duplicates=(size_t) StringToLong(arg1);
3950 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003951 if (p == (const char *) NULL)
anthonyebb73a22012-03-22 14:25:52 +00003952 new_images=DuplicateImages(_images,number_duplicates,"-1",
3953 _exception);
anthony805a2d42011-09-25 08:25:12 +00003954 else
anthony92c93bd2012-03-19 14:02:47 +00003955 new_images=DuplicateImages(_images,number_duplicates,p,
3956 _exception);
anthony805a2d42011-09-25 08:25:12 +00003957 }
anthonyafa3dfc2012-03-03 11:31:30 +00003958 else
anthony92c93bd2012-03-19 14:02:47 +00003959 new_images=DuplicateImages(_images,1,"-1",_exception);
3960 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003961 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003962 break;
3963 }
anthonyebb73a22012-03-22 14:25:52 +00003964 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003965 }
3966 case 'e':
3967 {
anthonyafa3dfc2012-03-03 11:31:30 +00003968 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003969 {
anthony2a0ec8c2012-03-24 04:35:56 +00003970 parse = ParseCommandOption(MagickEvaluateOptions,MagickFalse,arg1);
3971 if ( parse < 0 )
3972 CLIWandExceptArgBreak(OptionError,"UnrecognizedEvaluateOperator",
3973 option,arg1);
3974 new_images=EvaluateImages(_images,(MagickEvaluateOperator)parse,
3975 _exception);
anthony805a2d42011-09-25 08:25:12 +00003976 break;
3977 }
anthonyebb73a22012-03-22 14:25:52 +00003978 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003979 }
3980 case 'f':
3981 {
anthonyafa3dfc2012-03-03 11:31:30 +00003982 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003983 {
anthony92c93bd2012-03-19 14:02:47 +00003984 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003985 break;
3986 }
anthonyafa3dfc2012-03-03 11:31:30 +00003987 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003988 {
anthony319dac62012-03-06 04:12:44 +00003989 /* REDIRECTED to use -layers flatten instead */
anthony2e4501b2012-03-30 04:41:54 +00003990 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003991 break;
3992 }
anthonyafa3dfc2012-03-03 11:31:30 +00003993 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003994 {
anthony92c93bd2012-03-19 14:02:47 +00003995 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003996 break;
3997 }
anthonyebb73a22012-03-22 14:25:52 +00003998 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00003999 }
4000 case 'h':
4001 {
anthonyafa3dfc2012-03-03 11:31:30 +00004002 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004003 {
anthony31f1bf72012-01-30 12:37:22 +00004004 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00004005 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00004006 */
anthony805a2d42011-09-25 08:25:12 +00004007 Image
anthony31f1bf72012-01-30 12:37:22 +00004008 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00004009
anthony92c93bd2012-03-19 14:02:47 +00004010 new_images=RemoveFirstImageFromList(&_images);
4011 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004012 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004013 break;
anthony92c93bd2012-03-19 14:02:47 +00004014 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00004015 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00004016 break;
4017 }
anthonyebb73a22012-03-22 14:25:52 +00004018 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004019 }
4020 case 'i':
4021 {
anthonyafa3dfc2012-03-03 11:31:30 +00004022 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004023 {
4024 Image
anthony805a2d42011-09-25 08:25:12 +00004025 *magnitude_image,
4026 *phase_image;
4027
anthony92c93bd2012-03-19 14:02:47 +00004028 magnitude_image=RemoveFirstImageFromList(&_images);
4029 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00004030 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00004031 if (phase_image == (Image *) NULL)
4032 break;
4033 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00004034 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004035 magnitude_image=DestroyImage(magnitude_image);
4036 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00004037 break;
4038 }
anthonyafa3dfc2012-03-03 11:31:30 +00004039 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004040 {
4041 Image
anthony31f1bf72012-01-30 12:37:22 +00004042 *insert_image,
4043 *index_image;
4044
4045 ssize_t
4046 index;
anthony805a2d42011-09-25 08:25:12 +00004047
anthony7bcfe7f2012-03-30 14:01:22 +00004048 if (IfNormalOp && IfMagickFalse(IsGeometry(arg1)))
anthonyfe1aa782012-03-24 13:43:04 +00004049 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00004050 index=0;
anthony92c93bd2012-03-19 14:02:47 +00004051 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00004052 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00004053 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00004054 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00004055 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00004056 PrependImageToList(&_images,insert_image);
4057 else if (index == (ssize_t) GetImageListLength(_images))
4058 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00004059 else
anthony43f425d2012-02-26 12:58:58 +00004060 {
anthony92c93bd2012-03-19 14:02:47 +00004061 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00004062 if (index_image == (Image *) NULL)
anthonyfe1aa782012-03-24 13:43:04 +00004063 CLIWandExceptArgBreak(OptionError,"NoSuchImage",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004064 InsertImageInList(&index_image,insert_image);
4065 }
anthony92c93bd2012-03-19 14:02:47 +00004066 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00004067 break;
4068 }
anthonyebb73a22012-03-22 14:25:52 +00004069 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004070 }
4071 case 'l':
4072 {
anthonyafa3dfc2012-03-03 11:31:30 +00004073 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004074 {
anthonyfe1aa782012-03-24 13:43:04 +00004075 parse=ParseCommandOption(MagickLayerOptions,MagickFalse,arg1);
4076 if ( parse < 0 )
4077 CLIWandExceptArgBreak(OptionError,"UnrecognizedLayerMethod",
4078 option,arg1);
4079 switch ((ImageLayerMethod) parse)
anthony805a2d42011-09-25 08:25:12 +00004080 {
4081 case CoalesceLayer:
4082 {
anthony92c93bd2012-03-19 14:02:47 +00004083 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004084 break;
4085 }
4086 case CompareAnyLayer:
4087 case CompareClearLayer:
4088 case CompareOverlayLayer:
4089 default:
4090 {
anthonyfe1aa782012-03-24 13:43:04 +00004091 new_images=CompareImagesLayers(_images,(ImageLayerMethod) parse,
4092 _exception);
anthony805a2d42011-09-25 08:25:12 +00004093 break;
4094 }
4095 case MergeLayer:
4096 case FlattenLayer:
4097 case MosaicLayer:
4098 case TrimBoundsLayer:
4099 {
anthonyfe1aa782012-03-24 13:43:04 +00004100 new_images=MergeImageLayers(_images,(ImageLayerMethod) parse,
4101 _exception);
anthony805a2d42011-09-25 08:25:12 +00004102 break;
4103 }
4104 case DisposeLayer:
4105 {
anthony92c93bd2012-03-19 14:02:47 +00004106 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004107 break;
4108 }
4109 case OptimizeImageLayer:
4110 {
anthony92c93bd2012-03-19 14:02:47 +00004111 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004112 break;
4113 }
4114 case OptimizePlusLayer:
4115 {
anthony92c93bd2012-03-19 14:02:47 +00004116 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004117 break;
4118 }
4119 case OptimizeTransLayer:
4120 {
anthony92c93bd2012-03-19 14:02:47 +00004121 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004122 break;
4123 }
4124 case RemoveDupsLayer:
4125 {
anthony92c93bd2012-03-19 14:02:47 +00004126 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004127 break;
4128 }
4129 case RemoveZeroLayer:
4130 {
anthony92c93bd2012-03-19 14:02:47 +00004131 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00004132 break;
4133 }
4134 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00004135 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00004136 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004137 if (new_images == (Image *) NULL)
4138 break;
anthony92c93bd2012-03-19 14:02:47 +00004139 _images=DestroyImageList(_images);
4140 _images=OptimizeImageLayers(new_images,_exception);
4141 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004142 break;
4143 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00004144 OptimizeImageTransparency(_images,_exception);
4145 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
4146 _exception);
anthony805a2d42011-09-25 08:25:12 +00004147 break;
4148 }
4149 case CompositeLayer:
4150 {
anthony805a2d42011-09-25 08:25:12 +00004151 Image
4152 *source;
4153
4154 RectangleInfo
4155 geometry;
4156
anthony31f1bf72012-01-30 12:37:22 +00004157 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00004158 compose;
4159
4160 const char*
4161 value;
4162
anthony92c93bd2012-03-19 14:02:47 +00004163 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00004164 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00004165 if (value != (const char *) NULL)
4166 compose=(CompositeOperator) ParseCommandOption(
4167 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00004168
anthony31f1bf72012-01-30 12:37:22 +00004169 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00004170 source=_images;
anthony805a2d42011-09-25 08:25:12 +00004171 while (source != (Image *) NULL)
4172 {
4173 source=GetNextImageInList(source);
4174 if ((source != (Image *) NULL) &&
4175 (LocaleCompare(source->magick,"NULL") == 0))
4176 break;
4177 }
4178 if (source != (Image *) NULL)
4179 {
4180 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4181 (GetNextImageInList(source) == (Image *) NULL))
4182 source=(Image *) NULL;
4183 else
anthony31f1bf72012-01-30 12:37:22 +00004184 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00004185 source=SplitImageList(source->previous);
4186 DeleteImageFromList(&source);
4187 }
4188 }
4189 if (source == (Image *) NULL)
4190 {
anthony92c93bd2012-03-19 14:02:47 +00004191 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00004192 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00004193 break;
4194 }
anthony31f1bf72012-01-30 12:37:22 +00004195 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00004196 SetGeometry(_images,&geometry);
4197 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00004198 geometry.width=source->page.width != 0 ?
4199 source->page.width : source->columns;
4200 geometry.height=source->page.height != 0 ?
4201 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00004202 GravityAdjustGeometry(_images->page.width != 0 ?
4203 _images->page.width : _images->columns,
4204 _images->page.height != 0 ? _images->page.height :
4205 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00004206
anthony31f1bf72012-01-30 12:37:22 +00004207 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00004208 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
4209 _exception);
anthony805a2d42011-09-25 08:25:12 +00004210 source=DestroyImageList(source);
4211 break;
4212 }
4213 }
anthony805a2d42011-09-25 08:25:12 +00004214 break;
4215 }
anthonyafa3dfc2012-03-03 11:31:30 +00004216 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00004217 {
4218 MagickSizeType
4219 limit;
4220
anthony72feaa62012-01-17 06:46:23 +00004221 limit=MagickResourceInfinity;
anthonyfe1aa782012-03-24 13:43:04 +00004222 parse= ParseCommandOption(MagickResourceOptions,MagickFalse,arg1);
4223 if ( parse < 0 )
4224 CLIWandExceptArgBreak(OptionError,"UnrecognizedResourceType",
4225 option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004226 if (LocaleCompare("unlimited",arg2) != 0)
4227 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthonyfe1aa782012-03-24 13:43:04 +00004228 (void) SetMagickResourceLimit((ResourceType)parse,limit);
anthony72feaa62012-01-17 06:46:23 +00004229 break;
4230 }
anthonyebb73a22012-03-22 14:25:52 +00004231 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004232 }
4233 case 'm':
4234 {
anthonyafa3dfc2012-03-03 11:31:30 +00004235 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004236 {
anthony31f1bf72012-01-30 12:37:22 +00004237 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004238 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004239 break;
4240 }
anthonyafa3dfc2012-03-03 11:31:30 +00004241 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004242 {
4243 Image
4244 *morph_image;
4245
anthony7bcfe7f2012-03-30 14:01:22 +00004246 if (IfMagickFalse(IsGeometry(arg1)))
anthony7bc87992012-03-25 02:32:51 +00004247 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00004248 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4249 _exception);
anthony805a2d42011-09-25 08:25:12 +00004250 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004251 break;
anthony92c93bd2012-03-19 14:02:47 +00004252 _images=DestroyImageList(_images);
4253 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004254 break;
4255 }
anthonyafa3dfc2012-03-03 11:31:30 +00004256 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004257 {
anthony319dac62012-03-06 04:12:44 +00004258 /* REDIRECTED to use -layers mosaic instead */
anthony2e4501b2012-03-30 04:41:54 +00004259 CLIListOperatorImages(cli_wand,"-layers",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004260 break;
4261 }
anthonyebb73a22012-03-22 14:25:52 +00004262 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004263 }
4264 case 'p':
4265 {
anthonyafa3dfc2012-03-03 11:31:30 +00004266 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004267 {
4268 char
4269 *string;
4270
anthony92c93bd2012-03-19 14:02:47 +00004271 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004272 if (string == (char *) NULL)
4273 break;
4274 (void) FormatLocaleFile(stdout,"%s",string);
4275 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004276 break;
anthony805a2d42011-09-25 08:25:12 +00004277 }
anthonyafa3dfc2012-03-03 11:31:30 +00004278 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004279 {
4280 char
4281 **arguments;
4282
4283 int
4284 j,
4285 number_arguments;
4286
anthony31f1bf72012-01-30 12:37:22 +00004287 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004288 if (arguments == (char **) NULL)
4289 break;
anthony31f1bf72012-01-30 12:37:22 +00004290 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004291 {
4292 char
4293 breaker,
4294 quote,
4295 *token;
4296
4297 const char
4298 *arguments;
4299
4300 int
4301 next,
4302 status;
4303
4304 size_t
4305 length;
4306
4307 TokenInfo
4308 *token_info;
4309
4310 /*
anthony24aa8822012-03-11 00:56:06 +00004311 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004312 */
anthony31f1bf72012-01-30 12:37:22 +00004313 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004314 token=(char *) NULL;
4315 if (~length >= (MaxTextExtent-1))
4316 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4317 sizeof(*token));
4318 if (token == (char *) NULL)
4319 break;
4320 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004321 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004322 token_info=AcquireTokenInfo();
4323 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4324 "\"",'\0',&breaker,&next,&quote);
4325 token_info=DestroyTokenInfo(token_info);
4326 if (status == 0)
4327 {
4328 const char
4329 *argv;
4330
4331 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004332 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4333 _exception);
anthony805a2d42011-09-25 08:25:12 +00004334 }
4335 token=DestroyString(token);
4336 break;
4337 }
4338 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004339 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4340 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004341 for (j=0; j < number_arguments; j++)
4342 arguments[j]=DestroyString(arguments[j]);
4343 arguments=(char **) RelinquishMagickMemory(arguments);
4344 break;
4345 }
anthonyebb73a22012-03-22 14:25:52 +00004346 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004347 }
4348 case 'r':
4349 {
anthonyafa3dfc2012-03-03 11:31:30 +00004350 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004351 {
anthony92c93bd2012-03-19 14:02:47 +00004352 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004353 break;
4354 }
anthonyafa3dfc2012-03-03 11:31:30 +00004355 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004356 {
anthony92c93bd2012-03-19 14:02:47 +00004357 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004358 break;
4359 }
anthonyebb73a22012-03-22 14:25:52 +00004360 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004361 }
4362 case 's':
4363 {
anthonyafa3dfc2012-03-03 11:31:30 +00004364 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004365 {
4366 Image
4367 *smush_image;
4368
4369 ssize_t
4370 offset;
4371
anthony7bcfe7f2012-03-30 14:01:22 +00004372 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004373 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony31f1bf72012-01-30 12:37:22 +00004374 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004375 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004376 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004377 break;
anthony92c93bd2012-03-19 14:02:47 +00004378 _images=DestroyImageList(_images);
4379 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004380 break;
4381 }
anthony0ea037a2012-04-03 12:14:39 +00004382 if (LocaleCompare("swap",option+1) == 0) {
4383 Image
4384 *p,
4385 *q,
4386 *swap;
anthony805a2d42011-09-25 08:25:12 +00004387
anthony0ea037a2012-04-03 12:14:39 +00004388 ssize_t
4389 index,
4390 swap_index;
anthony805a2d42011-09-25 08:25:12 +00004391
anthony0ea037a2012-04-03 12:14:39 +00004392 index=-1;
4393 swap_index=-2;
4394 if (IfNormalOp) {
4395 GeometryInfo
4396 geometry_info;
4397
4398 MagickStatusType
4399 flags;
4400
4401 swap_index=(-1);
anthony7bcfe7f2012-03-30 14:01:22 +00004402 if (IfMagickFalse(IsGeometry(arg1)))
anthonyf42014d2012-03-25 09:53:06 +00004403 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004404 flags=ParseGeometry(arg1,&geometry_info);
4405 index=(ssize_t) geometry_info.rho;
4406 if ((flags & SigmaValue) != 0)
4407 swap_index=(ssize_t) geometry_info.sigma;
anthony805a2d42011-09-25 08:25:12 +00004408 }
anthony0ea037a2012-04-03 12:14:39 +00004409 p=GetImageFromList(_images,index);
4410 q=GetImageFromList(_images,swap_index);
anthony8226e722012-04-05 14:25:46 +00004411 if ((p == (Image *) NULL) || (q == (Image *) NULL)) {
4412 if (IfNormalOp)
4413 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1)
4414 else
4415 CLIWandExceptionBreak(OptionError,"TwoOrMoreImagesRequired",option);
4416 }
anthony0ea037a2012-04-03 12:14:39 +00004417 if (p == q)
anthony8226e722012-04-05 14:25:46 +00004418 CLIWandExceptArgBreak(OptionError,"InvalidImageIndex",option,arg1);
anthony0ea037a2012-04-03 12:14:39 +00004419 swap=CloneImage(p,0,0,MagickTrue,_exception);
4420 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
4421 ReplaceImageInList(&q,swap);
4422 _images=GetFirstImageInList(q);
4423 break;
4424 }
anthonyebb73a22012-03-22 14:25:52 +00004425 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004426 }
anthony805a2d42011-09-25 08:25:12 +00004427 default:
anthonyebb73a22012-03-22 14:25:52 +00004428 CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option);
anthony805a2d42011-09-25 08:25:12 +00004429 }
anthony31f1bf72012-01-30 12:37:22 +00004430 if (new_images == (Image *) NULL)
4431 return;
anthony805a2d42011-09-25 08:25:12 +00004432
anthony92c93bd2012-03-19 14:02:47 +00004433 if (_images != (Image *) NULL)
4434 _images=DestroyImageList(_images);
4435 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004436 return;
4437
anthony92c93bd2012-03-19 14:02:47 +00004438#undef _image_info
4439#undef _images
4440#undef _exception
4441#undef _draw_info
4442#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004443#undef IfNormalOp
4444#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004445#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004446}
anthony43f425d2012-02-26 12:58:58 +00004447
4448/*
4449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4450% %
4451% %
4452% %
4453+ C L I S p e c i a l O p e r a t i o n s %
4454% %
4455% %
4456% %
4457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4458%
4459% CLISpecialOption() Applies operations that may involve empty image lists
4460% and or stacks of image lists or image_info settings.
4461%
anthonyafa3dfc2012-03-03 11:31:30 +00004462% The classic operators of this type is -read, and image stack operators,
4463% which can be applied to empty image lists.
4464%
4465% Note: unlike other Operators, these may involve other special 'option'
4466% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004467%
4468% The format of the CLISpecialOption method is:
4469%
4470% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004471% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004472%
4473% A description of each parameter follows:
4474%
4475% o cli_wand: the main CLI Wand to use.
4476%
4477% o option: The special option (with any switch char) to process
4478%
anthony24aa8822012-03-11 00:56:06 +00004479% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004480%
anthony2052d272012-02-28 12:48:29 +00004481% Example Usage...
4482%
anthonyce8dcb32012-03-21 13:20:31 +00004483% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004484%
anthony24aa8822012-03-11 00:56:06 +00004485% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004486%
4487% cli_wand
4488% argc,argv
4489% i=index in argv
4490%
4491% option_info = GetCommandOptionInfo(argv[i]);
4492% count=option_info->type;
4493% option_type=option_info->flags;
4494%
4495% if ( (option_type & SpecialOptionFlag) != 0 )
4496% CLISpecialOperator(cli_wand,argv[i],
4497% count>=1 ? argv[i+1] : (char *)NULL);
4498% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004499%
4500*/
4501
anthony43f425d2012-02-26 12:58:58 +00004502WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004503 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004504{
anthony8226e722012-04-05 14:25:46 +00004505#define _image_info (cli_wand->wand.image_info)
4506#define _images (cli_wand->wand.images)
4507#define _exception (cli_wand->wand.exception)
4508#define IfNormalOp (*option=='-')
4509#define IfPlusOp (*option!='-')
anthony43f425d2012-02-26 12:58:58 +00004510
4511 assert(cli_wand != (MagickCLI *) NULL);
4512 assert(cli_wand->signature == WandSignature);
4513 assert(cli_wand->wand.signature == WandSignature);
anthony7bcfe7f2012-03-30 14:01:22 +00004514 if (IfMagickTrue(cli_wand->wand.debug))
anthony43f425d2012-02-26 12:58:58 +00004515 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4516
anthony8226e722012-04-05 14:25:46 +00004517 if(_images != (Image *)NULL)
4518 (void) SyncImagesSettings(cli_wand->wand.image_info,_images,_exception);
anthony24aa8822012-03-11 00:56:06 +00004519
anthony52bef752012-03-27 13:54:47 +00004520 /*
4521 No-op options
4522 */
4523 if (LocaleCompare("noop",option+1) == 0)
4524 return;
4525 if (LocaleCompare("sans",option+1) == 0)
4526 return;
4527 if (LocaleCompare("sans0",option+1) == 0)
4528 return;
4529 if (LocaleCompare("sans2",option+1) == 0)
4530 return;
4531 /*
4532 Image Reading
4533 */
4534 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthony0ea037a2012-04-03 12:14:39 +00004535 ( LocaleCompare("--",option) == 0 ) ) {
4536 int
4537 argc;
4538 char
4539 **argv;
anthony52bef752012-03-27 13:54:47 +00004540
anthony0ea037a2012-04-03 12:14:39 +00004541 ssize_t
4542 i;
4543
4544 /* Expand the filename argument (meta-characters or "@filelist" ) */
4545 argc = 1;
cristye71f2942012-04-04 11:07:05 +00004546 argv = (char **) &arg1;
anthony0ea037a2012-04-03 12:14:39 +00004547 MagickBooleanType
4548 status=ExpandFilenames(&argc,&argv);
4549
4550 if (IfMagickFalse(status))
4551 CLIWandExceptArgReturn(ResourceLimitError,"MemoryAllocationFailed",
4552 option,GetExceptionMessage(errno));
4553
4554 /* loop over expanded list reading images */
4555 for (i=0; i<argc; i++) {
anthony52bef752012-03-27 13:54:47 +00004556#if !USE_WAND_METHODS
4557 Image *
4558 new_images;
anthony8226e722012-04-05 14:25:46 +00004559 if (IfMagickTrue(_image_info->ping))
4560 new_images=PingImages(_image_info,argv[i],_exception);
anthony52bef752012-03-27 13:54:47 +00004561 else
anthony8226e722012-04-05 14:25:46 +00004562 new_images=ReadImages(_image_info,argv[i],_exception);
4563 AppendImageToList(&_images, new_images);
anthony52bef752012-03-27 13:54:47 +00004564#else
4565 /* read images using MagickWand method - no ping */
4566 /* This is not working! - it locks up in a CPU loop! */
4567 MagickSetLastIterator(&cli_wand->wand);
4568 MagickReadImage(&cli_wand->wand,arg1);
4569 MagickSetFirstIterator(&cli_wand->wand);
4570#endif
anthony52bef752012-03-27 13:54:47 +00004571 }
anthony0ea037a2012-04-03 12:14:39 +00004572 /* FUTURE: how do I free the expanded filename arguments??? */
4573
4574 return;
4575 }
anthony52bef752012-03-27 13:54:47 +00004576 /*
anthony8226e722012-04-05 14:25:46 +00004577 Image Writing
4578 */
4579 if (LocaleCompare("write",option+1) == 0) {
4580 char
4581 key[MaxTextExtent];
4582
4583 Image
4584 *write_images;
4585
4586 ImageInfo
4587 *write_info;
4588
4589 /* Need images, unless a "null:" output coder is used */
4590 if ( cli_wand->wand.images == (Image *) NULL ) {
4591 if ( LocaleCompare(option,"null:") == 0 )
4592 return;
4593 CLIWandExceptArgReturn(OptionError,"NoImagesForWrite",option,arg1);
4594 }
4595
4596 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
4597 (void) DeleteImageRegistry(key);
4598 write_images=_images;
4599 if (IfPlusOp)
4600 write_images=CloneImageList(_images,_exception);
4601 write_info=CloneImageInfo(_image_info);
4602 (void) WriteImages(write_info,write_images,arg1,_exception);
4603 write_info=DestroyImageInfo(write_info);
4604 if (IfPlusOp)
4605 write_images=DestroyImageList(write_images);
4606 return;
4607 }
4608 /*
anthony52bef752012-03-27 13:54:47 +00004609 Parenthesis and Brace operations
4610 */
anthonyce8dcb32012-03-21 13:20:31 +00004611 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
anthonyf42014d2012-03-25 09:53:06 +00004612 /* link image and setting stacks - option is itself saved on stack! */
anthonyce8dcb32012-03-21 13:20:31 +00004613 (void) SetImageOption(cli_wand->wand.image_info,option+1,
anthony8226e722012-04-05 14:25:46 +00004614 IfNormalOp ? "true" : (char *) NULL);
anthonyce8dcb32012-03-21 13:20:31 +00004615 return;
4616 }
4617 if (LocaleCompare("(",option) == 0) {
anthony8226e722012-04-05 14:25:46 +00004618 /* stack 'push' images */
4619 Stack
4620 *node;
anthony43f425d2012-02-26 12:58:58 +00004621
anthony8226e722012-04-05 14:25:46 +00004622 size_t
4623 size;
anthony43f425d2012-02-26 12:58:58 +00004624
anthony8226e722012-04-05 14:25:46 +00004625 size=0;
4626 node=cli_wand->image_list_stack;
4627 for ( ; node != (Stack *)NULL; node=node->next)
4628 size++;
4629 if ( size >= MAX_STACK_DEPTH )
4630 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
4631 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4632 if (node == (Stack *) NULL)
4633 CLIWandExceptionReturn(ResourceLimitFatalError,
4634 "MemoryAllocationFailed",option);
4635 node->data = (void *)cli_wand->wand.images;
4636 cli_wand->wand.images = NewImageList();
4637 node->next = cli_wand->image_list_stack;
4638 cli_wand->image_list_stack = node;
anthony43f425d2012-02-26 12:58:58 +00004639
anthony8226e722012-04-05 14:25:46 +00004640 /* handle respect-parenthesis */
4641 if (IfMagickTrue(IsStringTrue(GetImageOption(cli_wand->wand.image_info,
4642 "respect-parenthesis"))))
4643 option="{"; /* fall-thru so as to push image settings too */
4644 else
anthony43f425d2012-02-26 12:58:58 +00004645 return;
anthony8226e722012-04-05 14:25:46 +00004646 }
4647 if (LocaleCompare("{",option) == 0) {
4648 /* stack 'push' of image_info settings */
4649 Stack
4650 *node;
anthony43f425d2012-02-26 12:58:58 +00004651
anthony8226e722012-04-05 14:25:46 +00004652 size_t
4653 size;
anthony43f425d2012-02-26 12:58:58 +00004654
anthony8226e722012-04-05 14:25:46 +00004655 size=0;
4656 node=cli_wand->image_info_stack;
4657 for ( ; node != (Stack *)NULL; node=node->next)
4658 size++;
4659 if ( size >= MAX_STACK_DEPTH )
4660 CLIWandExceptionReturn(OptionError,"CurlyBracesNestedTooDeeply",option);
4661 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4662 if (node == (Stack *) NULL)
4663 CLIWandExceptionReturn(ResourceLimitFatalError,
4664 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004665
anthony8226e722012-04-05 14:25:46 +00004666 node->data = (void *)cli_wand->wand.image_info;
4667 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4668 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4669 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4670 option);
anthony43f425d2012-02-26 12:58:58 +00004671 cli_wand->wand.image_info = (ImageInfo *)node->data;
4672 node = (Stack *)RelinquishMagickMemory(node);
anthony43f425d2012-02-26 12:58:58 +00004673 return;
4674 }
anthony8226e722012-04-05 14:25:46 +00004675
4676 node->next = cli_wand->image_info_stack;
4677 cli_wand->image_info_stack = node;
4678
4679 return;
4680 }
4681 if (LocaleCompare(")",option) == 0) {
4682 /* pop images from stack */
4683 Stack
4684 *node;
4685
4686 node = (Stack *)cli_wand->image_list_stack;
4687 if ( node == (Stack *)NULL)
4688 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
4689 cli_wand->image_list_stack = node->next;
4690
4691 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4692 cli_wand->wand.images= (Image *)node->data;
4693 node = (Stack *)RelinquishMagickMemory(node);
4694
4695 /* handle respect-parenthesis - of the previous 'pushed' settings */
4696 node = cli_wand->image_info_stack;
4697 if ( node != (Stack *)NULL)
4698 {
4699 if (IfMagickTrue(IsStringTrue(GetImageOption(
4700 cli_wand->wand.image_info,"respect-parenthesis"))))
4701 option="}"; /* fall-thru so as to pop image settings too */
4702 else
4703 return;
4704 }
4705 else
4706 return;
4707 }
4708 if (LocaleCompare("}",option) == 0) {
4709 /* pop image_info settings from stack */
4710 Stack
4711 *node;
4712
4713 node = (Stack *)cli_wand->image_info_stack;
4714 if ( node == (Stack *)NULL)
4715 CLIWandExceptionReturn(OptionError,"UnbalancedCurlyBraces",option);
4716 cli_wand->image_info_stack = node->next;
4717
4718 (void) DestroyImageInfo(cli_wand->wand.image_info);
4719 cli_wand->wand.image_info = (ImageInfo *)node->data;
4720 node = (Stack *)RelinquishMagickMemory(node);
4721
4722 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4723 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4724 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4725
4726 return;
4727 }
anthonyce8dcb32012-03-21 13:20:31 +00004728 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004729 Image
4730 *new_images;
4731
4732 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004733 arg1="-1";
anthony7bcfe7f2012-03-30 14:01:22 +00004734 if (IfMagickFalse(IsSceneGeometry(arg1,MagickFalse)))
anthony92c93bd2012-03-19 14:02:47 +00004735 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004736 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004737 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004738 new_images = (Image *)cli_wand->image_list_stack->data;
4739 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004740 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4741 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004742 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004743 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony8226e722012-04-05 14:25:46 +00004744 AppendImageToList(&_images,new_images);
anthony43f425d2012-02-26 12:58:58 +00004745 return;
4746 }
anthony52bef752012-03-27 13:54:47 +00004747 /*
4748 Informational Operations
4749 */
anthony0ea037a2012-04-03 12:14:39 +00004750 if (LocaleCompare("version",option+1) == 0) {
anthony8226e722012-04-05 14:25:46 +00004751 (void) FormatLocaleFile(stdout,"Version: %s\n",
4752 GetMagickVersion((size_t *) NULL));
4753 (void) FormatLocaleFile(stdout,"Copyright: %s\n",
4754 GetMagickCopyright());
4755 (void) FormatLocaleFile(stdout,"Features: %s\n\n",
4756 GetMagickFeatures());
4757 return;
4758 }
anthonyce8dcb32012-03-21 13:20:31 +00004759 if (LocaleCompare("list",option+1) == 0) {
anthony8226e722012-04-05 14:25:46 +00004760 /* FUTURE: This should really be built into the MagickCore
4761 It does not actually require a cli-wand or and images!
4762 */
4763 ssize_t
4764 list;
anthony43f425d2012-02-26 12:58:58 +00004765
anthony8226e722012-04-05 14:25:46 +00004766 list=ParseCommandOption(MagickListOptions,MagickFalse,arg1);
4767 if ( list < 0 ) {
4768 CLIWandExceptionArg(OptionError,"UnrecognizedListType",option,arg1);
anthony43f425d2012-02-26 12:58:58 +00004769 return;
4770 }
anthony8226e722012-04-05 14:25:46 +00004771 switch (list)
4772 {
4773 case MagickCoderOptions:
4774 {
4775 (void) ListCoderInfo((FILE *) NULL,_exception);
4776 break;
4777 }
4778 case MagickColorOptions:
4779 {
4780 (void) ListColorInfo((FILE *) NULL,_exception);
4781 break;
4782 }
4783 case MagickConfigureOptions:
4784 {
4785 (void) ListConfigureInfo((FILE *) NULL,_exception);
4786 break;
4787 }
4788 case MagickDelegateOptions:
4789 {
4790 (void) ListDelegateInfo((FILE *) NULL,_exception);
4791 break;
4792 }
4793 case MagickFontOptions:
4794 {
4795 (void) ListTypeInfo((FILE *) NULL,_exception);
4796 break;
4797 }
4798 case MagickFormatOptions:
4799 (void) ListMagickInfo((FILE *) NULL,_exception);
4800 break;
4801 case MagickLocaleOptions:
4802 (void) ListLocaleInfo((FILE *) NULL,_exception);
4803 break;
4804 case MagickLogOptions:
4805 (void) ListLogInfo((FILE *) NULL,_exception);
4806 break;
4807 case MagickMagicOptions:
4808 (void) ListMagicInfo((FILE *) NULL,_exception);
4809 break;
4810 case MagickMimeOptions:
4811 (void) ListMimeInfo((FILE *) NULL,_exception);
4812 break;
4813 case MagickModuleOptions:
4814 (void) ListModuleInfo((FILE *) NULL,_exception);
4815 break;
4816 case MagickPolicyOptions:
4817 (void) ListPolicyInfo((FILE *) NULL,_exception);
4818 break;
4819 case MagickResourceOptions:
4820 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
4821 break;
4822 case MagickThresholdOptions:
4823 (void) ListThresholdMaps((FILE *) NULL,_exception);
4824 break;
4825 default:
4826 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4827 _exception);
4828 break;
4829 }
4830 return;
4831 }
anthony43f425d2012-02-26 12:58:58 +00004832
4833#if 0
anthony43f425d2012-02-26 12:58:58 +00004834 // Other 'special' options this should handle
anthony8226e722012-04-05 14:25:46 +00004835 // "region"
anthony43f425d2012-02-26 12:58:58 +00004836 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
anthony43f425d2012-02-26 12:58:58 +00004837#endif
anthonyebb73a22012-03-22 14:25:52 +00004838 CLIWandException(OptionError,"UnrecognizedOption",option);
anthony43f425d2012-02-26 12:58:58 +00004839
anthony8226e722012-04-05 14:25:46 +00004840#undef _image_info
4841#undef _images
anthony92c93bd2012-03-19 14:02:47 +00004842#undef _exception
anthony8226e722012-04-05 14:25:46 +00004843#undef IfNormalOp
4844#undef IfPlusOp
anthony43f425d2012-02-26 12:58:58 +00004845}