blob: ef72e3c8502e5a9f680acaa2e87f4f7791b9502c [file] [log] [blame]
anthony805a2d42011-09-25 08:25:12 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
anthony8b10b462012-02-08 12:32:44 +00006% OOO PPPP EEEE RRRR AA TTTTT III OOO N N %
7% O O P P E R R A A T I O O NN N %
8% O O PPPP EEE RRRR AAAA T I O O N N N %
9% O O P E R R A A T I O O N NN %
10% OOO P EEEE R RR A A T III OOO N N %
anthony805a2d42011-09-25 08:25:12 +000011% %
12% %
anthony8b10b462012-02-08 12:32:44 +000013% CLI Magick Option Methods %
anthony805a2d42011-09-25 08:25:12 +000014% %
anthony8b10b462012-02-08 12:32:44 +000015% Dragon Computing %
cristy9e58efd2012-01-30 14:27:34 +000016% Anthony Thyssen %
cristy0a0ca4f2011-09-28 01:15:28 +000017% September 2011 %
anthony805a2d42011-09-25 08:25:12 +000018% %
19% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
anthony805a2d42011-09-25 08:25:12 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36% Apply the given options (settings, and simple, or sequence operations) to
anthony8b10b462012-02-08 12:32:44 +000037% the given image(s) according to the current "image_info", "draw_info", and
38% "quantize_info" settings, stored in a special CLI Image Wand.
anthony805a2d42011-09-25 08:25:12 +000039%
40% The final goal is to allow the execution in a strict one option at a time
41% manner that is needed for 'pipelining and file scripting' of options in
42% IMv7.
43%
anthony8b10b462012-02-08 12:32:44 +000044% Anthony Thyssen, September 2011
anthony805a2d42011-09-25 08:25:12 +000045*/
46
47/*
48 Include declarations.
49*/
50#include "MagickWand/studio.h"
51#include "MagickWand/MagickWand.h"
anthony72feaa62012-01-17 06:46:23 +000052#include "MagickWand/magick-wand-private.h"
anthonyfd706f92012-01-19 04:22:02 +000053#include "MagickWand/operation.h"
anthony2052d272012-02-28 12:48:29 +000054#include "MagickWand/operation-private.h"
anthony43f425d2012-02-26 12:58:58 +000055#include "MagickWand/wand.h"
anthony805a2d42011-09-25 08:25:12 +000056#include "MagickCore/monitor-private.h"
57#include "MagickCore/thread-private.h"
58#include "MagickCore/string-private.h"
59
60/*
61 Define declarations.
62*/
anthonyafa3dfc2012-03-03 11:31:30 +000063#define USE_WAND_METHODS 0
64#define MAX_STACK_DEPTH 32
65#define UNDEFINED_COMPRESSION_QUALITY 0UL
66
anthony805a2d42011-09-25 08:25:12 +000067/*
68 Constant declaration. (temporary exports)
69*/
70static const char
71 BackgroundColor[] = "#fff", /* white */
anthony72feaa62012-01-17 06:46:23 +000072 BorderColor[] = "#dfdfdf", /* sRGB gray */
73 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
anthony805a2d42011-09-25 08:25:12 +000074
75/*
76** Function to report on the progress of image operations
77*/
78static MagickBooleanType MonitorProgress(const char *text,
79 const MagickOffsetType offset,const MagickSizeType extent,
anthony43f425d2012-02-26 12:58:58 +000080 void *wand_unused(cli_wandent_data))
anthony805a2d42011-09-25 08:25:12 +000081{
82 char
83 message[MaxTextExtent],
84 tag[MaxTextExtent];
85
86 const char
87 *locale_message;
88
89 register char
90 *p;
91
92 if (extent < 2)
93 return(MagickTrue);
94 (void) CopyMagickMemory(tag,text,MaxTextExtent);
95 p=strrchr(tag,'/');
96 if (p != (char *) NULL)
97 *p='\0';
98 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
99 locale_message=GetLocaleMessage(message);
100 if (locale_message == message)
101 locale_message=tag;
102 if (p == (char *) NULL)
103 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
104 locale_message,(long) offset,(unsigned long) extent,(long)
105 (100L*offset/(extent-1)));
106 else
107 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
108 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
109 (100L*offset/(extent-1)));
110 if (offset == (MagickOffsetType) (extent-1))
111 (void) FormatLocaleFile(stderr,"\n");
112 (void) fflush(stderr);
113 return(MagickTrue);
114}
115
116/*
117** GetImageCache() will read an image into a image cache if not already
118** present then return the image that is in the cache under that filename.
119*/
120static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
121 ExceptionInfo *exception)
122{
123 char
124 key[MaxTextExtent];
125
126 ExceptionInfo
127 *sans_exception;
128
129 Image
130 *image;
131
132 ImageInfo
133 *read_info;
134
135 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
136 sans_exception=AcquireExceptionInfo();
137 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
138 sans_exception=DestroyExceptionInfo(sans_exception);
139 if (image != (Image *) NULL)
140 return(image);
141 read_info=CloneImageInfo(image_info);
142 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
143 image=ReadImage(read_info,exception);
144 read_info=DestroyImageInfo(read_info);
145 if (image != (Image *) NULL)
146 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
147 return(image);
148}
149
150/*
anthonya89dd172011-10-04 13:29:35 +0000151 SparseColorOption() parse the complex -sparse-color argument into an
152 an array of floating point values than call SparseColorImage().
153 Argument is a complex mix of floating-point pixel coodinates, and color
154 specifications (or direct floating point numbers). The number of floats
155 needed to represent a color varies depending on teh current channel
156 setting.
anthony43f425d2012-02-26 12:58:58 +0000157
158 This really should be in MagickCore, so that other API's can make use of it.
anthony805a2d42011-09-25 08:25:12 +0000159*/
160static Image *SparseColorOption(const Image *image,
161 const SparseColorMethod method,const char *arguments,
anthony31f1bf72012-01-30 12:37:22 +0000162 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000163{
164 char
165 token[MaxTextExtent];
166
167 const char
168 *p;
169
170 double
171 *sparse_arguments;
172
173 Image
174 *sparse_image;
175
176 PixelInfo
177 color;
178
179 MagickBooleanType
180 error;
181
182 register size_t
183 x;
184
185 size_t
186 number_arguments,
187 number_colors;
188
189 assert(image != (Image *) NULL);
190 assert(image->signature == MagickSignature);
191 if (image->debug != MagickFalse)
192 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
193 assert(exception != (ExceptionInfo *) NULL);
194 assert(exception->signature == MagickSignature);
195 /*
196 Limit channels according to image - and add up number of color channel.
197 */
198 number_colors=0;
199 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
200 number_colors++;
201 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
202 number_colors++;
203 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
204 number_colors++;
205 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
206 (image->colorspace == CMYKColorspace))
207 number_colors++;
208 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
209 (image->matte != MagickFalse))
210 number_colors++;
211
212 /*
213 Read string, to determine number of arguments needed,
214 */
215 p=arguments;
216 x=0;
217 while( *p != '\0' )
218 {
219 GetMagickToken(p,&p,token);
220 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000221 if ( isalpha((int) token[0]) || token[0] == '#' )
222 x += number_colors; /* color argument found */
anthonyce8dcb32012-03-21 13:20:31 +0000223 else
anthony805a2d42011-09-25 08:25:12 +0000224 x++; /* floating point argument */
anthony805a2d42011-09-25 08:25:12 +0000225 }
226 error=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +0000227 /* control points and color values */
228 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
229 number_arguments=x;
anthony805a2d42011-09-25 08:25:12 +0000230 if ( error ) {
231 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000232 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000233 "Invalid number of Arguments");
234 return( (Image *)NULL);
235 }
236
237 /* Allocate and fill in the floating point arguments */
238 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
239 sizeof(*sparse_arguments));
240 if (sparse_arguments == (double *) NULL) {
241 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
242 "MemoryAllocationFailed","%s","SparseColorOption");
243 return( (Image *)NULL);
244 }
245 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
246 sizeof(*sparse_arguments));
247 p=arguments;
248 x=0;
249 while( *p != '\0' && x < number_arguments ) {
250 /* X coordinate */
251 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
252 if ( token[0] == '\0' ) break;
253 if ( isalpha((int) token[0]) || token[0] == '#' ) {
254 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000255 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000256 "Color found, instead of X-coord");
257 error = MagickTrue;
258 break;
259 }
cristydbdd0e32011-11-04 23:29:40 +0000260 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000261 /* Y coordinate */
262 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
263 if ( token[0] == '\0' ) break;
264 if ( isalpha((int) token[0]) || token[0] == '#' ) {
265 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000266 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000267 "Color found, instead of Y-coord");
268 error = MagickTrue;
269 break;
270 }
cristydbdd0e32011-11-04 23:29:40 +0000271 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000272 /* color name or function given in string argument */
273 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
274 if ( token[0] == '\0' ) break;
275 if ( isalpha((int) token[0]) || token[0] == '#' ) {
276 /* Color string given */
277 (void) QueryColorCompliance(token,AllCompliance,&color,
278 exception);
279 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
280 sparse_arguments[x++] = QuantumScale*color.red;
281 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
282 sparse_arguments[x++] = QuantumScale*color.green;
283 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
284 sparse_arguments[x++] = QuantumScale*color.blue;
285 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
286 (image->colorspace == CMYKColorspace))
287 sparse_arguments[x++] = QuantumScale*color.black;
288 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
289 (image->matte != MagickFalse))
290 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000291 }
anthony31f1bf72012-01-30 12:37:22 +0000292 else {
293 /* Colors given as a set of floating point values - experimental */
294 /* NB: token contains the first floating point value to use! */
295 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
296 {
297 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
298 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
299 break;
300 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
301 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000302 }
anthony31f1bf72012-01-30 12:37:22 +0000303 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
304 {
305 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
306 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
307 break;
308 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
309 token[0] = ','; /* used this token - get another */
310 }
311 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
312 {
313 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
314 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
315 break;
316 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
317 token[0] = ','; /* used this token - get another */
318 }
319 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
320 (image->colorspace == CMYKColorspace))
321 {
322 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
323 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
324 break;
325 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
326 token[0] = ','; /* used this token - get another */
327 }
328 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
329 (image->matte != MagickFalse))
330 {
331 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
332 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
333 break;
334 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
335 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000336 }
337 }
338 }
339 if ( number_arguments != x && !error ) {
340 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000341 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000342 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
343 return( (Image *)NULL);
344 }
345 if ( error )
346 return( (Image *)NULL);
347
anthony31f1bf72012-01-30 12:37:22 +0000348 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000349 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
350 exception);
351 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
352 return( sparse_image );
353}
354
355/*
356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357% %
358% %
359% %
anthony43f425d2012-02-26 12:58:58 +0000360+ A c q u i r e W a n d C L I %
anthony805a2d42011-09-25 08:25:12 +0000361% %
362% %
363% %
364%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365%
anthony43f425d2012-02-26 12:58:58 +0000366% AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
367% Wand). The given image_info and exception is included as is if provided.
anthony805a2d42011-09-25 08:25:12 +0000368%
anthony43f425d2012-02-26 12:58:58 +0000369% Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
370% needed.
371%
372% The format of the NewMagickWand method is:
anthonyafa3dfc2012-03-03 11:31:30 +0000373%
anthony43f425d2012-02-26 12:58:58 +0000374% MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
375% ExceptionInfo *exception)
376%
377*/
378WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
379 ExceptionInfo *exception)
380{
381 MagickCLI
382 *cli_wand;
383
384 /* precaution - as per NewMagickWand() */
385 {
386 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
387 const char *quantum = GetMagickQuantumDepth(&depth);
388 if (depth != MAGICKCORE_QUANTUM_DEPTH)
389 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
390 }
391
392 /* allocate memory for MgaickCLI */
393 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
394 if (cli_wand == (MagickCLI *) NULL)
395 {
396 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
397 GetExceptionMessage(errno));
398 return((MagickCLI *)NULL);
399 }
400
401 /* Initialize Wand Part of MagickCLI
402 FUTURE: this is a repeat of code from NewMagickWand()
403 However some parts may be given fro man external source!
404 */
405 cli_wand->wand.id=AcquireWandId();
406 (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
407 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
408 cli_wand->wand.images=NewImageList();
409 if ( image_info == (ImageInfo *)NULL)
410 cli_wand->wand.image_info=AcquireImageInfo();
411 else
412 cli_wand->wand.image_info=image_info;
413 if ( exception == (ExceptionInfo *)NULL)
414 cli_wand->wand.exception=AcquireExceptionInfo();
415 else
416 cli_wand->wand.exception=exception;
417 cli_wand->wand.debug=IsEventLogging();
418 cli_wand->wand.signature=WandSignature;
419
420 /* Initialize CLI Part of MagickCLI */
421 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
422 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
423 cli_wand->image_list_stack=(Stack *)NULL;
424 cli_wand->image_info_stack=(Stack *)NULL;
anthony5330ae02012-03-20 14:17:01 +0000425 cli_wand->location="'%s'"; /* option location not known by default */
426 cli_wand->location2="'%s' '%s'";
anthony319dac62012-03-06 04:12:44 +0000427 cli_wand->filename=cli_wand->wand.name;
anthony1cdc5b72012-03-03 02:31:18 +0000428 cli_wand->line=0;
429 cli_wand->column=0;
anthony43f425d2012-02-26 12:58:58 +0000430 cli_wand->signature=WandSignature;
431
432 if (cli_wand->wand.debug != MagickFalse)
433 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
434 return(cli_wand);
435}
436
437/*
438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439% %
440% %
441% %
442+ D e s t r o y W a n d C L I %
443% %
444% %
445% %
446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447%
448% DestroyMagickCLI() destorys everything in a CLI wand, including image_info
449% and any exceptions, if still present in the wand.
450%
451% The format of the NewMagickWand method is:
anthonyafa3dfc2012-03-03 11:31:30 +0000452%
anthony43f425d2012-02-26 12:58:58 +0000453% MagickWand *DestroyMagickCLI()
454% Exception *exception)
455%
456*/
457WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
458{
459 Stack
460 *node;
461
462 assert(cli_wand != (MagickCLI *) NULL);
463 assert(cli_wand->signature == WandSignature);
464 assert(cli_wand->wand.signature == WandSignature);
465 if (cli_wand->wand.debug != MagickFalse)
466 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
467
468 /* Destroy CLI part of MagickCLI */
469 if (cli_wand->draw_info != (DrawInfo *) NULL )
470 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
471 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
472 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
473 while(cli_wand->image_list_stack != (Stack *)NULL)
474 {
475 node=cli_wand->image_list_stack;
476 cli_wand->image_list_stack=node->next;
477 (void) DestroyImageList((Image *)node->data);
478 (void) RelinquishMagickMemory(node);
479 }
480 while(cli_wand->image_info_stack != (Stack *)NULL)
481 {
482 node=cli_wand->image_info_stack;
483 cli_wand->image_info_stack=node->next;
484 (void) DestroyImageInfo((ImageInfo *)node->data);
485 (void) RelinquishMagickMemory(node);
486 }
487 cli_wand->signature=(~WandSignature);
488
489 /* Destroy Wand part MagickCLI */
490 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
491 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
492 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
493 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
494 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
495 RelinquishWandId(cli_wand->wand.id);
496 cli_wand->wand.signature=(~WandSignature);
497
498 return((MagickCLI *)NULL);
499}
500
501/*
502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
503% %
504% %
505% %
anthony2052d272012-02-28 12:48:29 +0000506+ C L I C a t c h E x c e p t i o n %
507% %
508% %
509% %
510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511%
512% CLICatchException() will report exceptions, either just non-fatal warnings
513% only, or all errors, according to 'all_execeptions' boolean argument.
514%
515% The function returns true is errors are fatal, in which case the caller
516% should abort and re-call with an 'all_exceptions' argument of true before
517% quitting.
518%
519% The cut-off level between fatal and non-fatal may be controlled by options
520% (FUTURE), but defaults to 'Error' exceptions.
521%
522% The format of the CLICatchException method is:
523%
524% MagickBooleanType CLICatchException(MagickCLI *cli_wand,
525% const MagickBooleanType all_exceptions );
526%
527*/
528WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
529 const MagickBooleanType all_exceptions )
530{
531 MagickBooleanType
532 status;
533 assert(cli_wand != (MagickCLI *) NULL);
534 assert(cli_wand->signature == WandSignature);
535 assert(cli_wand->wand.signature == WandSignature);
536 if (cli_wand->wand.debug != MagickFalse)
537 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
538
539 // FUTURE: '-regard_warning' should make this more sensitive.
540 // Note pipelined options may like more control over this level
541
542 status = MagickFalse;
543 if (cli_wand->wand.exception->severity > ErrorException)
544 status = MagickTrue;
545
546 if ( status == MagickFalse || all_exceptions != MagickFalse )
547 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
548
549 return(status);
550}
551
552/*
553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554% %
555% %
556% %
anthony43f425d2012-02-26 12:58:58 +0000557+ C L I S e t t i n g O p t i o n I n f o %
558% %
559% %
560% %
561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562%
563% CLISettingOptionInfo() applies a single settings option into a CLI wand
564% holding the image_info, draw_info, quantize_info structures that will be
565% used when processing the images.
566%
567% These options do no require images to be present in the CLI wand for them
568% to be able to be set, in which case they will generally be applied to image
569% that are read in later
anthony80c37752012-01-16 01:03:11 +0000570%
571% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000572% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000573%
anthony2052d272012-02-28 12:48:29 +0000574% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000575%
anthonyafa3dfc2012-03-03 11:31:30 +0000576% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +0000577% const char *option, const char *arg1)
anthony805a2d42011-09-25 08:25:12 +0000578%
579% A description of each parameter follows:
580%
anthony43f425d2012-02-26 12:58:58 +0000581% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000582%
anthonydcf510d2011-10-30 13:51:40 +0000583% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000584%
anthony24aa8822012-03-11 00:56:06 +0000585% o arg1: The single argument used to set this option.
anthonydcf510d2011-10-30 13:51:40 +0000586%
anthony72feaa62012-01-17 06:46:23 +0000587% Example usage...
588%
anthonyafa3dfc2012-03-03 11:31:30 +0000589% CLISettingOptionInfo(cli_wand, "-background", "Red"); // set value
590% CLISettingOptionInfo(cli_wand, "-adjoin", NULL); // set boolean
591% CLISettingOptionInfo(cli_wand, "+adjoin", NULL); // unset
anthony72feaa62012-01-17 06:46:23 +0000592%
anthony24aa8822012-03-11 00:56:06 +0000593% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +0000594%
595% argc,argv
596% i=index in argv
597%
anthony2052d272012-02-28 12:48:29 +0000598% option_info = GetCommandOptionInfo(argv[i]);
599% count=option_info->type;
600% option_type=option_info->flags;
601%
602% if ( (option_type & SettingOperatorOptionFlags) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +0000603% CLISettingOptionInfo(cli_wand, argv[i],
604% (count>0) ? argv[i+1] : (char *)NULL);
anthonydcf510d2011-10-30 13:51:40 +0000605% i += count+1;
606%
anthony805a2d42011-09-25 08:25:12 +0000607*/
anthonyafa3dfc2012-03-03 11:31:30 +0000608WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +0000609 const char *option,const char *arg1)
anthony805a2d42011-09-25 08:25:12 +0000610{
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);
614 if (cli_wand->wand.debug != MagickFalse)
615 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony1afdc7a2011-10-05 11:54:28 +0000616
anthony92c93bd2012-03-19 14:02:47 +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=='-')
622#define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
623#define ArgBooleanNot (IfSetOption?MagickFalse:MagickTrue)
624#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 {
anthony92c93bd2012-03-19 14:02:47 +0000654 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
655 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 }
664 break;
665 }
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
anthony72feaa62012-01-17 06:46:23 +0000675 we should fall back to image
676 Note that +background, means fall-back to image background
677 and only if not set fall back to BackgroundColor const.
anthony74b1cfc2011-10-06 12:44:16 +0000678 */
anthony92c93bd2012-03-19 14:02:47 +0000679 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000680 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000681 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000682 break;
683 }
anthonyafa3dfc2012-03-03 11:31:30 +0000684 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000685 {
anthony74b1cfc2011-10-06 12:44:16 +0000686 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000687 as it is actually rarely used except in direct convolve operations
688 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000689
690 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000691 */
anthony5330ae02012-03-20 14:17:01 +0000692 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
693 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000694 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000695 break;
696 }
anthonyafa3dfc2012-03-03 11:31:30 +0000697 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000698 {
anthony72feaa62012-01-17 06:46:23 +0000699 /* Used as a image chromaticity setting
700 SyncImageSettings() used to set per-image attribute.
701 */
anthony92c93bd2012-03-19 14:02:47 +0000702 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000703 break;
704 }
anthonyafa3dfc2012-03-03 11:31:30 +0000705 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000706 {
anthonyafbaed72011-10-26 12:05:04 +0000707 /* Image chromaticity X,Y NB: Y=X if Y not defined
708 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000709 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000710 */
anthony5330ae02012-03-20 14:17:01 +0000711 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
712 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000713 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000714 break;
715 }
anthonyafa3dfc2012-03-03 11:31:30 +0000716 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000717 {
anthony92c93bd2012-03-19 14:02:47 +0000718 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000719 SyncImageSettings() used to set per-image attribute.
720 */
anthony74b1cfc2011-10-06 12:44:16 +0000721 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000722 {
anthony92c93bd2012-03-19 14:02:47 +0000723 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000724 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000725 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000726 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000727 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000728 break;
729 }
anthony92c93bd2012-03-19 14:02:47 +0000730 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000731 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000732 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000733 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000734 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000735 break;
736 }
anthonyafa3dfc2012-03-03 11:31:30 +0000737 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000738 {
anthonyfd706f92012-01-19 04:22:02 +0000739 /* DEPRECIATED - now "undercolor" */
anthony24aa8822012-03-11 00:56:06 +0000740 CLISettingOptionInfo(cli_wand,"undercolor",arg1);
anthonyfd706f92012-01-19 04:22:02 +0000741 break;
anthony805a2d42011-09-25 08:25:12 +0000742 }
743 break;
744 }
745 case 'c':
746 {
anthonyafa3dfc2012-03-03 11:31:30 +0000747 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000748 {
749 MagickSizeType
750 limit;
751
anthony5330ae02012-03-20 14:17:01 +0000752 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
753 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000754 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000755 if (LocaleCompare("unlimited",arg1) != 0)
756 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000757 (void) SetMagickResourceLimit(MemoryResource,limit);
758 (void) SetMagickResourceLimit(MapResource,2*limit);
759 break;
760 }
anthonyafa3dfc2012-03-03 11:31:30 +0000761 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000762 {
anthony92c93bd2012-03-19 14:02:47 +0000763 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000764 break;
765 }
anthonyafa3dfc2012-03-03 11:31:30 +0000766 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000767 {
anthony43f425d2012-02-26 12:58:58 +0000768 /* FUTURE: -channel mask {vaules}
anthony24aa8822012-03-11 00:56:06 +0000769 This is also applied to images in SimpleImageOperator!!!
anthony43f425d2012-02-26 12:58:58 +0000770 Move it to SyncImageSettings() - or alternative
anthony31f1bf72012-01-30 12:37:22 +0000771 */
anthony5330ae02012-03-20 14:17:01 +0000772 ssize_t
773 channel = DefaultChannels;
774 if ( IfSetOption ) {
775 channel=ParseChannelOption(arg1);
776 if (channel < 0)
777 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
778 option,arg1);
cristydfdb19e2012-03-21 22:22:24 +0000779 (void) SetImageOption(_image_info,option+1,arg1);
780 } else {
781 (void) SetImageOption(_image_info,option+1,"default");
anthony5330ae02012-03-20 14:17:01 +0000782 }
783 _image_info->channel=(ChannelType) channel;
anthony805a2d42011-09-25 08:25:12 +0000784 break;
785 }
anthonyafa3dfc2012-03-03 11:31:30 +0000786 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000787 {
anthonyafbaed72011-10-26 12:05:04 +0000788 /* Setting used for new images via AquireImage()
789 But also used as a SimpleImageOperator
790 Undefined colorspace means don't modify images on
791 read or as a operation */
anthony5330ae02012-03-20 14:17:01 +0000792 ssize_t
793 colorspace = ParseCommandOption(MagickColorspaceOptions,
794 MagickFalse,ArgOption("undefined"));
795 if (colorspace < 0)
796 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
797 option,arg1);
798 _image_info->colorspace=(ColorspaceType) colorspace;
anthony805a2d42011-09-25 08:25:12 +0000799 break;
800 }
anthonyafa3dfc2012-03-03 11:31:30 +0000801 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000802 {
anthony92c93bd2012-03-19 14:02:47 +0000803 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000804 break;
805 }
anthonyafa3dfc2012-03-03 11:31:30 +0000806 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000807 {
anthony92c93bd2012-03-19 14:02:47 +0000808 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000809 SyncImageSettings() used to set per-image attribute. - REMOVE
810
anthonyafbaed72011-10-26 12:05:04 +0000811 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000812 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000813 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000814 */
anthony92c93bd2012-03-19 14:02:47 +0000815 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
816 _image_info->compose=(CompositeOperator) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000817 MagickComposeOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000818 break;
819 }
anthonyafa3dfc2012-03-03 11:31:30 +0000820 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000821 {
anthony92c93bd2012-03-19 14:02:47 +0000822 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000823 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000824 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000825
anthony92c93bd2012-03-19 14:02:47 +0000826 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000827 however the image attribute (for save) is set from the
828 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000829
830 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000831 */
anthony92c93bd2012-03-19 14:02:47 +0000832 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
833 _image_info->compression=(CompressionType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000834 MagickCompressOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000835 break;
836 }
837 break;
838 }
839 case 'd':
840 {
anthonyafa3dfc2012-03-03 11:31:30 +0000841 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000842 {
anthony72feaa62012-01-17 06:46:23 +0000843 /* SyncImageSettings() used to set per-image attribute. */
844 (void) SetLogEventMask(ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000845 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000846 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000847 break;
848 }
anthonyafa3dfc2012-03-03 11:31:30 +0000849 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000850 {
anthony24aa8822012-03-11 00:56:06 +0000851 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000852 {
anthony5f867ae2011-10-09 10:28:34 +0000853 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000854 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000855 else
anthony24aa8822012-03-11 00:56:06 +0000856 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000857 break;
858 }
anthony24aa8822012-03-11 00:56:06 +0000859 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000860 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000861 (void) DefineImageOption(_image_info,arg1);
anthony5f867ae2011-10-09 10:28:34 +0000862 else
anthony92c93bd2012-03-19 14:02:47 +0000863 (void) DeleteImageOption(_image_info,arg1);
anthony805a2d42011-09-25 08:25:12 +0000864 break;
865 }
anthonyafa3dfc2012-03-03 11:31:30 +0000866 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000867 {
anthonyafbaed72011-10-26 12:05:04 +0000868 /* Only used for new images via AcquireImage()
869 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000870 */
anthony92c93bd2012-03-19 14:02:47 +0000871 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000872 break;
873 }
anthonyafa3dfc2012-03-03 11:31:30 +0000874 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000875 {
anthony92c93bd2012-03-19 14:02:47 +0000876 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000877 Basically as density can be in a XxY form!
878
879 SyncImageSettings() used to set per-image attribute.
880 */
anthony92c93bd2012-03-19 14:02:47 +0000881 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
882 (void) CloneString(&_image_info->density,ArgOption(NULL));
883 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000884 break;
885 }
anthonyafa3dfc2012-03-03 11:31:30 +0000886 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000887 {
anthony72feaa62012-01-17 06:46:23 +0000888 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
889 SyncImageSettings() used to set per-image attribute.
890 */
anthony92c93bd2012-03-19 14:02:47 +0000891 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000892 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000893 break;
894 }
anthonyafa3dfc2012-03-03 11:31:30 +0000895 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000896 {
anthony92c93bd2012-03-19 14:02:47 +0000897 /* Image Option is only used to set _draw_info */
898 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
899 _draw_info->direction=(DirectionType) ParseCommandOption(
anthony5f867ae2011-10-09 10:28:34 +0000900 MagickDirectionOptions,MagickFalse,
anthony72feaa62012-01-17 06:46:23 +0000901 ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000902 break;
903 }
anthonyafa3dfc2012-03-03 11:31:30 +0000904 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000905 {
anthony92c93bd2012-03-19 14:02:47 +0000906 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
907 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000908 break;
909 }
anthonyafa3dfc2012-03-03 11:31:30 +0000910 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000911 {
anthony72feaa62012-01-17 06:46:23 +0000912 /* only used in setting new images */
anthony92c93bd2012-03-19 14:02:47 +0000913 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000914 break;
915 }
anthonyafa3dfc2012-03-03 11:31:30 +0000916 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000917 {
anthony92c93bd2012-03-19 14:02:47 +0000918 /* _image_info attr (on/off), _quantize_info attr (on/off)
919 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000920 FUTURE: merge the duality of the dithering options
921 */
anthony92c93bd2012-03-19 14:02:47 +0000922 _image_info->dither = _quantize_info->dither = ArgBoolean;
923 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
924 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000925 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000926 if (_quantize_info->dither_method == NoDitherMethod)
927 _image_info->dither = _quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000928 break;
929 }
930 break;
931 }
932 case 'e':
933 {
anthonyafa3dfc2012-03-03 11:31:30 +0000934 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000935 {
anthony92c93bd2012-03-19 14:02:47 +0000936 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
937 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000938 break;
939 }
anthonyafa3dfc2012-03-03 11:31:30 +0000940 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000941 {
anthony92c93bd2012-03-19 14:02:47 +0000942 /* Both _image_info attr and ImageInfo */
943 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
944 _image_info->endian=(EndianType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000945 MagickEndianOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000946 break;
947 }
anthonyafa3dfc2012-03-03 11:31:30 +0000948 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000949 {
anthony92c93bd2012-03-19 14:02:47 +0000950 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000951 break;
952 }
953 break;
954 }
955 case 'f':
956 {
anthonyafa3dfc2012-03-03 11:31:30 +0000957 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000958 {
anthony92c93bd2012-03-19 14:02:47 +0000959 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000960 break;
961 }
anthonyafa3dfc2012-03-03 11:31:30 +0000962 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000963 {
anthony92c93bd2012-03-19 14:02:47 +0000964 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000965 The original fill color is preserved if a fill-pattern is given.
966 That way it does not effect other operations that directly using
967 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000968 */
anthony6dc09cd2011-10-12 08:56:49 +0000969 const char
anthony72feaa62012-01-17 06:46:23 +0000970 *value;
971
972 MagickBooleanType
973 status;
anthony6dc09cd2011-10-12 08:56:49 +0000974
975 ExceptionInfo
976 *sans;
977
anthonyfd706f92012-01-19 04:22:02 +0000978 PixelInfo
979 color;
980
anthony72feaa62012-01-17 06:46:23 +0000981 value = ArgOption("none");
anthony92c93bd2012-03-19 14:02:47 +0000982 (void) SetImageOption(_image_info,option+1,value);
983 if (_draw_info->fill_pattern != (Image *) NULL)
984 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000985
986 /* is it a color or a image? -- ignore exceptions */
987 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +0000988 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000989 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000990
anthony6dc09cd2011-10-12 08:56:49 +0000991 if (status == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +0000992 _draw_info->fill_pattern=GetImageCache(_image_info,value,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000993 else
anthony92c93bd2012-03-19 14:02:47 +0000994 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000995 break;
996 }
anthonyafa3dfc2012-03-03 11:31:30 +0000997 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000998 {
anthony72feaa62012-01-17 06:46:23 +0000999 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001000 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001001 break;
1002 }
anthonyafa3dfc2012-03-03 11:31:30 +00001003 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001004 {
anthony92c93bd2012-03-19 14:02:47 +00001005 (void) CloneString(&_draw_info->font,ArgOption(NULL));
1006 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +00001007 break;
1008 }
anthonyafa3dfc2012-03-03 11:31:30 +00001009 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001010 {
anthonydcf510d2011-10-30 13:51:40 +00001011 /* FUTURE: why the ping test, you could set ping after this! */
1012 /*
anthony805a2d42011-09-25 08:25:12 +00001013 register const char
1014 *q;
1015
anthony24aa8822012-03-11 00:56:06 +00001016 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +00001017 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00001018 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +00001019 */
anthony92c93bd2012-03-19 14:02:47 +00001020 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001021 break;
1022 }
anthonyafa3dfc2012-03-03 11:31:30 +00001023 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001024 {
anthony72feaa62012-01-17 06:46:23 +00001025 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +00001026 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +00001027 SyncImageSettings() used to set per-image attribute.
1028
anthony92c93bd2012-03-19 14:02:47 +00001029 Can't find anything else using _image_info->fuzz directly!
anthony6613bf32011-10-15 07:24:44 +00001030 */
1031 if (IfSetOption)
cristy947cb4c2011-10-20 18:41:46 +00001032 {
anthony92c93bd2012-03-19 14:02:47 +00001033 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +00001034 QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00001035 (void) SetImageOption(_image_info,option+1,arg1);
cristy947cb4c2011-10-20 18:41:46 +00001036 break;
1037 }
anthony92c93bd2012-03-19 14:02:47 +00001038 _image_info->fuzz=0.0;
1039 (void) SetImageOption(_image_info,option+1,"0");
anthony805a2d42011-09-25 08:25:12 +00001040 break;
1041 }
1042 break;
1043 }
1044 case 'g':
1045 {
anthonyafa3dfc2012-03-03 11:31:30 +00001046 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001047 {
anthony72feaa62012-01-17 06:46:23 +00001048 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001049 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
1050 _draw_info->gravity=(GravityType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001051 MagickGravityOptions,MagickFalse,ArgOption("none"));
anthony805a2d42011-09-25 08:25:12 +00001052 break;
1053 }
anthonyafa3dfc2012-03-03 11:31:30 +00001054 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001055 {
anthonydcf510d2011-10-30 13:51:40 +00001056 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +00001057 SyncImageSettings() used to set per-image attribute.
1058 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +00001059 */
anthony92c93bd2012-03-19 14:02:47 +00001060 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001061 break;
1062 }
1063 break;
1064 }
1065 case 'i':
1066 {
anthonyafa3dfc2012-03-03 11:31:30 +00001067 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001068 {
anthony72feaa62012-01-17 06:46:23 +00001069 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +00001070 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +00001071 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001072 */
anthony92c93bd2012-03-19 14:02:47 +00001073 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001074 break;
1075 }
anthonyafa3dfc2012-03-03 11:31:30 +00001076 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001077 {
anthony92c93bd2012-03-19 14:02:47 +00001078 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +00001079 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001080 */
anthony92c93bd2012-03-19 14:02:47 +00001081 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
1082 _image_info->interlace=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001083 MagickInterlaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001084 break;
1085 }
anthonyafa3dfc2012-03-03 11:31:30 +00001086 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001087 {
anthony92c93bd2012-03-19 14:02:47 +00001088 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1089 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +00001090 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001091 break;
1092 }
anthonyafa3dfc2012-03-03 11:31:30 +00001093 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001094 {
anthonyfd706f92012-01-19 04:22:02 +00001095 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001096 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001097 break;
1098 }
anthonyafa3dfc2012-03-03 11:31:30 +00001099 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001100 {
anthony92c93bd2012-03-19 14:02:47 +00001101 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1102 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001103 break;
1104 }
1105 break;
1106 }
1107 case 'k':
1108 {
anthonyafa3dfc2012-03-03 11:31:30 +00001109 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001110 {
anthony92c93bd2012-03-19 14:02:47 +00001111 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1112 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001113 break;
1114 }
1115 break;
1116 }
1117 case 'l':
1118 {
anthonyafa3dfc2012-03-03 11:31:30 +00001119 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001120 {
anthony72feaa62012-01-17 06:46:23 +00001121 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001122 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001123 break;
1124 }
anthonyafa3dfc2012-03-03 11:31:30 +00001125 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001126 {
anthonydcf510d2011-10-30 13:51:40 +00001127 if (IfSetOption)
anthony24aa8822012-03-11 00:56:06 +00001128 (void) SetLogFormat(arg1);
anthony805a2d42011-09-25 08:25:12 +00001129 break;
1130 }
anthonyafa3dfc2012-03-03 11:31:30 +00001131 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001132 {
anthony72feaa62012-01-17 06:46:23 +00001133 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001134 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001135 break;
1136 }
1137 break;
1138 }
1139 case 'm':
1140 {
anthonyafa3dfc2012-03-03 11:31:30 +00001141 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001142 {
anthony72feaa62012-01-17 06:46:23 +00001143 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001144 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001145 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001146 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001147 break;
1148 }
anthonyafa3dfc2012-03-03 11:31:30 +00001149 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001150 {
anthony92c93bd2012-03-19 14:02:47 +00001151 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001152 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001153 break;
1154 }
anthonyafa3dfc2012-03-03 11:31:30 +00001155 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001156 {
anthony24aa8822012-03-11 00:56:06 +00001157 /* Setting (used by some input coders!) -- why?
1158 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001159 */
anthony92c93bd2012-03-19 14:02:47 +00001160 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001161 break;
1162 }
1163 break;
1164 }
1165 case 'o':
1166 {
anthonyafa3dfc2012-03-03 11:31:30 +00001167 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001168 {
anthony72feaa62012-01-17 06:46:23 +00001169 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001170 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001171 FUTURE: make set meta-data operator instead.
1172 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001173 */
anthony92c93bd2012-03-19 14:02:47 +00001174 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1175 _image_info->orientation=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001176 MagickOrientationOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001177 break;
1178 }
1179 }
1180 case 'p':
1181 {
anthonyafa3dfc2012-03-03 11:31:30 +00001182 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001183 {
anthony72feaa62012-01-17 06:46:23 +00001184 /* Only used for new images and image generators
1185 SyncImageSettings() used to set per-image attribute. ?????
1186 That last is WRONG!!!!
1187 */
anthony805a2d42011-09-25 08:25:12 +00001188 char
1189 *canonical_page,
1190 page[MaxTextExtent];
1191
1192 const char
1193 *image_option;
1194
1195 MagickStatusType
1196 flags;
1197
1198 RectangleInfo
1199 geometry;
1200
anthonydcf510d2011-10-30 13:51:40 +00001201 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001202 {
anthony92c93bd2012-03-19 14:02:47 +00001203 (void) DeleteImageOption(_image_info,option+1);
1204 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001205 break;
1206 }
1207 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001208 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001209 if (image_option != (const char *) NULL)
1210 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001211 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001212 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1213 canonical_page=DestroyString(canonical_page);
1214 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1215 (unsigned long) geometry.width,(unsigned long) geometry.height);
1216 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1217 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1218 (unsigned long) geometry.width,(unsigned long) geometry.height,
1219 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001220 (void) SetImageOption(_image_info,option+1,page);
1221 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001222 break;
1223 }
anthonyafa3dfc2012-03-03 11:31:30 +00001224 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001225 {
anthony92c93bd2012-03-19 14:02:47 +00001226 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001227 break;
1228 }
anthonyafa3dfc2012-03-03 11:31:30 +00001229 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001230 {
anthony92c93bd2012-03-19 14:02:47 +00001231 _image_info->pointsize=_draw_info->pointsize=
anthony72feaa62012-01-17 06:46:23 +00001232 StringToDouble(ArgOption("12"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001233 break;
1234 }
anthonyafa3dfc2012-03-03 11:31:30 +00001235 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001236 {
anthony72feaa62012-01-17 06:46:23 +00001237 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
anthony805a2d42011-09-25 08:25:12 +00001238 break;
1239 }
anthonydcf510d2011-10-30 13:51:40 +00001240 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001241 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001242 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001243 {
anthony92c93bd2012-03-19 14:02:47 +00001244 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001245 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001246 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001247 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001248 break;
1249 }
anthonydcf510d2011-10-30 13:51:40 +00001250 */
anthony805a2d42011-09-25 08:25:12 +00001251 break;
1252 }
1253 case 'q':
1254 {
anthonyafa3dfc2012-03-03 11:31:30 +00001255 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001256 {
anthony92c93bd2012-03-19 14:02:47 +00001257 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1258 _image_info->quality=UNDEFINED_COMPRESSION_QUALITY;
anthony72feaa62012-01-17 06:46:23 +00001259 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001260 _image_info->quality=StringToUnsignedLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00001261 break;
1262 }
anthonyafa3dfc2012-03-03 11:31:30 +00001263 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001264 {
anthony92c93bd2012-03-19 14:02:47 +00001265 /* Just a set direct in _quantize_info */
1266 _quantize_info->colorspace=UndefinedColorspace;
anthonyafbaed72011-10-26 12:05:04 +00001267 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001268 _quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001269 MagickColorspaceOptions,MagickFalse,arg1);
anthonyafbaed72011-10-26 12:05:04 +00001270 break;
1271 }
anthonyafa3dfc2012-03-03 11:31:30 +00001272 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001273 {
anthonydcf510d2011-10-30 13:51:40 +00001274 /* FUTURE: if two -quiet is performed you can not do +quiet! */
anthony805a2d42011-09-25 08:25:12 +00001275 static WarningHandler
1276 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001277
anthonyafbaed72011-10-26 12:05:04 +00001278 WarningHandler
1279 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001280
anthonyafbaed72011-10-26 12:05:04 +00001281 if ( tmp != (WarningHandler) NULL)
1282 warning_handler = tmp; /* remember the old handler */
1283 if (!IfSetOption) /* set the old handler */
1284 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001285 break;
1286 }
1287 break;
1288 }
1289 case 'r':
1290 {
anthonyafa3dfc2012-03-03 11:31:30 +00001291 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001292 {
anthonydcf510d2011-10-30 13:51:40 +00001293 /* Image chromaticity X,Y NB: Y=X if Y not defined
1294 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001295 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001296 */
anthony92c93bd2012-03-19 14:02:47 +00001297 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001298 break;
1299 }
anthonyafa3dfc2012-03-03 11:31:30 +00001300 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001301 {
anthony92c93bd2012-03-19 14:02:47 +00001302 /* _draw_info only setting */
1303 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001304 break;
1305 }
anthony805a2d42011-09-25 08:25:12 +00001306 break;
1307 }
1308 case 's':
1309 {
anthonyafa3dfc2012-03-03 11:31:30 +00001310 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001311 {
anthonyafbaed72011-10-26 12:05:04 +00001312 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony92c93bd2012-03-19 14:02:47 +00001313 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001314 break;
1315 }
anthonyafa3dfc2012-03-03 11:31:30 +00001316 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001317 {
anthony72feaa62012-01-17 06:46:23 +00001318 /* SyncImageSettings() used to set per-image attribute.
1319 What ??? Why ????
1320 */
anthony92c93bd2012-03-19 14:02:47 +00001321 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1322 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001323 break;
1324 }
anthonyafa3dfc2012-03-03 11:31:30 +00001325 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001326 {
anthonyafbaed72011-10-26 12:05:04 +00001327 SeedPseudoRandomGenerator(
anthony24aa8822012-03-11 00:56:06 +00001328 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001329 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001330 break;
1331 }
anthonyafa3dfc2012-03-03 11:31:30 +00001332 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001333 {
anthony92c93bd2012-03-19 14:02:47 +00001334 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001335 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001336 */
anthony92c93bd2012-03-19 14:02:47 +00001337 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001338 break;
1339 }
anthonyafa3dfc2012-03-03 11:31:30 +00001340 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001341 {
anthony92c93bd2012-03-19 14:02:47 +00001342 _draw_info->stretch=(StretchType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001343 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001344 break;
1345 }
anthonyafa3dfc2012-03-03 11:31:30 +00001346 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001347 {
anthonyafbaed72011-10-26 12:05:04 +00001348 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001349 UPDATE: ensure stroke color is not destroyed is a pattern
1350 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001351 */
1352 const char
anthony72feaa62012-01-17 06:46:23 +00001353 *value;
1354
1355 MagickBooleanType
1356 status;
anthonyafbaed72011-10-26 12:05:04 +00001357
1358 ExceptionInfo
1359 *sans;
1360
anthonyfd706f92012-01-19 04:22:02 +00001361 PixelInfo
1362 color;
1363
anthony72feaa62012-01-17 06:46:23 +00001364 value = ArgOption("none");
anthony92c93bd2012-03-19 14:02:47 +00001365 (void) SetImageOption(_image_info,option+1,value);
1366 if (_draw_info->stroke_pattern != (Image *) NULL)
1367 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001368
1369 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001370 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +00001371 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001372 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001373
anthonyafbaed72011-10-26 12:05:04 +00001374 if (status == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00001375 _draw_info->stroke_pattern=GetImageCache(_image_info,value,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001376 else
anthony92c93bd2012-03-19 14:02:47 +00001377 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001378 break;
1379 }
anthonyafa3dfc2012-03-03 11:31:30 +00001380 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001381 {
anthony92c93bd2012-03-19 14:02:47 +00001382 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1383 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001384 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001385 break;
1386 }
anthonyafa3dfc2012-03-03 11:31:30 +00001387 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001388 {
anthony92c93bd2012-03-19 14:02:47 +00001389 _draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
anthony72feaa62012-01-17 06:46:23 +00001390 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001391 break;
1392 }
anthonyafa3dfc2012-03-03 11:31:30 +00001393 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001394 {
anthony92c93bd2012-03-19 14:02:47 +00001395 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001396 break;
1397 }
1398 break;
1399 }
1400 case 't':
1401 {
anthonyafa3dfc2012-03-03 11:31:30 +00001402 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001403 {
anthony72feaa62012-01-17 06:46:23 +00001404 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001405 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001406 break;
1407 }
anthonyafa3dfc2012-03-03 11:31:30 +00001408 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001409 {
anthony92c93bd2012-03-19 14:02:47 +00001410 /* FUTURE: move _image_info string to option splay-tree */
1411 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001412 break;
1413 }
anthonyafa3dfc2012-03-03 11:31:30 +00001414 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001415 {
anthony92c93bd2012-03-19 14:02:47 +00001416 _draw_info->fill_pattern=IfSetOption
1417 ?GetImageCache(_image_info,arg1,_exception)
1418 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001419 break;
1420 }
anthonyafa3dfc2012-03-03 11:31:30 +00001421 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001422 {
anthony72feaa62012-01-17 06:46:23 +00001423 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony92c93bd2012-03-19 14:02:47 +00001424 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001425 break;
1426 }
anthonyafa3dfc2012-03-03 11:31:30 +00001427 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001428 {
anthony92c93bd2012-03-19 14:02:47 +00001429 /* FUTURE: both _image_info attribute & ImageOption in use!
1430 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001431 SyncImageSettings() used to set per-image attribute.
1432
anthonyafbaed72011-10-26 12:05:04 +00001433 Note that +transparent-color, means fall-back to image
1434 attribute so ImageOption is deleted, not set to a default.
1435 */
anthony92c93bd2012-03-19 14:02:47 +00001436 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001437 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001438 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001439 break;
1440 }
anthonyafa3dfc2012-03-03 11:31:30 +00001441 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001442 {
anthony92c93bd2012-03-19 14:02:47 +00001443 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1444 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001445 break;
1446 }
anthonyafa3dfc2012-03-03 11:31:30 +00001447 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001448 {
anthony72feaa62012-01-17 06:46:23 +00001449 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001450 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1451 _image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
anthony72feaa62012-01-17 06:46:23 +00001452 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001453 break;
1454 }
1455 break;
1456 }
1457 case 'u':
1458 {
anthonyafa3dfc2012-03-03 11:31:30 +00001459 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001460 {
anthony92c93bd2012-03-19 14:02:47 +00001461 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001462 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001463 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001464 break;
1465 }
anthonyafa3dfc2012-03-03 11:31:30 +00001466 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001467 {
anthony72feaa62012-01-17 06:46:23 +00001468 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001469 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001470 FUTURE: this probably should be part of the density setting
1471 */
anthony92c93bd2012-03-19 14:02:47 +00001472 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1473 _image_info->units=(ResolutionType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001474 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001475 break;
1476 }
1477 break;
1478 }
1479 case 'v':
1480 {
anthonyafa3dfc2012-03-03 11:31:30 +00001481 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001482 {
anthony24aa8822012-03-11 00:56:06 +00001483 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001484 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001485 */
anthony92c93bd2012-03-19 14:02:47 +00001486 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1487 _image_info->verbose= ArgBoolean;
1488 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001489 break;
1490 }
anthonyafa3dfc2012-03-03 11:31:30 +00001491 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001492 {
anthony92c93bd2012-03-19 14:02:47 +00001493 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001494 Only used by coder FPX
1495 */
anthony92c93bd2012-03-19 14:02:47 +00001496 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001497 break;
1498 }
anthonyafa3dfc2012-03-03 11:31:30 +00001499 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001500 {
anthonyfd706f92012-01-19 04:22:02 +00001501 /* SyncImageSettings() used to set per-image attribute.
1502 This is VERY deep in the image caching structure.
1503 */
anthony92c93bd2012-03-19 14:02:47 +00001504 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001505 break;
1506 }
1507 break;
1508 }
1509 case 'w':
1510 {
anthonyafa3dfc2012-03-03 11:31:30 +00001511 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001512 {
anthony72feaa62012-01-17 06:46:23 +00001513 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001514 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001515 */
anthony72feaa62012-01-17 06:46:23 +00001516 if (!IfSetOption)
1517 break;
anthony92c93bd2012-03-19 14:02:47 +00001518 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001519 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001520 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001521 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001522 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001523 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001524 if (_draw_info->weight <= 800)
1525 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001526 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001527 if (_draw_info->weight >= 100)
1528 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001529 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001530 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001531 break;
1532 }
anthonyafa3dfc2012-03-03 11:31:30 +00001533 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001534 {
anthony72feaa62012-01-17 06:46:23 +00001535 /* Used as a image chromaticity setting
1536 SyncImageSettings() used to set per-image attribute.
1537 */
anthony92c93bd2012-03-19 14:02:47 +00001538 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001539 break;
1540 }
1541 break;
1542 }
1543 default:
1544 break;
1545 }
anthony24aa8822012-03-11 00:56:06 +00001546
anthony92c93bd2012-03-19 14:02:47 +00001547#undef _image_info
1548#undef _exception
1549#undef _draw_info
1550#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001551#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001552#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001553#undef ArgBooleanNot
1554#undef ArgBooleanString
1555#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001556
anthony31f1bf72012-01-30 12:37:22 +00001557 return;
anthony805a2d42011-09-25 08:25:12 +00001558}
1559
1560/*
1561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1562% %
1563% %
1564% %
anthony43f425d2012-02-26 12:58:58 +00001565+ 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 +00001566% %
1567% %
1568% %
1569%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1570%
anthony31f1bf72012-01-30 12:37:22 +00001571% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001572% the images in the CLI wand, with the settings that was previously saved in
1573% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001574%
1575% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001576% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001577%
anthonyd1447672012-01-19 05:33:53 +00001578% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001579%
anthony43f425d2012-02-26 12:58:58 +00001580% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001581% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001582%
1583% A description of each parameter follows:
1584%
anthony43f425d2012-02-26 12:58:58 +00001585% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001586%
anthonyfd706f92012-01-19 04:22:02 +00001587% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001588%
anthonyfd706f92012-01-19 04:22:02 +00001589% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001590%
anthony31f1bf72012-01-30 12:37:22 +00001591% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001592%
anthony31f1bf72012-01-30 12:37:22 +00001593% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001594%
anthonyafa3dfc2012-03-03 11:31:30 +00001595% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1596% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1597% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001598%
anthony24aa8822012-03-11 00:56:06 +00001599% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +00001600%
anthony43f425d2012-02-26 12:58:58 +00001601% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001602% argc,argv
1603% i=index in argv
1604%
anthony2052d272012-02-28 12:48:29 +00001605% option_info = GetCommandOptionInfo(argv[i]);
1606% count=option_info->type;
1607% option_type=option_info->flags;
1608%
1609% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001610% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001611% count>=1 ? argv[i+1] : (char *)NULL,
1612% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001613% i += count+1;
1614%
anthony805a2d42011-09-25 08:25:12 +00001615*/
anthony31f1bf72012-01-30 12:37:22 +00001616
1617/*
1618 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001619 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001620
1621 The image in the list may be modified in three different ways...
1622 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1623 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1624 * one image replace by a list of images (-separate and -crop only!)
1625
anthonyafa3dfc2012-03-03 11:31:30 +00001626 In each case the result replaces the single original image in the list, as
1627 well as the pointer to the modified image (last image added if replaced by a
1628 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001629
1630 As the image pointed to may be replaced, the first image in the list may
1631 also change. GetFirstImageInList() should be used by caller if they wish
1632 return the Image pointer to the first image in list.
1633*/
anthony43f425d2012-02-26 12:58:58 +00001634static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001635 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001636{
1637 Image *
1638 new_image;
1639
anthony805a2d42011-09-25 08:25:12 +00001640 GeometryInfo
1641 geometry_info;
1642
1643 RectangleInfo
1644 geometry;
1645
1646 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001647 flags;
1648
anthony92c93bd2012-03-19 14:02:47 +00001649 ssize_t
1650 type;
1651
1652#define _image_info (cli_wand->wand.image_info)
1653#define _image (cli_wand->wand.images)
1654#define _exception (cli_wand->wand.exception)
1655#define _draw_info (cli_wand->draw_info)
1656#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001657#define IfNormalOp (*option=='-')
1658#define IfPlusOp (*option!='-')
1659#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
1660#define plus_alt_op (IfNormalOp?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001661
anthony43f425d2012-02-26 12:58:58 +00001662 assert(cli_wand != (MagickCLI *) NULL);
1663 assert(cli_wand->signature == WandSignature);
1664 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001665 assert(_image != (Image *) NULL); /* an image must be present */
anthony43f425d2012-02-26 12:58:58 +00001666 if (cli_wand->wand.debug != MagickFalse)
1667 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001668
anthony92c93bd2012-03-19 14:02:47 +00001669 (void) SyncImageSettings(_image_info,_image,_exception);
anthony24aa8822012-03-11 00:56:06 +00001670
anthony805a2d42011-09-25 08:25:12 +00001671 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001672
anthony5330ae02012-03-20 14:17:01 +00001673 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001674
anthonyfd706f92012-01-19 04:22:02 +00001675 /* FUTURE: We may need somthing a little more optimized than this!
1676 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1677 */
anthonyafa3dfc2012-03-03 11:31:30 +00001678 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001679 {
1680 case 'a':
1681 {
anthonyafa3dfc2012-03-03 11:31:30 +00001682 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001683 {
anthony92c93bd2012-03-19 14:02:47 +00001684 if (IsGeometry(arg1) == MagickFalse)
1685 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001686 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001687 if ((flags & SigmaValue) == 0)
1688 geometry_info.sigma=1.0;
1689 if ((flags & XiValue) == 0)
1690 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001691 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1692 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001693 break;
1694 }
anthonyafa3dfc2012-03-03 11:31:30 +00001695 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001696 {
anthony92c93bd2012-03-19 14:02:47 +00001697 if (IsGeometry(arg1) == MagickFalse)
1698 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1699 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1700 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1701 _exception);
anthony805a2d42011-09-25 08:25:12 +00001702 break;
1703 }
anthonyafa3dfc2012-03-03 11:31:30 +00001704 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001705 {
anthony92c93bd2012-03-19 14:02:47 +00001706 if (IsGeometry(arg1) == MagickFalse)
1707 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001708 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001709 if ((flags & SigmaValue) == 0)
1710 geometry_info.sigma=1.0;
1711 if ((flags & XiValue) == 0)
1712 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001713 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1714 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001715 break;
1716 }
anthonyafa3dfc2012-03-03 11:31:30 +00001717 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001718 {
anthony92c93bd2012-03-19 14:02:47 +00001719 type=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1720 if (type < 0)
1721 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1722 option,arg1);
1723 (void) SetImageAlphaChannel(_image,(AlphaChannelType)type,_exception);
anthony805a2d42011-09-25 08:25:12 +00001724 break;
1725 }
anthonyafa3dfc2012-03-03 11:31:30 +00001726 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001727 {
1728 char
1729 *text,
1730 geometry[MaxTextExtent];
1731
anthony92c93bd2012-03-19 14:02:47 +00001732 if (IsGeometry(arg1) == MagickFalse)
1733 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001734 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001735 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001736 if ((flags & SigmaValue) == 0)
1737 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001738 text=InterpretImageProperties(_image_info,_image,arg2,
1739 _exception);
anthony805a2d42011-09-25 08:25:12 +00001740 if (text == (char *) NULL)
1741 break;
anthony92c93bd2012-03-19 14:02:47 +00001742 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001743 text=DestroyString(text);
1744 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1745 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001746 (void) CloneString(&_draw_info->geometry,geometry);
1747 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001748 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001749 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001750 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001751 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001752 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001753 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001754 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001755 (void) AnnotateImage(_image,_draw_info,_exception);
1756 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001757 break;
1758 }
anthonyafa3dfc2012-03-03 11:31:30 +00001759 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001760 {
anthony92c93bd2012-03-19 14:02:47 +00001761 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001762 break;
1763 }
anthonyafa3dfc2012-03-03 11:31:30 +00001764 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001765 {
anthony92c93bd2012-03-19 14:02:47 +00001766 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001767 break;
1768 }
anthonyafa3dfc2012-03-03 11:31:30 +00001769 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001770 {
anthony5330ae02012-03-20 14:17:01 +00001771 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001772 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001773 {
1774 case TopRightOrientation:
1775 {
anthony92c93bd2012-03-19 14:02:47 +00001776 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001777 break;
1778 }
1779 case BottomRightOrientation:
1780 {
anthony92c93bd2012-03-19 14:02:47 +00001781 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001782 break;
1783 }
1784 case BottomLeftOrientation:
1785 {
anthony92c93bd2012-03-19 14:02:47 +00001786 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001787 break;
1788 }
1789 case LeftTopOrientation:
1790 {
anthony92c93bd2012-03-19 14:02:47 +00001791 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001792 break;
1793 }
1794 case RightTopOrientation:
1795 {
anthony92c93bd2012-03-19 14:02:47 +00001796 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001797 break;
1798 }
1799 case RightBottomOrientation:
1800 {
anthony92c93bd2012-03-19 14:02:47 +00001801 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001802 break;
1803 }
1804 case LeftBottomOrientation:
1805 {
anthony92c93bd2012-03-19 14:02:47 +00001806 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001807 break;
1808 }
1809 default:
1810 break;
1811 }
1812 if (new_image != (Image *) NULL)
1813 new_image->orientation=TopLeftOrientation;
1814 break;
1815 }
1816 break;
1817 }
1818 case 'b':
1819 {
anthonyafa3dfc2012-03-03 11:31:30 +00001820 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001821 {
anthony5330ae02012-03-20 14:17:01 +00001822 if (IsGeometry(arg1) == MagickFalse)
1823 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001824 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001825 break;
1826 }
anthonyafa3dfc2012-03-03 11:31:30 +00001827 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001828 {
anthony805a2d42011-09-25 08:25:12 +00001829 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001830 if (IfNormalOp) {
1831 if (IsGeometry(arg1) == MagickFalse)
1832 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001833 flags=ParseGeometry(arg1,&geometry_info);
anthony5330ae02012-03-20 14:17:01 +00001834 }
anthony92c93bd2012-03-19 14:02:47 +00001835 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001836 break;
1837 }
anthonyafa3dfc2012-03-03 11:31:30 +00001838 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001839 {
anthony74b1cfc2011-10-06 12:44:16 +00001840 /* FUTURE: use of "bias" in a blur is non-sensible */
anthony5330ae02012-03-20 14:17:01 +00001841 if (IsGeometry(arg1) == MagickFalse)
1842 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001843 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001844 if ((flags & SigmaValue) == 0)
1845 geometry_info.sigma=1.0;
1846 if ((flags & XiValue) == 0)
1847 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001848 new_image=BlurImage(_image,geometry_info.rho,
1849 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001850 break;
1851 }
anthonyafa3dfc2012-03-03 11:31:30 +00001852 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001853 {
anthony31f1bf72012-01-30 12:37:22 +00001854 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001855 compose;
1856
1857 const char*
anthony5f867ae2011-10-09 10:28:34 +00001858 value;
1859
anthony5330ae02012-03-20 14:17:01 +00001860 if (IsGeometry(arg1) == MagickFalse)
1861 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1862
anthony92c93bd2012-03-19 14:02:47 +00001863 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001864 if (value != (const char *) NULL)
1865 compose=(CompositeOperator) ParseCommandOption(
1866 MagickComposeOptions,MagickFalse,value);
1867 else
anthony92c93bd2012-03-19 14:02:47 +00001868 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001869
anthony92c93bd2012-03-19 14:02:47 +00001870 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001871 if ((flags & SigmaValue) == 0)
1872 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00001873 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001874 break;
1875 }
anthonyafa3dfc2012-03-03 11:31:30 +00001876 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001877 {
1878 double
1879 brightness,
1880 contrast;
1881
1882 GeometryInfo
1883 geometry_info;
1884
1885 MagickStatusType
1886 flags;
1887
anthony5330ae02012-03-20 14:17:01 +00001888 if (IsGeometry(arg1) == MagickFalse)
1889 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001890 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001891 brightness=geometry_info.rho;
1892 contrast=0.0;
1893 if ((flags & SigmaValue) != 0)
1894 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001895 (void) BrightnessContrastImage(_image,brightness,contrast,
1896 _exception);
anthony805a2d42011-09-25 08:25:12 +00001897 break;
1898 }
1899 break;
1900 }
1901 case 'c':
1902 {
anthonyafa3dfc2012-03-03 11:31:30 +00001903 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001904 {
1905 char
1906 *color_correction_collection;
1907
1908 /*
1909 Color correct with a color decision list.
1910 */
anthony92c93bd2012-03-19 14:02:47 +00001911 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001912 if (color_correction_collection == (char *) NULL)
1913 break;
anthony92c93bd2012-03-19 14:02:47 +00001914 (void) ColorDecisionListImage(_image,color_correction_collection,
1915 _exception);
anthony805a2d42011-09-25 08:25:12 +00001916 break;
1917 }
anthonyafa3dfc2012-03-03 11:31:30 +00001918 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001919 {
anthonyfd706f92012-01-19 04:22:02 +00001920 /* The "channel" setting has already been set
anthony24aa8822012-03-11 00:56:06 +00001921 FUTURE: This probably should be part of SyncImageSettings().
anthony5330ae02012-03-20 14:17:01 +00001922 How is it applied to new images?
anthony92c93bd2012-03-19 14:02:47 +00001923 SetPixelChannelMapMask(_image,_image_info->channel);
cristyddf87b62012-03-21 21:00:20 +00001924 */
anthony805a2d42011-09-25 08:25:12 +00001925 break;
1926 }
anthonyafa3dfc2012-03-03 11:31:30 +00001927 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001928 {
anthony5330ae02012-03-20 14:17:01 +00001929 if (IsGeometry(arg1) == MagickFalse)
1930 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001931 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001932 if ((flags & SigmaValue) == 0)
1933 geometry_info.sigma=1.0;
1934 if ((flags & XiValue) == 0)
1935 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001936 new_image=CharcoalImage(_image,geometry_info.rho,
1937 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001938 break;
1939 }
anthonyafa3dfc2012-03-03 11:31:30 +00001940 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001941 {
anthony5330ae02012-03-20 14:17:01 +00001942 if (IsGeometry(arg1) == MagickFalse)
1943 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001944 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1945 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001946 break;
1947 }
anthonyafa3dfc2012-03-03 11:31:30 +00001948 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001949 {
anthony92c93bd2012-03-19 14:02:47 +00001950 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001951 break;
1952 }
anthonyafa3dfc2012-03-03 11:31:30 +00001953 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001954 {
anthonyafa3dfc2012-03-03 11:31:30 +00001955 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001956 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001957 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001958 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001959 break;
1960 }
anthonyafa3dfc2012-03-03 11:31:30 +00001961 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001962 {
1963 CacheView
1964 *mask_view;
1965
1966 Image
1967 *mask_image;
1968
1969 register Quantum
1970 *restrict q;
1971
1972 register ssize_t
1973 x;
1974
1975 ssize_t
1976 y;
1977
anthonyafa3dfc2012-03-03 11:31:30 +00001978 if (IfPlusOp) {
1979 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001980 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00001981 break;
1982 }
anthony92c93bd2012-03-19 14:02:47 +00001983 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001984 if (mask_image == (Image *) NULL)
1985 break;
anthony92c93bd2012-03-19 14:02:47 +00001986 if (SetImageStorageClass(mask_image,DirectClass,_exception)
anthonyfd706f92012-01-19 04:22:02 +00001987 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001988 break;
anthony5330ae02012-03-20 14:17:01 +00001989 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00001990 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00001991 mask_view=AcquireCacheView(mask_image);
1992 for (y=0; y < (ssize_t) mask_image->rows; y++)
1993 {
1994 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00001995 _exception);
anthony805a2d42011-09-25 08:25:12 +00001996 if (q == (Quantum *) NULL)
1997 break;
1998 for (x=0; x < (ssize_t) mask_image->columns; x++)
1999 {
2000 if (mask_image->matte == MagickFalse)
2001 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
2002 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2003 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2004 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2005 q+=GetPixelChannels(mask_image);
2006 }
anthony92c93bd2012-03-19 14:02:47 +00002007 if (SyncCacheViewAuthenticPixels(mask_view,_exception) == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002008 break;
2009 }
anthonyfd706f92012-01-19 04:22:02 +00002010 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002011 mask_view=DestroyCacheView(mask_view);
2012 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002013 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002014 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002015 break;
2016 }
anthonyafa3dfc2012-03-03 11:31:30 +00002017 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002018 {
anthony92c93bd2012-03-19 14:02:47 +00002019 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002020 break;
2021 }
anthonyafa3dfc2012-03-03 11:31:30 +00002022 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002023 {
anthony5330ae02012-03-20 14:17:01 +00002024 if (IsGeometry(arg1) == MagickFalse)
2025 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002026 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002027 break;
2028 }
anthonyafa3dfc2012-03-03 11:31:30 +00002029 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002030 {
2031 KernelInfo
2032 *kernel;
2033
anthonyfd706f92012-01-19 04:22:02 +00002034 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002035 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002036 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002037 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002038 kernel=DestroyKernelInfo(kernel);
2039 break;
2040 }
anthonyafa3dfc2012-03-03 11:31:30 +00002041 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002042 {
anthony5330ae02012-03-20 14:17:01 +00002043 /* Reduce the number of colors in the image.
2044 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002045 */
anthony92c93bd2012-03-19 14:02:47 +00002046 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2047 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002048 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002049 if ((_image->storage_class == DirectClass) ||
2050 _image->colors > _quantize_info->number_colors)
2051 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002052 else
anthony92c93bd2012-03-19 14:02:47 +00002053 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002054 break;
2055 }
anthonyafa3dfc2012-03-03 11:31:30 +00002056 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002057 {
anthony5330ae02012-03-20 14:17:01 +00002058 /* WARNING: this is both a image_info setting (already done)
2059 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002060
2061 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002062 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002063
anthonyd2cdc862011-10-07 14:07:17 +00002064 Note that +colorspace sets "undefined" or no effect on
2065 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002066 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002067 */
anthony92c93bd2012-03-19 14:02:47 +00002068 (void) TransformImageColorspace(_image,
2069 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2070 _exception);
anthony805a2d42011-09-25 08:25:12 +00002071 break;
2072 }
anthonyafa3dfc2012-03-03 11:31:30 +00002073 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002074 {
anthony92c93bd2012-03-19 14:02:47 +00002075 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002076 break;
2077 }
anthonyafa3dfc2012-03-03 11:31:30 +00002078 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002079 {
2080 double
2081 black_point,
2082 white_point;
2083
2084 MagickStatusType
2085 flags;
2086
anthonyfd706f92012-01-19 04:22:02 +00002087 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002088 black_point=geometry_info.rho;
2089 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2090 black_point;
2091 if ((flags & PercentValue) != 0)
2092 {
anthony92c93bd2012-03-19 14:02:47 +00002093 black_point*=(double) _image->columns*_image->rows/100.0;
2094 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002095 }
anthony92c93bd2012-03-19 14:02:47 +00002096 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002097 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002098 (void) ContrastStretchImage(_image,black_point,white_point,
2099 _exception);
anthony805a2d42011-09-25 08:25:12 +00002100 break;
2101 }
anthonyafa3dfc2012-03-03 11:31:30 +00002102 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002103 {
2104 KernelInfo
2105 *kernel_info;
2106
anthonyfd706f92012-01-19 04:22:02 +00002107 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002108 if (kernel_info == (KernelInfo *) NULL)
2109 break;
anthony92c93bd2012-03-19 14:02:47 +00002110 kernel_info->bias=_image->bias;
2111 new_image=ConvolveImage(_image,kernel_info,_exception);
anthony805a2d42011-09-25 08:25:12 +00002112 kernel_info=DestroyKernelInfo(kernel_info);
2113 break;
2114 }
anthonyafa3dfc2012-03-03 11:31:30 +00002115 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002116 {
anthony31f1bf72012-01-30 12:37:22 +00002117 /* WARNING: This can generate multiple images! */
anthony92c93bd2012-03-19 14:02:47 +00002118 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002119 break;
2120 }
anthonyafa3dfc2012-03-03 11:31:30 +00002121 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002122 {
anthony92c93bd2012-03-19 14:02:47 +00002123 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2124 _exception);
anthony805a2d42011-09-25 08:25:12 +00002125 break;
2126 }
2127 break;
2128 }
2129 case 'd':
2130 {
anthonyafa3dfc2012-03-03 11:31:30 +00002131 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002132 {
2133 StringInfo
2134 *passkey;
2135
anthony92c93bd2012-03-19 14:02:47 +00002136 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002137 if (passkey != (StringInfo *) NULL)
2138 {
anthony92c93bd2012-03-19 14:02:47 +00002139 (void) PasskeyDecipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002140 passkey=DestroyStringInfo(passkey);
2141 }
2142 break;
2143 }
anthonyafa3dfc2012-03-03 11:31:30 +00002144 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002145 {
anthony92c93bd2012-03-19 14:02:47 +00002146 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002147 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002148
anthonydcf510d2011-10-30 13:51:40 +00002149 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2150 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002151
anthonyfd706f92012-01-19 04:22:02 +00002152 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002153 */
anthony92c93bd2012-03-19 14:02:47 +00002154 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002155 break;
2156 }
anthonyafa3dfc2012-03-03 11:31:30 +00002157 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002158 {
2159 double
2160 threshold;
2161
anthonyafa3dfc2012-03-03 11:31:30 +00002162 if (IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00002163 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyafa3dfc2012-03-03 11:31:30 +00002164 else
2165 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002166 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002167 break;
2168 }
anthonyafa3dfc2012-03-03 11:31:30 +00002169 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002170 {
anthony92c93bd2012-03-19 14:02:47 +00002171 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002172 break;
2173 }
anthonyafa3dfc2012-03-03 11:31:30 +00002174 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002175 {
2176 char
2177 *args,
2178 token[MaxTextExtent];
2179
2180 const char
2181 *p;
2182
2183 DistortImageMethod
2184 method;
2185
2186 double
2187 *arguments;
2188
2189 register ssize_t
2190 x;
2191
2192 size_t
2193 number_arguments;
2194
anthony805a2d42011-09-25 08:25:12 +00002195 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
anthonyfd706f92012-01-19 04:22:02 +00002196 MagickFalse,arg1);
anthony80c37752012-01-16 01:03:11 +00002197 if (method == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002198 {
anthony80c37752012-01-16 01:03:11 +00002199 double
2200 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002201 /* Special Case - Argument is actually a resize geometry!
2202 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002203 ** FUTURE: make a separate special resize operator
anthony805a2d42011-09-25 08:25:12 +00002204 */
anthony92c93bd2012-03-19 14:02:47 +00002205 (void) ParseRegionGeometry(_image,arg2,&geometry,
2206 _exception);
anthony80c37752012-01-16 01:03:11 +00002207 resize_args[0]=(double) geometry.width;
2208 resize_args[1]=(double) geometry.height;
anthony92c93bd2012-03-19 14:02:47 +00002209 new_image=DistortImage(_image,method,(size_t)2,
2210 resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002211 break;
2212 }
anthonyfd706f92012-01-19 04:22:02 +00002213 /* handle percent arguments */
anthony92c93bd2012-03-19 14:02:47 +00002214 args=InterpretImageProperties(_image_info,_image,arg2,
2215 _exception);
anthony805a2d42011-09-25 08:25:12 +00002216 if (args == (char *) NULL)
2217 break;
anthonyfd706f92012-01-19 04:22:02 +00002218 /* convert arguments into an array of doubles
2219 FUTURE: make this a separate function.
2220 Also make use of new 'sentinal' feature to avoid need for
2221 tokenization.
2222 */
anthony805a2d42011-09-25 08:25:12 +00002223 p=(char *) args;
2224 for (x=0; *p != '\0'; x++)
2225 {
2226 GetMagickToken(p,&p,token);
2227 if (*token == ',')
2228 GetMagickToken(p,&p,token);
2229 }
2230 number_arguments=(size_t) x;
2231 arguments=(double *) AcquireQuantumMemory(number_arguments,
2232 sizeof(*arguments));
2233 if (arguments == (double *) NULL)
2234 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002235 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002236 (void) ResetMagickMemory(arguments,0,number_arguments*
2237 sizeof(*arguments));
2238 p=(char *) args;
2239 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2240 {
2241 GetMagickToken(p,&p,token);
2242 if (*token == ',')
2243 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002244 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002245 }
2246 args=DestroyString(args);
anthony92c93bd2012-03-19 14:02:47 +00002247 new_image=DistortImage(_image,method,number_arguments,arguments,
2248 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002249 arguments=(double *) RelinquishMagickMemory(arguments);
2250 break;
2251 }
anthonyafa3dfc2012-03-03 11:31:30 +00002252 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002253 {
anthony92c93bd2012-03-19 14:02:47 +00002254 (void) CloneString(&_draw_info->primitive,arg1);
2255 (void) DrawImage(_image,_draw_info,_exception);
2256 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002257 break;
2258 }
2259 break;
2260 }
2261 case 'e':
2262 {
anthonyafa3dfc2012-03-03 11:31:30 +00002263 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002264 {
anthonyfd706f92012-01-19 04:22:02 +00002265 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002266 if ((flags & SigmaValue) == 0)
2267 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002268 new_image=EdgeImage(_image,geometry_info.rho,
2269 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002270 break;
2271 }
anthonyafa3dfc2012-03-03 11:31:30 +00002272 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002273 {
anthonyfd706f92012-01-19 04:22:02 +00002274 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002275 if ((flags & SigmaValue) == 0)
2276 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002277 new_image=EmbossImage(_image,geometry_info.rho,
2278 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002279 break;
2280 }
anthonyafa3dfc2012-03-03 11:31:30 +00002281 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002282 {
2283 StringInfo
2284 *passkey;
2285
anthony92c93bd2012-03-19 14:02:47 +00002286 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002287 if (passkey != (StringInfo *) NULL)
2288 {
anthony92c93bd2012-03-19 14:02:47 +00002289 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002290 passkey=DestroyStringInfo(passkey);
2291 }
2292 break;
2293 }
anthonyafa3dfc2012-03-03 11:31:30 +00002294 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002295 {
anthony92c93bd2012-03-19 14:02:47 +00002296 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002297 break;
2298 }
anthonyafa3dfc2012-03-03 11:31:30 +00002299 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002300 {
anthony92c93bd2012-03-19 14:02:47 +00002301 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002302 break;
2303 }
anthonyafa3dfc2012-03-03 11:31:30 +00002304 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002305 {
2306 double
2307 constant;
2308
2309 MagickEvaluateOperator
2310 op;
2311
anthony805a2d42011-09-25 08:25:12 +00002312 op=(MagickEvaluateOperator) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00002313 MagickEvaluateOptions,MagickFalse,arg1);
2314 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00002315 (void) EvaluateImage(_image,op,constant,_exception);
anthony805a2d42011-09-25 08:25:12 +00002316 break;
2317 }
anthonyafa3dfc2012-03-03 11:31:30 +00002318 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002319 {
anthony92c93bd2012-03-19 14:02:47 +00002320 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002321 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002322 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002323 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002324 geometry.height=_image->rows;
2325 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002326 break;
2327 }
2328 break;
2329 }
2330 case 'f':
2331 {
anthonyafa3dfc2012-03-03 11:31:30 +00002332 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002333 {
anthony31f1bf72012-01-30 12:37:22 +00002334 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002335 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002336 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002337 break;
2338 }
anthony92c93bd2012-03-19 14:02:47 +00002339 (void) SetImageArtifact(_image,"identify:features","true");
2340 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002341 break;
2342 }
anthonyafa3dfc2012-03-03 11:31:30 +00002343 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002344 {
anthony92c93bd2012-03-19 14:02:47 +00002345 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002346 break;
2347 }
anthonyafa3dfc2012-03-03 11:31:30 +00002348 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002349 {
anthony92c93bd2012-03-19 14:02:47 +00002350 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002351 break;
2352 }
anthonyafa3dfc2012-03-03 11:31:30 +00002353 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002354 {
2355 PixelInfo
2356 target;
2357
anthony92c93bd2012-03-19 14:02:47 +00002358 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2359 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2360 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2361 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002362 break;
2363 }
anthonyafa3dfc2012-03-03 11:31:30 +00002364 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002365 {
2366 FrameInfo
2367 frame_info;
2368
anthony31f1bf72012-01-30 12:37:22 +00002369 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002370 compose;
2371
2372 const char*
2373 value;
2374
anthony92c93bd2012-03-19 14:02:47 +00002375 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002376 if (value != (const char *) NULL)
2377 compose=(CompositeOperator) ParseCommandOption(
2378 MagickComposeOptions,MagickFalse,value);
2379 else
anthony92c93bd2012-03-19 14:02:47 +00002380 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002381
anthony92c93bd2012-03-19 14:02:47 +00002382 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002383 frame_info.width=geometry.width;
2384 frame_info.height=geometry.height;
2385 if ((flags & HeightValue) == 0)
2386 frame_info.height=geometry.width;
2387 frame_info.outer_bevel=geometry.x;
2388 frame_info.inner_bevel=geometry.y;
2389 frame_info.x=(ssize_t) frame_info.width;
2390 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002391 frame_info.width=_image->columns+2*frame_info.width;
2392 frame_info.height=_image->rows+2*frame_info.height;
2393 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002394 break;
2395 }
anthonyafa3dfc2012-03-03 11:31:30 +00002396 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002397 {
2398 char
2399 *arguments,
2400 token[MaxTextExtent];
2401
2402 const char
2403 *p;
2404
2405 double
2406 *parameters;
2407
2408 MagickFunction
2409 function;
2410
2411 register ssize_t
2412 x;
2413
2414 size_t
2415 number_parameters;
2416
cristy947cb4c2011-10-20 18:41:46 +00002417 /*
2418 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002419 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002420 */
anthony805a2d42011-09-25 08:25:12 +00002421 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
anthonyfd706f92012-01-19 04:22:02 +00002422 MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002423 arguments=InterpretImageProperties(_image_info,_image,arg2,
2424 _exception);
anthony805a2d42011-09-25 08:25:12 +00002425 if (arguments == (char *) NULL)
2426 break;
2427 p=(char *) arguments;
2428 for (x=0; *p != '\0'; x++)
2429 {
2430 GetMagickToken(p,&p,token);
2431 if (*token == ',')
2432 GetMagickToken(p,&p,token);
2433 }
2434 number_parameters=(size_t) x;
2435 parameters=(double *) AcquireQuantumMemory(number_parameters,
2436 sizeof(*parameters));
2437 if (parameters == (double *) NULL)
2438 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002439 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002440 (void) ResetMagickMemory(parameters,0,number_parameters*
2441 sizeof(*parameters));
2442 p=(char *) arguments;
2443 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2444 {
2445 GetMagickToken(p,&p,token);
2446 if (*token == ',')
2447 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002448 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002449 }
2450 arguments=DestroyString(arguments);
anthony92c93bd2012-03-19 14:02:47 +00002451 (void) FunctionImage(_image,function,number_parameters,parameters,
2452 _exception);
anthony805a2d42011-09-25 08:25:12 +00002453 parameters=(double *) RelinquishMagickMemory(parameters);
2454 break;
2455 }
2456 break;
2457 }
2458 case 'g':
2459 {
anthonyafa3dfc2012-03-03 11:31:30 +00002460 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002461 {
anthonyafa3dfc2012-03-03 11:31:30 +00002462 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002463 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2464 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002465 else
anthony92c93bd2012-03-19 14:02:47 +00002466 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002467 break;
2468 }
anthonyafa3dfc2012-03-03 11:31:30 +00002469 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2470 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002471 {
anthonyfd706f92012-01-19 04:22:02 +00002472 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002473 if ((flags & SigmaValue) == 0)
2474 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002475 new_image=GaussianBlurImage(_image,geometry_info.rho,
2476 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002477 break;
2478 }
anthonyafa3dfc2012-03-03 11:31:30 +00002479 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002480 {
anthonyfd706f92012-01-19 04:22:02 +00002481 /*
anthony31f1bf72012-01-30 12:37:22 +00002482 Record Image offset for composition. (A Setting)
anthony92c93bd2012-03-19 14:02:47 +00002483 Resize last _image. (ListOperator)
anthony31f1bf72012-01-30 12:37:22 +00002484 FUTURE: Why if no 'offset' does this resize ALL images?
2485 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002486 */
anthonyafa3dfc2012-03-03 11:31:30 +00002487 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002488 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002489 if (_image->geometry != (char *) NULL)
2490 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002491 break;
2492 }
anthony92c93bd2012-03-19 14:02:47 +00002493 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002494 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002495 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002496 else
anthony92c93bd2012-03-19 14:02:47 +00002497 new_image=ResizeImage(_image,geometry.width,geometry.height,
2498 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00002499 break;
2500 }
anthony805a2d42011-09-25 08:25:12 +00002501 break;
2502 }
2503 case 'h':
2504 {
anthonyafa3dfc2012-03-03 11:31:30 +00002505 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002506 {
anthony92c93bd2012-03-19 14:02:47 +00002507 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002508 break;
2509 }
2510 break;
2511 }
2512 case 'i':
2513 {
anthonyafa3dfc2012-03-03 11:31:30 +00002514 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002515 {
anthony31f1bf72012-01-30 12:37:22 +00002516 const char
2517 *format,
anthony805a2d42011-09-25 08:25:12 +00002518 *text;
2519
anthony92c93bd2012-03-19 14:02:47 +00002520 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002521 if (format == (char *) NULL)
2522 {
anthony92c93bd2012-03-19 14:02:47 +00002523 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2524 _exception);
anthony805a2d42011-09-25 08:25:12 +00002525 break;
2526 }
anthony92c93bd2012-03-19 14:02:47 +00002527 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002528 if (text == (char *) NULL)
2529 break;
2530 (void) fputs(text,stdout);
2531 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002532 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002533 break;
2534 }
anthonyafa3dfc2012-03-03 11:31:30 +00002535 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002536 {
anthonyfd706f92012-01-19 04:22:02 +00002537 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002538 new_image=ImplodeImage(_image,geometry_info.rho,
2539 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002540 break;
2541 }
anthonyafa3dfc2012-03-03 11:31:30 +00002542 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002543 {
anthony92c93bd2012-03-19 14:02:47 +00002544 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2545 new_image=InterpolativeResizeImage(_image,geometry.width,
2546 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002547 break;
2548 }
anthony805a2d42011-09-25 08:25:12 +00002549 break;
2550 }
2551 case 'l':
2552 {
anthonyafa3dfc2012-03-03 11:31:30 +00002553 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002554 {
anthonyfd706f92012-01-19 04:22:02 +00002555 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002556 if ((flags & PercentValue) != 0)
2557 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002558 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002559 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002560 _exception);
anthony805a2d42011-09-25 08:25:12 +00002561 break;
2562 }
anthonyafa3dfc2012-03-03 11:31:30 +00002563 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002564 {
2565 MagickRealType
2566 black_point,
2567 gamma,
2568 white_point;
2569
2570 MagickStatusType
2571 flags;
2572
anthonyfd706f92012-01-19 04:22:02 +00002573 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002574 black_point=geometry_info.rho;
2575 white_point=(MagickRealType) QuantumRange;
2576 if ((flags & SigmaValue) != 0)
2577 white_point=geometry_info.sigma;
2578 gamma=1.0;
2579 if ((flags & XiValue) != 0)
2580 gamma=geometry_info.xi;
2581 if ((flags & PercentValue) != 0)
2582 {
2583 black_point*=(MagickRealType) (QuantumRange/100.0);
2584 white_point*=(MagickRealType) (QuantumRange/100.0);
2585 }
2586 if ((flags & SigmaValue) == 0)
2587 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002588 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002589 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002590 else
anthony92c93bd2012-03-19 14:02:47 +00002591 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002592 break;
2593 }
anthonyafa3dfc2012-03-03 11:31:30 +00002594 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002595 {
2596 char
2597 token[MaxTextExtent];
2598
2599 const char
2600 *p;
2601
2602 PixelInfo
2603 black_point,
2604 white_point;
2605
anthonyfd706f92012-01-19 04:22:02 +00002606 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002607 GetMagickToken(p,&p,token); /* get black point color */
2608 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002609 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002610 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002611 else
cristy269c9412011-10-13 23:41:15 +00002612 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002613 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002614 if (isalpha((int) token[0]) || (token[0] == '#'))
2615 GetMagickToken(p,&p,token);
2616 if (*token == '\0')
2617 white_point=black_point; /* set everything to that color */
2618 else
2619 {
2620 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2621 GetMagickToken(p,&p,token); /* Get white point color. */
2622 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002623 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002624 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002625 else
cristy269c9412011-10-13 23:41:15 +00002626 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002627 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002628 }
anthony92c93bd2012-03-19 14:02:47 +00002629 (void) LevelImageColors(_image,&black_point,&white_point,
2630 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002631 break;
2632 }
anthonyafa3dfc2012-03-03 11:31:30 +00002633 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002634 {
2635 double
2636 black_point,
2637 white_point;
2638
2639 MagickStatusType
2640 flags;
2641
anthonyfd706f92012-01-19 04:22:02 +00002642 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002643 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002644 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002645 if ((flags & SigmaValue) != 0)
2646 white_point=geometry_info.sigma;
2647 if ((flags & PercentValue) != 0)
2648 {
anthony92c93bd2012-03-19 14:02:47 +00002649 black_point*=(double) _image->columns*_image->rows/100.0;
2650 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002651 }
2652 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002653 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002654 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002655 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002656 break;
2657 }
anthonyafa3dfc2012-03-03 11:31:30 +00002658 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002659 {
anthony92c93bd2012-03-19 14:02:47 +00002660 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002661 if ((flags & XValue) == 0)
2662 geometry.x=1;
2663 if ((flags & YValue) == 0)
2664 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002665 new_image=LiquidRescaleImage(_image,geometry.width,
2666 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002667 break;
2668 }
anthonyafa3dfc2012-03-03 11:31:30 +00002669 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002670 {
anthony92c93bd2012-03-19 14:02:47 +00002671 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002672 break;
2673 }
2674 break;
2675 }
2676 case 'm':
2677 {
anthonyafa3dfc2012-03-03 11:31:30 +00002678 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002679 {
2680 Image
2681 *remap_image;
2682
anthony31f1bf72012-01-30 12:37:22 +00002683 /* DEPRECIATED use -remap */
anthony92c93bd2012-03-19 14:02:47 +00002684 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002685 if (remap_image == (Image *) NULL)
2686 break;
anthony92c93bd2012-03-19 14:02:47 +00002687 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002688 remap_image=DestroyImage(remap_image);
2689 break;
2690 }
anthonyafa3dfc2012-03-03 11:31:30 +00002691 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002692 {
2693 Image
2694 *mask;
2695
anthonyafa3dfc2012-03-03 11:31:30 +00002696 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002697 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002698 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002699 break;
2700 }
anthony5330ae02012-03-20 14:17:01 +00002701 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002702 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002703 if (mask == (Image *) NULL)
2704 break;
anthony92c93bd2012-03-19 14:02:47 +00002705 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002706 mask=DestroyImage(mask);
2707 break;
2708 }
anthonyafa3dfc2012-03-03 11:31:30 +00002709 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002710 {
anthony31f1bf72012-01-30 12:37:22 +00002711 /* DEPRECIATED */
anthony92c93bd2012-03-19 14:02:47 +00002712 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2713 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002714 break;
2715 }
anthonya3ef4ed2012-03-17 06:52:53 +00002716 if (LocaleCompare("median",option+1) == 0)
2717 {
2718 /* DEPRECIATED - use -statistic Median */
2719 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2720 break;
2721 }
anthonyafa3dfc2012-03-03 11:31:30 +00002722 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002723 {
anthonyfd706f92012-01-19 04:22:02 +00002724 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002725 if ((flags & SigmaValue) == 0)
2726 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002727 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2728 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002729 break;
2730 }
anthonyafa3dfc2012-03-03 11:31:30 +00002731 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002732 {
anthony92c93bd2012-03-19 14:02:47 +00002733 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002734 break;
2735 }
anthonyafa3dfc2012-03-03 11:31:30 +00002736 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002737 {
anthony92c93bd2012-03-19 14:02:47 +00002738 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002739 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002740 break;
2741 }
anthonyafa3dfc2012-03-03 11:31:30 +00002742 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002743 {
anthony92c93bd2012-03-19 14:02:47 +00002744 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002745 break;
2746 }
anthonyafa3dfc2012-03-03 11:31:30 +00002747 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002748 {
2749 char
2750 token[MaxTextExtent];
2751
2752 const char
2753 *p;
2754
2755 KernelInfo
2756 *kernel;
2757
2758 MorphologyMethod
2759 method;
2760
2761 ssize_t
2762 iterations;
2763
anthonyfd706f92012-01-19 04:22:02 +00002764 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002765 GetMagickToken(p,&p,token);
2766 method=(MorphologyMethod) ParseCommandOption(
2767 MagickMorphologyOptions,MagickFalse,token);
2768 iterations=1L;
2769 GetMagickToken(p,&p,token);
2770 if ((*p == ':') || (*p == ','))
2771 GetMagickToken(p,&p,token);
2772 if ((*p != '\0'))
2773 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002774 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002775 if (kernel == (KernelInfo *) NULL)
2776 {
anthony92c93bd2012-03-19 14:02:47 +00002777 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00002778 OptionError,"UnabletoParseKernel","morphology");
anthony805a2d42011-09-25 08:25:12 +00002779 break;
2780 }
anthony92c93bd2012-03-19 14:02:47 +00002781 new_image=MorphologyImage(_image,method,iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002782 kernel=DestroyKernelInfo(kernel);
2783 break;
2784 }
anthonyafa3dfc2012-03-03 11:31:30 +00002785 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002786 {
anthonyfd706f92012-01-19 04:22:02 +00002787 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002788 if ((flags & SigmaValue) == 0)
2789 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002790 new_image=MotionBlurImage(_image,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002791 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
anthony92c93bd2012-03-19 14:02:47 +00002792 _exception);
anthony805a2d42011-09-25 08:25:12 +00002793 break;
2794 }
2795 break;
2796 }
2797 case 'n':
2798 {
anthonyafa3dfc2012-03-03 11:31:30 +00002799 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002800 {
anthony92c93bd2012-03-19 14:02:47 +00002801 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002802 break;
2803 }
anthonyafa3dfc2012-03-03 11:31:30 +00002804 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002805 {
anthonyafa3dfc2012-03-03 11:31:30 +00002806 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002807 {
anthonyfd706f92012-01-19 04:22:02 +00002808 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002809 if ((flags & SigmaValue) == 0)
2810 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002811 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2812 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002813 }
2814 else
2815 {
2816 NoiseType
2817 noise;
2818
anthony31f1bf72012-01-30 12:37:22 +00002819 double
2820 attenuate;
2821
2822 const char*
2823 value;
2824
anthony805a2d42011-09-25 08:25:12 +00002825 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
anthony31f1bf72012-01-30 12:37:22 +00002826 MagickFalse,arg1),
2827
anthony92c93bd2012-03-19 14:02:47 +00002828 value=GetImageOption(_image_info,"attenuate");
anthony31f1bf72012-01-30 12:37:22 +00002829 if (value != (const char *) NULL)
2830 attenuate=StringToDouble(value,(char **) NULL);
2831 else
2832 attenuate=1.0;
2833
anthony92c93bd2012-03-19 14:02:47 +00002834 new_image=AddNoiseImage(_image,noise,attenuate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002835 }
2836 break;
2837 }
anthonyafa3dfc2012-03-03 11:31:30 +00002838 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002839 {
anthony92c93bd2012-03-19 14:02:47 +00002840 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002841 break;
2842 }
2843 break;
2844 }
2845 case 'o':
2846 {
anthonyafa3dfc2012-03-03 11:31:30 +00002847 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002848 {
2849 PixelInfo
2850 target;
2851
anthony92c93bd2012-03-19 14:02:47 +00002852 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2853 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2854 _exception);
anthony805a2d42011-09-25 08:25:12 +00002855 break;
2856 }
anthonyafa3dfc2012-03-03 11:31:30 +00002857 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002858 {
anthony92c93bd2012-03-19 14:02:47 +00002859 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002860 break;
2861 }
2862 break;
2863 }
2864 case 'p':
2865 {
anthonyafa3dfc2012-03-03 11:31:30 +00002866 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002867 {
anthonyfd706f92012-01-19 04:22:02 +00002868 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002869 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2870 _exception);
anthony805a2d42011-09-25 08:25:12 +00002871 break;
2872 }
anthonyafa3dfc2012-03-03 11:31:30 +00002873 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002874 {
cristye9e3d382011-12-14 01:50:13 +00002875 const char
2876 *caption;
2877
anthony805a2d42011-09-25 08:25:12 +00002878 double
2879 angle;
2880
anthonyafa3dfc2012-03-03 11:31:30 +00002881 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002882 {
2883 RandomInfo
2884 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002885
anthony31f1bf72012-01-30 12:37:22 +00002886 random_info=AcquireRandomInfo();
2887 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2888 random_info=DestroyRandomInfo(random_info);
2889 }
2890 else
anthony805a2d42011-09-25 08:25:12 +00002891 {
2892 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00002893 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002894 angle=geometry_info.rho;
2895 }
anthony92c93bd2012-03-19 14:02:47 +00002896 caption=GetImageProperty(_image,"caption",_exception);
2897 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2898 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002899 break;
2900 }
anthonyafa3dfc2012-03-03 11:31:30 +00002901 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002902 {
anthony31f1bf72012-01-30 12:37:22 +00002903 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002904 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
2905 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00002906 break;
2907 }
anthonyafa3dfc2012-03-03 11:31:30 +00002908 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002909 {
2910 PreviewType
cristy947cb4c2011-10-20 18:41:46 +00002911 preview_type;
anthony170fce92011-10-20 11:50:23 +00002912
anthony31f1bf72012-01-30 12:37:22 +00002913 /* FUTURE: should be a 'Genesis' option?
2914 Option however is also in WandSettingOptionInfo()
cristy947cb4c2011-10-20 18:41:46 +00002915 */
anthony31f1bf72012-01-30 12:37:22 +00002916 preview_type=UndefinedPreview;
anthonyafa3dfc2012-03-03 11:31:30 +00002917 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00002918 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2919 MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002920 new_image=PreviewImage(_image,preview_type,_exception);
anthony805a2d42011-09-25 08:25:12 +00002921 break;
2922 }
anthonyafa3dfc2012-03-03 11:31:30 +00002923 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002924 {
2925 const char
2926 *name;
2927
2928 const StringInfo
2929 *profile;
2930
2931 Image
2932 *profile_image;
2933
2934 ImageInfo
2935 *profile_info;
2936
anthonyafa3dfc2012-03-03 11:31:30 +00002937 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00002938 { /* Remove a profile from the _image. */
2939 (void) ProfileImage(_image,arg1,(const unsigned char *)
2940 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002941 break;
2942 }
anthony92c93bd2012-03-19 14:02:47 +00002943 /* Associate a profile with the _image. */
2944 profile_info=CloneImageInfo(_image_info);
2945 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002946 if (profile != (StringInfo *) NULL)
2947 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00002948 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002949 profile_info=DestroyImageInfo(profile_info);
2950 if (profile_image == (Image *) NULL)
2951 {
2952 StringInfo
2953 *profile;
2954
anthony92c93bd2012-03-19 14:02:47 +00002955 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00002956 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002957 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00002958 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002959 if (profile != (StringInfo *) NULL)
2960 {
anthony92c93bd2012-03-19 14:02:47 +00002961 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002962 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00002963 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002964 profile=DestroyStringInfo(profile);
2965 }
2966 profile_info=DestroyImageInfo(profile_info);
2967 break;
2968 }
2969 ResetImageProfileIterator(profile_image);
2970 name=GetNextImageProfile(profile_image);
2971 while (name != (const char *) NULL)
2972 {
2973 profile=GetImageProfile(profile_image,name);
2974 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00002975 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2976 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002977 name=GetNextImageProfile(profile_image);
2978 }
2979 profile_image=DestroyImage(profile_image);
2980 break;
2981 }
2982 break;
2983 }
anthony805a2d42011-09-25 08:25:12 +00002984 case 'r':
2985 {
anthonyafa3dfc2012-03-03 11:31:30 +00002986 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002987 {
anthonyfd706f92012-01-19 04:22:02 +00002988 flags=ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002989 new_image=RadialBlurImage(_image,geometry_info.rho,
2990 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002991 break;
2992 }
anthonyafa3dfc2012-03-03 11:31:30 +00002993 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002994 {
anthony92c93bd2012-03-19 14:02:47 +00002995 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002996 if ((flags & SigmaValue) == 0)
2997 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00002998 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002999 break;
3000 }
anthonyafa3dfc2012-03-03 11:31:30 +00003001 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003002 {
anthony92c93bd2012-03-19 14:02:47 +00003003 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003004 break;
3005 }
anthonyafa3dfc2012-03-03 11:31:30 +00003006 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003007 {
3008 Image
3009 *remap_image;
3010
anthony92c93bd2012-03-19 14:02:47 +00003011 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003012 if (remap_image == (Image *) NULL)
3013 break;
anthony92c93bd2012-03-19 14:02:47 +00003014 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003015 remap_image=DestroyImage(remap_image);
3016 break;
3017 }
anthonyafa3dfc2012-03-03 11:31:30 +00003018 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003019 {
anthonyafa3dfc2012-03-03 11:31:30 +00003020 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003021 (void) ResetImagePage(_image,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003022 else
anthony92c93bd2012-03-19 14:02:47 +00003023 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003024 break;
3025 }
anthonyafa3dfc2012-03-03 11:31:30 +00003026 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003027 {
anthony31f1bf72012-01-30 12:37:22 +00003028 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00003029 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003030 if ((flags & SigmaValue) == 0)
3031 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003032 new_image=ResampleImage(_image,geometry_info.rho,
3033 geometry_info.sigma,_image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003034 break;
3035 }
anthonyafa3dfc2012-03-03 11:31:30 +00003036 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003037 {
anthonyafbaed72011-10-26 12:05:04 +00003038 /* FUTURE: remove blur argument - no longer used */
anthony92c93bd2012-03-19 14:02:47 +00003039 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3040 new_image=ResizeImage(_image,geometry.width,geometry.height,
3041 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003042 break;
3043 }
anthonyafa3dfc2012-03-03 11:31:30 +00003044 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003045 {
anthony92c93bd2012-03-19 14:02:47 +00003046 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3047 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003048 break;
3049 }
anthonyafa3dfc2012-03-03 11:31:30 +00003050 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003051 {
anthonyfd706f92012-01-19 04:22:02 +00003052 if (strchr(arg1,'>') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003053 if (_image->columns <= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003054 break;
anthonyfd706f92012-01-19 04:22:02 +00003055 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003056 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003057 break;
anthonyafbaed72011-10-26 12:05:04 +00003058
anthonyfd706f92012-01-19 04:22:02 +00003059 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003060 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003061 break;
3062 }
3063 break;
3064 }
3065 case 's':
3066 {
anthonyafa3dfc2012-03-03 11:31:30 +00003067 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003068 {
anthony92c93bd2012-03-19 14:02:47 +00003069 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3070 new_image=SampleImage(_image,geometry.width,geometry.height,
3071 _exception);
anthony805a2d42011-09-25 08:25:12 +00003072 break;
3073 }
anthonyafa3dfc2012-03-03 11:31:30 +00003074 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003075 {
anthony92c93bd2012-03-19 14:02:47 +00003076 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3077 new_image=ScaleImage(_image,geometry.width,geometry.height,
3078 _exception);
anthony805a2d42011-09-25 08:25:12 +00003079 break;
3080 }
anthonyafa3dfc2012-03-03 11:31:30 +00003081 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003082 {
anthonyfd706f92012-01-19 04:22:02 +00003083 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003084 if ((flags & PercentValue) != 0)
3085 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003086 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3087 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003088 break;
3089 }
anthonyafa3dfc2012-03-03 11:31:30 +00003090 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003091 {
anthony31f1bf72012-01-30 12:37:22 +00003092 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003093 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003094 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003095 break;
3096 }
anthonyafa3dfc2012-03-03 11:31:30 +00003097 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003098 {
3099 double
3100 threshold;
3101
anthonyfd706f92012-01-19 04:22:02 +00003102 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003103 new_image=SepiaToneImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003104 break;
3105 }
anthonyafa3dfc2012-03-03 11:31:30 +00003106 if (LocaleCompare("segment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003107 {
anthonyfd706f92012-01-19 04:22:02 +00003108 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003109 if ((flags & SigmaValue) == 0)
3110 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003111 (void) SegmentImage(_image,_image->colorspace,
3112 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3113 _exception);
anthony805a2d42011-09-25 08:25:12 +00003114 break;
3115 }
anthonyafa3dfc2012-03-03 11:31:30 +00003116 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003117 {
3118 char
3119 *value;
3120
anthonyafa3dfc2012-03-03 11:31:30 +00003121 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00003122 {
anthonyfd706f92012-01-19 04:22:02 +00003123 if (LocaleNCompare(arg1,"registry:",9) == 0)
3124 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003125 else
anthony31f1bf72012-01-30 12:37:22 +00003126 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003127 {
anthony92c93bd2012-03-19 14:02:47 +00003128 (void) DeleteImageOption(_image_info,arg1+7);
3129 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003130 }
3131 else
anthony92c93bd2012-03-19 14:02:47 +00003132 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003133 break;
3134 }
anthony92c93bd2012-03-19 14:02:47 +00003135 value=InterpretImageProperties(_image_info,_image,arg2,
3136 _exception);
anthony805a2d42011-09-25 08:25:12 +00003137 if (value == (char *) NULL)
3138 break;
anthonyfd706f92012-01-19 04:22:02 +00003139 if (LocaleNCompare(arg1,"registry:",9) == 0)
3140 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony92c93bd2012-03-19 14:02:47 +00003141 _exception);
anthony805a2d42011-09-25 08:25:12 +00003142 else
anthonyfd706f92012-01-19 04:22:02 +00003143 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003144 {
anthony92c93bd2012-03-19 14:02:47 +00003145 (void) SetImageOption(_image_info,arg1+7,value);
3146 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003147 }
3148 else
anthony92c93bd2012-03-19 14:02:47 +00003149 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003150 value=DestroyString(value);
3151 break;
3152 }
anthonyafa3dfc2012-03-03 11:31:30 +00003153 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003154 {
anthonyfd706f92012-01-19 04:22:02 +00003155 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003156 if ((flags & SigmaValue) == 0)
3157 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003158 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3159 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003160 break;
3161 }
anthonyafa3dfc2012-03-03 11:31:30 +00003162 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003163 {
anthonyfd706f92012-01-19 04:22:02 +00003164 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003165 if ((flags & SigmaValue) == 0)
3166 geometry_info.sigma=1.0;
3167 if ((flags & XiValue) == 0)
3168 geometry_info.xi=4.0;
3169 if ((flags & PsiValue) == 0)
3170 geometry_info.psi=4.0;
anthony92c93bd2012-03-19 14:02:47 +00003171 new_image=ShadowImage(_image,geometry_info.rho,
3172 geometry_info.sigma,_image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003173 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
anthony92c93bd2012-03-19 14:02:47 +00003174 _exception);
anthony805a2d42011-09-25 08:25:12 +00003175 break;
3176 }
anthonyafa3dfc2012-03-03 11:31:30 +00003177 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003178 {
anthonyfd706f92012-01-19 04:22:02 +00003179 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003180 if ((flags & SigmaValue) == 0)
3181 geometry_info.sigma=1.0;
3182 if ((flags & XiValue) == 0)
3183 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00003184 new_image=SharpenImage(_image,geometry_info.rho,
3185 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003186 break;
3187 }
anthonyafa3dfc2012-03-03 11:31:30 +00003188 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003189 {
anthony92c93bd2012-03-19 14:02:47 +00003190 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3191 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003192 break;
3193 }
anthonyafa3dfc2012-03-03 11:31:30 +00003194 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003195 {
anthonyfd706f92012-01-19 04:22:02 +00003196 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003197 if ((flags & SigmaValue) == 0)
3198 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003199 new_image=ShearImage(_image,geometry_info.rho,
3200 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003201 break;
3202 }
anthonyafa3dfc2012-03-03 11:31:30 +00003203 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003204 {
anthonyfd706f92012-01-19 04:22:02 +00003205 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003206 if ((flags & SigmaValue) == 0)
3207 geometry_info.sigma=(double) QuantumRange/2.0;
3208 if ((flags & PercentValue) != 0)
3209 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3210 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003211 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003212 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003213 _exception);
anthony805a2d42011-09-25 08:25:12 +00003214 break;
3215 }
anthonyafa3dfc2012-03-03 11:31:30 +00003216 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003217 {
anthonyfd706f92012-01-19 04:22:02 +00003218 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003219 if ((flags & SigmaValue) == 0)
3220 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003221 new_image=SketchImage(_image,geometry_info.rho,
3222 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003223 break;
3224 }
anthonyafa3dfc2012-03-03 11:31:30 +00003225 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003226 {
anthony92c93bd2012-03-19 14:02:47 +00003227 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3228 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003229 break;
3230 }
anthonyafa3dfc2012-03-03 11:31:30 +00003231 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003232 {
3233 SparseColorMethod
3234 method;
3235
3236 char
3237 *arguments;
3238
anthony805a2d42011-09-25 08:25:12 +00003239 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003240 MagickSparseColorOptions,MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003241 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003242 if (arguments == (char *) NULL)
3243 break;
anthony92c93bd2012-03-19 14:02:47 +00003244 new_image=SparseColorOption(_image,method,arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003245 arguments=DestroyString(arguments);
3246 break;
3247 }
anthonyafa3dfc2012-03-03 11:31:30 +00003248 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003249 {
anthony92c93bd2012-03-19 14:02:47 +00003250 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3251 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003252 break;
3253 }
anthonyafa3dfc2012-03-03 11:31:30 +00003254 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003255 {
anthonyfd706f92012-01-19 04:22:02 +00003256 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003257 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3258 _exception);
anthony805a2d42011-09-25 08:25:12 +00003259 break;
3260 }
anthonyafa3dfc2012-03-03 11:31:30 +00003261 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003262 {
3263 StatisticType
3264 type;
3265
anthony805a2d42011-09-25 08:25:12 +00003266 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
anthonyfd706f92012-01-19 04:22:02 +00003267 MagickFalse,arg1);
3268 (void) ParseGeometry(arg2,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003269 new_image=StatisticImage(_image,type,(size_t) geometry_info.rho,
3270 (size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003271 break;
3272 }
anthonyafa3dfc2012-03-03 11:31:30 +00003273 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003274 {
anthony92c93bd2012-03-19 14:02:47 +00003275 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003276 break;
3277 }
anthonyafa3dfc2012-03-03 11:31:30 +00003278 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003279 {
anthonyfd706f92012-01-19 04:22:02 +00003280 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003281 new_image=SwirlImage(_image,geometry_info.rho,
3282 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003283 break;
3284 }
3285 break;
3286 }
3287 case 't':
3288 {
anthonyafa3dfc2012-03-03 11:31:30 +00003289 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003290 {
3291 double
3292 threshold;
3293
anthonyafa3dfc2012-03-03 11:31:30 +00003294 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003295 threshold=(double) QuantumRange/2;
3296 else
anthonyfd706f92012-01-19 04:22:02 +00003297 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003298 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003299 break;
3300 }
anthonyafa3dfc2012-03-03 11:31:30 +00003301 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003302 {
anthony92c93bd2012-03-19 14:02:47 +00003303 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3304 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3305 _exception);
anthony805a2d42011-09-25 08:25:12 +00003306 break;
3307 }
anthonyafa3dfc2012-03-03 11:31:30 +00003308 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003309 {
anthony92c93bd2012-03-19 14:02:47 +00003310 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003311 break;
3312 }
anthonyafa3dfc2012-03-03 11:31:30 +00003313 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003314 {
anthonya3ef4ed2012-03-17 06:52:53 +00003315 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony92c93bd2012-03-19 14:02:47 +00003316 new_image=AffineTransformImage(_image,&_draw_info->affine,
3317 _exception);
anthony805a2d42011-09-25 08:25:12 +00003318 break;
3319 }
anthonyafa3dfc2012-03-03 11:31:30 +00003320 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003321 {
3322 PixelInfo
3323 target;
3324
anthony92c93bd2012-03-19 14:02:47 +00003325 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3326 (void) TransparentPaintImage(_image,&target,(Quantum)
3327 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003328 break;
3329 }
anthonyafa3dfc2012-03-03 11:31:30 +00003330 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003331 {
anthony92c93bd2012-03-19 14:02:47 +00003332 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003333 break;
3334 }
anthonyafa3dfc2012-03-03 11:31:30 +00003335 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003336 {
anthony92c93bd2012-03-19 14:02:47 +00003337 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003338 break;
3339 }
anthonyafa3dfc2012-03-03 11:31:30 +00003340 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003341 {
anthony92c93bd2012-03-19 14:02:47 +00003342 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003343 break;
3344 }
anthonyafa3dfc2012-03-03 11:31:30 +00003345 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003346 {
anthonyab3a50c2011-10-27 11:48:57 +00003347 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003348 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003349 break;
3350 }
3351 break;
3352 }
3353 case 'u':
3354 {
anthonyafa3dfc2012-03-03 11:31:30 +00003355 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003356 {
anthony31f1bf72012-01-30 12:37:22 +00003357 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthony24aa8822012-03-11 00:56:06 +00003358 /* FUTURE: This option is not documented!!!!! */
anthonyafa3dfc2012-03-03 11:31:30 +00003359 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003360 {
anthony92c93bd2012-03-19 14:02:47 +00003361 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003362 break;
3363 }
anthony92c93bd2012-03-19 14:02:47 +00003364 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3365 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003366 break;
3367 }
anthonyafa3dfc2012-03-03 11:31:30 +00003368 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003369 {
anthony92c93bd2012-03-19 14:02:47 +00003370 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003371 break;
3372 }
anthonyafa3dfc2012-03-03 11:31:30 +00003373 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003374 {
anthonyfd706f92012-01-19 04:22:02 +00003375 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003376 if ((flags & SigmaValue) == 0)
3377 geometry_info.sigma=1.0;
3378 if ((flags & XiValue) == 0)
3379 geometry_info.xi=1.0;
3380 if ((flags & PsiValue) == 0)
3381 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003382 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3383 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003384 break;
3385 }
3386 break;
3387 }
3388 case 'v':
3389 {
anthonyafa3dfc2012-03-03 11:31:30 +00003390 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003391 {
anthonyafa3dfc2012-03-03 11:31:30 +00003392 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003393 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003394 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003395 */
anthony92c93bd2012-03-19 14:02:47 +00003396 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003397 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003398 break;
3399 }
anthonyafa3dfc2012-03-03 11:31:30 +00003400 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003401 {
anthonyfd706f92012-01-19 04:22:02 +00003402 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003403 if ((flags & SigmaValue) == 0)
3404 geometry_info.sigma=1.0;
3405 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003406 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003407 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003408 geometry_info.psi=0.1*_image->rows;
3409 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3410 _image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3411 (ssize_t) ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003412 break;
3413 }
anthony805a2d42011-09-25 08:25:12 +00003414 break;
3415 }
3416 case 'w':
3417 {
anthonyafa3dfc2012-03-03 11:31:30 +00003418 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003419 {
anthonyfd706f92012-01-19 04:22:02 +00003420 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003421 if ((flags & SigmaValue) == 0)
3422 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003423 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3424 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003425 break;
3426 }
anthonyafa3dfc2012-03-03 11:31:30 +00003427 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003428 {
anthony92c93bd2012-03-19 14:02:47 +00003429 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003430 break;
3431 }
3432 break;
3433 }
3434 default:
3435 break;
3436 }
3437 /*
3438 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003439 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003440 */
3441 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003442 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003443
anthony31f1bf72012-01-30 12:37:22 +00003444 return;
anthony92c93bd2012-03-19 14:02:47 +00003445#undef _image_info
3446#undef _draw_info
3447#undef _quantize_info
3448#undef _image
3449#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003450#undef IfNormalOp
3451#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003452#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003453#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003454}
anthonyfd706f92012-01-19 04:22:02 +00003455
anthony43f425d2012-02-26 12:58:58 +00003456WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003457 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003458{
3459 size_t
anthony43f425d2012-02-26 12:58:58 +00003460 n,
anthony31f1bf72012-01-30 12:37:22 +00003461 i;
3462
anthony43f425d2012-02-26 12:58:58 +00003463 assert(cli_wand != (MagickCLI *) NULL);
3464 assert(cli_wand->signature == WandSignature);
3465 assert(cli_wand->wand.signature == WandSignature);
3466 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3467 if (cli_wand->wand.debug != MagickFalse)
3468 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003469
anthonyafa3dfc2012-03-03 11:31:30 +00003470#if !USE_WAND_METHODS
3471 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003472 i=0;
anthony43f425d2012-02-26 12:58:58 +00003473 n=GetImageListLength(cli_wand->wand.images);
3474 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003475 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003476 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003477 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003478 if ( cli_wand->wand.images->next == (Image *) NULL )
3479 break;
3480 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003481 }
anthony43f425d2012-02-26 12:58:58 +00003482 assert( i == n );
3483 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003484#else
3485 MagickResetIterator(&cli_wand->wand);
3486 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3487 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3488 MagickResetIterator(&cli_wand->wand);
3489#endif
anthony31f1bf72012-01-30 12:37:22 +00003490 return;
anthony805a2d42011-09-25 08:25:12 +00003491}
3492
3493/*
3494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3495% %
3496% %
3497% %
anthony43f425d2012-02-26 12:58:58 +00003498+ 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 +00003499% %
3500% %
3501% %
3502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3503%
anthony43f425d2012-02-26 12:58:58 +00003504% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003505% entire image list as a whole. The result is often a complete replacment
3506% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003507%
3508% The format of the MogrifyImage method is:
3509%
anthony43f425d2012-02-26 12:58:58 +00003510% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003511% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003512%
3513% A description of each parameter follows:
3514%
anthony43f425d2012-02-26 12:58:58 +00003515% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003516%
anthony36a8c2c2012-02-10 00:08:44 +00003517% o option: The option string for the operation
3518%
anthony31f1bf72012-01-30 12:37:22 +00003519% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003520%
anthony8b10b462012-02-08 12:32:44 +00003521% NOTE: only "limit" currently uses two arguments.
3522%
3523% Example usage...
3524%
anthonyafa3dfc2012-03-03 11:31:30 +00003525% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3526% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003527%
anthony24aa8822012-03-11 00:56:06 +00003528% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003529%
anthony43f425d2012-02-26 12:58:58 +00003530% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003531% argc,argv
3532% i=index in argv
3533%
anthony2052d272012-02-28 12:48:29 +00003534% option_info = GetCommandOptionInfo(argv[i]);
3535% count=option_info->type;
3536% option_type=option_info->flags;
3537%
3538% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003539% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003540% count>=1 ? argv[i+1] : (char *)NULL,
3541% count>=2 ? argv[i+2] : (char *)NULL );
3542% i += count+1;
3543%
anthony805a2d42011-09-25 08:25:12 +00003544*/
anthony43f425d2012-02-26 12:58:58 +00003545WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003546 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003547{
anthony31f1bf72012-01-30 12:37:22 +00003548 Image
3549 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003550
anthony92c93bd2012-03-19 14:02:47 +00003551#define _image_info (cli_wand->wand.image_info)
3552#define _images (cli_wand->wand.images)
3553#define _exception (cli_wand->wand.exception)
3554#define _draw_info (cli_wand->draw_info)
3555#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003556#define IfNormalOp (*option=='-')
3557#define IfPlusOp (*option!='-')
3558#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003559
anthony43f425d2012-02-26 12:58:58 +00003560 assert(cli_wand != (MagickCLI *) NULL);
3561 assert(cli_wand->signature == WandSignature);
3562 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003563 assert(_images != (Image *) NULL); /* _images must be present */
anthony43f425d2012-02-26 12:58:58 +00003564 if (cli_wand->wand.debug != MagickFalse)
3565 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003566
anthony92c93bd2012-03-19 14:02:47 +00003567 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003568
3569 new_images=NewImageList();
3570
anthonyafa3dfc2012-03-03 11:31:30 +00003571 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003572 {
3573 case 'a':
3574 {
anthonyafa3dfc2012-03-03 11:31:30 +00003575 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003576 {
anthony92c93bd2012-03-19 14:02:47 +00003577 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003578 break;
3579 }
anthonyafa3dfc2012-03-03 11:31:30 +00003580 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003581 {
anthony31f1bf72012-01-30 12:37:22 +00003582 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003583 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003584 break;
3585 }
3586 break;
3587 }
3588 case 'c':
3589 {
cristy5f257b22012-03-07 00:27:29 +00003590 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003591 {
anthony92c93bd2012-03-19 14:02:47 +00003592 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003593 break;
3594 }
anthonyafa3dfc2012-03-03 11:31:30 +00003595 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003596 {
anthony805a2d42011-09-25 08:25:12 +00003597 Image
anthony31f1bf72012-01-30 12:37:22 +00003598 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003599
anthonyafa3dfc2012-03-03 11:31:30 +00003600 /* FUTURE - make this a compose option, and thus can be used
3601 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003602 _images.
cristy87c02f42012-02-24 00:19:10 +00003603 */
anthony92c93bd2012-03-19 14:02:47 +00003604 new_images=RemoveFirstImageFromList(&_images);
3605 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003606 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003607 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003608 break;
anthony92c93bd2012-03-19 14:02:47 +00003609 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003610 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003611 break;
3612 }
anthonyafa3dfc2012-03-03 11:31:30 +00003613 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003614 {
anthony92c93bd2012-03-19 14:02:47 +00003615 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003616 break;
3617 }
anthonyafa3dfc2012-03-03 11:31:30 +00003618 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003619 {
anthony43f425d2012-02-26 12:58:58 +00003620 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003621 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003622 break;
3623 }
anthonyafa3dfc2012-03-03 11:31:30 +00003624 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003625 {
3626 Image
3627 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003628 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003629
3630 RectangleInfo
3631 geometry;
3632
anthony31f1bf72012-01-30 12:37:22 +00003633 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003634 compose;
3635
3636 const char*
3637 value;
3638
anthony92c93bd2012-03-19 14:02:47 +00003639 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00003640 if (value != (const char *) NULL)
3641 compose=(CompositeOperator) ParseCommandOption(
3642 MagickComposeOptions,MagickFalse,value);
3643 else
anthony31f1bf72012-01-30 12:37:22 +00003644 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003645
anthony92c93bd2012-03-19 14:02:47 +00003646 new_images=RemoveFirstImageFromList(&_images);
3647 source_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003648 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003649 if (source_image == (Image *) NULL)
3650 break;
anthonye8f56492012-02-12 12:39:02 +00003651
anthony31f1bf72012-01-30 12:37:22 +00003652 /* FUTURE - this should not be here! - should be part of -geometry */
3653 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003654 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003655
anthony31f1bf72012-01-30 12:37:22 +00003656 SetGeometry(source_image,&geometry);
3657 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3658 GravityAdjustGeometry(new_images->columns,new_images->rows,
3659 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003660
anthony92c93bd2012-03-19 14:02:47 +00003661 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003662 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003663 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003664 if ((compose == DisplaceCompositeOp) ||
3665 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003666 { /* Merge Y displacement into X displace/distort map. */
3667 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony92c93bd2012-03-19 14:02:47 +00003668 mask_image,0,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003669 mask_image=DestroyImage(mask_image);
3670 }
3671 else
3672 {
3673 /*
3674 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003675 */
anthony92c93bd2012-03-19 14:02:47 +00003676 (void) NegateImage(mask_image,MagickFalse,_exception);
3677 (void) SetImageMask(new_images,mask_image,_exception);
cristy1539afd2012-01-30 01:32:59 +00003678 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003679 }
3680 }
anthony31f1bf72012-01-30 12:37:22 +00003681 (void) CompositeImage(new_images,compose,source_image,geometry.x,
anthony92c93bd2012-03-19 14:02:47 +00003682 geometry.y,_exception);
3683 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003684 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003685 break;
3686 }
3687 break;
3688 }
3689 case 'd':
3690 {
anthonyafa3dfc2012-03-03 11:31:30 +00003691 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003692 {
anthony31f1bf72012-01-30 12:37:22 +00003693 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003694 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003695 break;
3696 }
anthonyafa3dfc2012-03-03 11:31:30 +00003697 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003698 {
anthonyafa3dfc2012-03-03 11:31:30 +00003699 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003700 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003701 else
anthony92c93bd2012-03-19 14:02:47 +00003702 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003703 break;
3704 }
anthonyafa3dfc2012-03-03 11:31:30 +00003705 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003706 {
anthonyafa3dfc2012-03-03 11:31:30 +00003707 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003708 {
3709 const char
3710 *p;
3711
3712 size_t
3713 number_duplicates;
3714
anthony31f1bf72012-01-30 12:37:22 +00003715 number_duplicates=(size_t) StringToLong(arg1);
3716 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003717 if (p == (const char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003718 new_images=DuplicateImages(_images,number_duplicates,
3719 "-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003720 else
anthony92c93bd2012-03-19 14:02:47 +00003721 new_images=DuplicateImages(_images,number_duplicates,p,
3722 _exception);
anthony805a2d42011-09-25 08:25:12 +00003723 }
anthonyafa3dfc2012-03-03 11:31:30 +00003724 else
anthony92c93bd2012-03-19 14:02:47 +00003725 new_images=DuplicateImages(_images,1,"-1",_exception);
3726 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003727 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003728 break;
3729 }
3730 break;
3731 }
3732 case 'e':
3733 {
anthonyafa3dfc2012-03-03 11:31:30 +00003734 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003735 {
anthony805a2d42011-09-25 08:25:12 +00003736 MagickEvaluateOperator
anthony31f1bf72012-01-30 12:37:22 +00003737 method;
anthony805a2d42011-09-25 08:25:12 +00003738
anthony31f1bf72012-01-30 12:37:22 +00003739 method=(MagickEvaluateOperator) ParseCommandOption(
3740 MagickEvaluateOptions,MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003741 new_images=EvaluateImages(_images,method,_exception);
anthony805a2d42011-09-25 08:25:12 +00003742 break;
3743 }
3744 break;
3745 }
3746 case 'f':
3747 {
anthonyafa3dfc2012-03-03 11:31:30 +00003748 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003749 {
anthony92c93bd2012-03-19 14:02:47 +00003750 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003751 break;
3752 }
anthonyafa3dfc2012-03-03 11:31:30 +00003753 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003754 {
anthony319dac62012-03-06 04:12:44 +00003755 /* REDIRECTED to use -layers flatten instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003756 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003757 break;
3758 }
anthonyafa3dfc2012-03-03 11:31:30 +00003759 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003760 {
anthony92c93bd2012-03-19 14:02:47 +00003761 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003762 break;
3763 }
3764 break;
3765 }
3766 case 'h':
3767 {
anthonyafa3dfc2012-03-03 11:31:30 +00003768 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003769 {
anthony31f1bf72012-01-30 12:37:22 +00003770 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003771 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003772 */
anthony805a2d42011-09-25 08:25:12 +00003773 Image
anthony31f1bf72012-01-30 12:37:22 +00003774 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003775
anthony92c93bd2012-03-19 14:02:47 +00003776 new_images=RemoveFirstImageFromList(&_images);
3777 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003778 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003779 break;
anthony92c93bd2012-03-19 14:02:47 +00003780 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003781 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003782 break;
3783 }
3784 break;
3785 }
3786 case 'i':
3787 {
anthonyafa3dfc2012-03-03 11:31:30 +00003788 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003789 {
3790 Image
anthony805a2d42011-09-25 08:25:12 +00003791 *magnitude_image,
3792 *phase_image;
3793
anthony92c93bd2012-03-19 14:02:47 +00003794 magnitude_image=RemoveFirstImageFromList(&_images);
3795 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003796 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003797 if (phase_image == (Image *) NULL)
3798 break;
3799 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003800 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003801 magnitude_image=DestroyImage(magnitude_image);
3802 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003803 break;
3804 }
anthonyafa3dfc2012-03-03 11:31:30 +00003805 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003806 {
3807 Image
anthony31f1bf72012-01-30 12:37:22 +00003808 *insert_image,
3809 *index_image;
3810
3811 ssize_t
3812 index;
anthony805a2d42011-09-25 08:25:12 +00003813
3814 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003815 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003816 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003817 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003818 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003819 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003820 PrependImageToList(&_images,insert_image);
3821 else if (index == (ssize_t) GetImageListLength(_images))
3822 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003823 else
anthony43f425d2012-02-26 12:58:58 +00003824 {
anthony92c93bd2012-03-19 14:02:47 +00003825 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003826 if (index_image == (Image *) NULL)
3827 {
anthony92c93bd2012-03-19 14:02:47 +00003828 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +00003829 OptionError,"NoSuchImage","'%s'",arg1);
3830 break;
3831 }
3832 InsertImageInList(&index_image,insert_image);
3833 }
anthony92c93bd2012-03-19 14:02:47 +00003834 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003835 break;
3836 }
anthony805a2d42011-09-25 08:25:12 +00003837 break;
3838 }
3839 case 'l':
3840 {
anthonyafa3dfc2012-03-03 11:31:30 +00003841 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003842 {
anthony805a2d42011-09-25 08:25:12 +00003843 ImageLayerMethod
3844 method;
3845
anthony805a2d42011-09-25 08:25:12 +00003846 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
anthony31f1bf72012-01-30 12:37:22 +00003847 MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00003848 switch (method)
3849 {
3850 case CoalesceLayer:
3851 {
anthony92c93bd2012-03-19 14:02:47 +00003852 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003853 break;
3854 }
3855 case CompareAnyLayer:
3856 case CompareClearLayer:
3857 case CompareOverlayLayer:
3858 default:
3859 {
anthony92c93bd2012-03-19 14:02:47 +00003860 new_images=CompareImagesLayers(_images,method,_exception);
anthony805a2d42011-09-25 08:25:12 +00003861 break;
3862 }
3863 case MergeLayer:
3864 case FlattenLayer:
3865 case MosaicLayer:
3866 case TrimBoundsLayer:
3867 {
anthony92c93bd2012-03-19 14:02:47 +00003868 new_images=MergeImageLayers(_images,method,_exception);
anthony805a2d42011-09-25 08:25:12 +00003869 break;
3870 }
3871 case DisposeLayer:
3872 {
anthony92c93bd2012-03-19 14:02:47 +00003873 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003874 break;
3875 }
3876 case OptimizeImageLayer:
3877 {
anthony92c93bd2012-03-19 14:02:47 +00003878 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003879 break;
3880 }
3881 case OptimizePlusLayer:
3882 {
anthony92c93bd2012-03-19 14:02:47 +00003883 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003884 break;
3885 }
3886 case OptimizeTransLayer:
3887 {
anthony92c93bd2012-03-19 14:02:47 +00003888 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003889 break;
3890 }
3891 case RemoveDupsLayer:
3892 {
anthony92c93bd2012-03-19 14:02:47 +00003893 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003894 break;
3895 }
3896 case RemoveZeroLayer:
3897 {
anthony92c93bd2012-03-19 14:02:47 +00003898 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003899 break;
3900 }
3901 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003902 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00003903 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003904 if (new_images == (Image *) NULL)
3905 break;
anthony92c93bd2012-03-19 14:02:47 +00003906 _images=DestroyImageList(_images);
3907 _images=OptimizeImageLayers(new_images,_exception);
3908 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003909 break;
3910 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00003911 OptimizeImageTransparency(_images,_exception);
3912 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3913 _exception);
anthony805a2d42011-09-25 08:25:12 +00003914 break;
3915 }
3916 case CompositeLayer:
3917 {
anthony805a2d42011-09-25 08:25:12 +00003918 Image
3919 *source;
3920
3921 RectangleInfo
3922 geometry;
3923
anthony31f1bf72012-01-30 12:37:22 +00003924 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003925 compose;
3926
3927 const char*
3928 value;
3929
anthony92c93bd2012-03-19 14:02:47 +00003930 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003931 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003932 if (value != (const char *) NULL)
3933 compose=(CompositeOperator) ParseCommandOption(
3934 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003935
anthony31f1bf72012-01-30 12:37:22 +00003936 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00003937 source=_images;
anthony805a2d42011-09-25 08:25:12 +00003938 while (source != (Image *) NULL)
3939 {
3940 source=GetNextImageInList(source);
3941 if ((source != (Image *) NULL) &&
3942 (LocaleCompare(source->magick,"NULL") == 0))
3943 break;
3944 }
3945 if (source != (Image *) NULL)
3946 {
3947 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3948 (GetNextImageInList(source) == (Image *) NULL))
3949 source=(Image *) NULL;
3950 else
anthony31f1bf72012-01-30 12:37:22 +00003951 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003952 source=SplitImageList(source->previous);
3953 DeleteImageFromList(&source);
3954 }
3955 }
3956 if (source == (Image *) NULL)
3957 {
anthony92c93bd2012-03-19 14:02:47 +00003958 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00003959 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003960 break;
3961 }
anthony31f1bf72012-01-30 12:37:22 +00003962 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00003963 SetGeometry(_images,&geometry);
3964 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003965 geometry.width=source->page.width != 0 ?
3966 source->page.width : source->columns;
3967 geometry.height=source->page.height != 0 ?
3968 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00003969 GravityAdjustGeometry(_images->page.width != 0 ?
3970 _images->page.width : _images->columns,
3971 _images->page.height != 0 ? _images->page.height :
3972 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003973
anthony31f1bf72012-01-30 12:37:22 +00003974 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00003975 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
3976 _exception);
anthony805a2d42011-09-25 08:25:12 +00003977 source=DestroyImageList(source);
3978 break;
3979 }
3980 }
anthony805a2d42011-09-25 08:25:12 +00003981 break;
3982 }
anthonyafa3dfc2012-03-03 11:31:30 +00003983 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00003984 {
3985 MagickSizeType
3986 limit;
3987
3988 ResourceType
3989 type;
3990
anthony72feaa62012-01-17 06:46:23 +00003991 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
anthony31f1bf72012-01-30 12:37:22 +00003992 MagickFalse,arg1);
anthony72feaa62012-01-17 06:46:23 +00003993 limit=MagickResourceInfinity;
anthony31f1bf72012-01-30 12:37:22 +00003994 if (LocaleCompare("unlimited",arg2) != 0)
3995 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthony72feaa62012-01-17 06:46:23 +00003996 (void) SetMagickResourceLimit(type,limit);
3997 break;
3998 }
anthony805a2d42011-09-25 08:25:12 +00003999 break;
4000 }
4001 case 'm':
4002 {
anthonyafa3dfc2012-03-03 11:31:30 +00004003 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004004 {
anthony31f1bf72012-01-30 12:37:22 +00004005 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004006 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004007 break;
4008 }
anthonyafa3dfc2012-03-03 11:31:30 +00004009 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004010 {
4011 Image
4012 *morph_image;
4013
anthony92c93bd2012-03-19 14:02:47 +00004014 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4015 _exception);
anthony805a2d42011-09-25 08:25:12 +00004016 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004017 break;
anthony92c93bd2012-03-19 14:02:47 +00004018 _images=DestroyImageList(_images);
4019 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004020 break;
4021 }
anthonyafa3dfc2012-03-03 11:31:30 +00004022 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004023 {
anthony319dac62012-03-06 04:12:44 +00004024 /* REDIRECTED to use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00004025 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004026 break;
4027 }
4028 break;
4029 }
4030 case 'p':
4031 {
anthonyafa3dfc2012-03-03 11:31:30 +00004032 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004033 {
4034 char
4035 *string;
4036
anthony92c93bd2012-03-19 14:02:47 +00004037 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004038 if (string == (char *) NULL)
4039 break;
4040 (void) FormatLocaleFile(stdout,"%s",string);
4041 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004042 break;
anthony805a2d42011-09-25 08:25:12 +00004043 }
anthonyafa3dfc2012-03-03 11:31:30 +00004044 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004045 {
4046 char
4047 **arguments;
4048
4049 int
4050 j,
4051 number_arguments;
4052
anthony31f1bf72012-01-30 12:37:22 +00004053 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004054 if (arguments == (char **) NULL)
4055 break;
anthony31f1bf72012-01-30 12:37:22 +00004056 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004057 {
4058 char
4059 breaker,
4060 quote,
4061 *token;
4062
4063 const char
4064 *arguments;
4065
4066 int
4067 next,
4068 status;
4069
4070 size_t
4071 length;
4072
4073 TokenInfo
4074 *token_info;
4075
4076 /*
anthony24aa8822012-03-11 00:56:06 +00004077 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004078 */
anthony31f1bf72012-01-30 12:37:22 +00004079 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004080 token=(char *) NULL;
4081 if (~length >= (MaxTextExtent-1))
4082 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4083 sizeof(*token));
4084 if (token == (char *) NULL)
4085 break;
4086 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004087 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004088 token_info=AcquireTokenInfo();
4089 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4090 "\"",'\0',&breaker,&next,&quote);
4091 token_info=DestroyTokenInfo(token_info);
4092 if (status == 0)
4093 {
4094 const char
4095 *argv;
4096
4097 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004098 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4099 _exception);
anthony805a2d42011-09-25 08:25:12 +00004100 }
4101 token=DestroyString(token);
4102 break;
4103 }
4104 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004105 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4106 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004107 for (j=0; j < number_arguments; j++)
4108 arguments[j]=DestroyString(arguments[j]);
4109 arguments=(char **) RelinquishMagickMemory(arguments);
4110 break;
4111 }
4112 break;
4113 }
4114 case 'r':
4115 {
anthonyafa3dfc2012-03-03 11:31:30 +00004116 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004117 {
anthony92c93bd2012-03-19 14:02:47 +00004118 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4119 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004120 break;
4121 }
anthonyafa3dfc2012-03-03 11:31:30 +00004122 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004123 {
anthony92c93bd2012-03-19 14:02:47 +00004124 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004125 break;
4126 }
4127 break;
4128 }
4129 case 's':
4130 {
anthonyafa3dfc2012-03-03 11:31:30 +00004131 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004132 {
4133 Image
4134 *smush_image;
4135
4136 ssize_t
4137 offset;
4138
anthony31f1bf72012-01-30 12:37:22 +00004139 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004140 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004141 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004142 break;
anthony92c93bd2012-03-19 14:02:47 +00004143 _images=DestroyImageList(_images);
4144 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004145 break;
4146 }
anthonyafa3dfc2012-03-03 11:31:30 +00004147 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004148 {
4149 Image
4150 *p,
4151 *q,
4152 *swap;
4153
4154 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004155 index,
anthony805a2d42011-09-25 08:25:12 +00004156 swap_index;
4157
anthony31f1bf72012-01-30 12:37:22 +00004158 index=-1;
4159 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004160 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004161 {
4162 GeometryInfo
4163 geometry_info;
4164
4165 MagickStatusType
4166 flags;
4167
4168 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004169 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004170 index=(ssize_t) geometry_info.rho;
4171 if ((flags & SigmaValue) != 0)
4172 swap_index=(ssize_t) geometry_info.sigma;
4173 }
anthony92c93bd2012-03-19 14:02:47 +00004174 p=GetImageFromList(_images,index);
4175 q=GetImageFromList(_images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004176 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4177 {
anthony92c93bd2012-03-19 14:02:47 +00004178 (void) ThrowMagickException(_exception,GetMagickModule(),
4179 OptionError,"NoSuchImage","'%s'",_images->filename);
anthony805a2d42011-09-25 08:25:12 +00004180 break;
4181 }
4182 if (p == q)
4183 break;
anthony92c93bd2012-03-19 14:02:47 +00004184 swap=CloneImage(p,0,0,MagickTrue,_exception);
4185 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
anthony805a2d42011-09-25 08:25:12 +00004186 ReplaceImageInList(&q,swap);
anthony92c93bd2012-03-19 14:02:47 +00004187 _images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004188 break;
4189 }
4190 break;
4191 }
4192 case 'w':
4193 {
anthonyafa3dfc2012-03-03 11:31:30 +00004194 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004195 {
4196 char
4197 key[MaxTextExtent];
4198
4199 Image
4200 *write_images;
4201
4202 ImageInfo
4203 *write_info;
4204
anthony31f1bf72012-01-30 12:37:22 +00004205 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004206 (void) DeleteImageRegistry(key);
anthony92c93bd2012-03-19 14:02:47 +00004207 write_images=_images;
anthonyafa3dfc2012-03-03 11:31:30 +00004208 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00004209 write_images=CloneImageList(_images,_exception);
4210 write_info=CloneImageInfo(_image_info);
4211 (void) WriteImages(write_info,write_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004212 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004213 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004214 write_images=DestroyImageList(write_images);
4215 break;
4216 }
4217 break;
4218 }
4219 default:
4220 break;
4221 }
anthony31f1bf72012-01-30 12:37:22 +00004222 if (new_images == (Image *) NULL)
4223 return;
anthony805a2d42011-09-25 08:25:12 +00004224
anthony92c93bd2012-03-19 14:02:47 +00004225 if (_images != (Image *) NULL)
4226 _images=DestroyImageList(_images);
4227 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004228 return;
4229
anthony92c93bd2012-03-19 14:02:47 +00004230#undef _image_info
4231#undef _images
4232#undef _exception
4233#undef _draw_info
4234#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004235#undef IfNormalOp
4236#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004237#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004238}
anthony43f425d2012-02-26 12:58:58 +00004239
4240/*
4241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4242% %
4243% %
4244% %
4245+ C L I S p e c i a l O p e r a t i o n s %
4246% %
4247% %
4248% %
4249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4250%
4251% CLISpecialOption() Applies operations that may involve empty image lists
4252% and or stacks of image lists or image_info settings.
4253%
anthonyafa3dfc2012-03-03 11:31:30 +00004254% The classic operators of this type is -read, and image stack operators,
4255% which can be applied to empty image lists.
4256%
4257% Note: unlike other Operators, these may involve other special 'option'
4258% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004259%
4260% The format of the CLISpecialOption method is:
4261%
4262% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004263% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004264%
4265% A description of each parameter follows:
4266%
4267% o cli_wand: the main CLI Wand to use.
4268%
4269% o option: The special option (with any switch char) to process
4270%
anthony24aa8822012-03-11 00:56:06 +00004271% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004272%
anthony2052d272012-02-28 12:48:29 +00004273% Example Usage...
4274%
anthonyce8dcb32012-03-21 13:20:31 +00004275% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004276%
anthony24aa8822012-03-11 00:56:06 +00004277% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004278%
4279% cli_wand
4280% argc,argv
4281% i=index in argv
4282%
4283% option_info = GetCommandOptionInfo(argv[i]);
4284% count=option_info->type;
4285% option_type=option_info->flags;
4286%
4287% if ( (option_type & SpecialOptionFlag) != 0 )
4288% CLISpecialOperator(cli_wand,argv[i],
4289% count>=1 ? argv[i+1] : (char *)NULL);
4290% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004291%
4292*/
4293
anthony43f425d2012-02-26 12:58:58 +00004294WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004295 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004296{
anthony92c93bd2012-03-19 14:02:47 +00004297#define _exception (cli_wand->wand.exception)
anthony43f425d2012-02-26 12:58:58 +00004298
4299 assert(cli_wand != (MagickCLI *) NULL);
4300 assert(cli_wand->signature == WandSignature);
4301 assert(cli_wand->wand.signature == WandSignature);
4302 if (cli_wand->wand.debug != MagickFalse)
4303 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4304
anthony24aa8822012-03-11 00:56:06 +00004305 if(cli_wand->wand.images != (Image *)NULL)
4306 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
anthony92c93bd2012-03-19 14:02:47 +00004307 _exception);
anthony24aa8822012-03-11 00:56:06 +00004308
anthonyce8dcb32012-03-21 13:20:31 +00004309 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
4310 /* image-setting stack linkage */
4311 (void) SetImageOption(cli_wand->wand.image_info,option+1,
4312 *option == '-' ? "true" : (char *) NULL);
4313 return;
4314 }
4315 if (LocaleCompare("(",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004316 /* stack 'push' images */
4317 Stack
4318 *node;
4319
4320 size_t
4321 size;
4322
anthony43f425d2012-02-26 12:58:58 +00004323 size=0;
4324 node=cli_wand->image_list_stack;
4325 for ( ; node != (Stack *)NULL; node=node->next)
4326 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004327 if ( size >= MAX_STACK_DEPTH )
anthony92c93bd2012-03-19 14:02:47 +00004328 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004329 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4330 if (node == (Stack *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004331 CLIWandExceptionReturn(ResourceLimitFatalError,
4332 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004333 node->data = (void *)cli_wand->wand.images;
4334 cli_wand->wand.images = NewImageList();
4335 node->next = cli_wand->image_list_stack;
4336 cli_wand->image_list_stack = node;
4337
4338 /* handle respect-parenthesis */
anthonyce8dcb32012-03-21 13:20:31 +00004339 if ( IsMagickTrue(GetImageOption(cli_wand->wand.image_info,
4340 "respect-parenthesis")) != MagickFalse )
anthony43f425d2012-02-26 12:58:58 +00004341 option="{";
4342 else
4343 return;
4344 }
anthonyce8dcb32012-03-21 13:20:31 +00004345 if (LocaleCompare("{",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004346 /* stack 'push' of image_info settings */
4347 Stack
4348 *node;
4349
4350 size_t
4351 size;
4352
4353 size=0;
4354 node=cli_wand->image_info_stack;
4355 for ( ; node != (Stack *)NULL; node=node->next)
4356 size++;
anthony92c93bd2012-03-19 14:02:47 +00004357 if ( size >= MAX_STACK_DEPTH )
4358 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004359 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthony92c93bd2012-03-19 14:02:47 +00004360 if (node == (Stack *) NULL)
4361 CLIWandExceptionReturn(ResourceLimitFatalError,
4362 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004363
4364 node->data = (void *)cli_wand->wand.image_info;
4365 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004366 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
anthony92c93bd2012-03-19 14:02:47 +00004367 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4368 option);
anthonyafa3dfc2012-03-03 11:31:30 +00004369 cli_wand->wand.image_info = (ImageInfo *)node->data;
4370 node = (Stack *)RelinquishMagickMemory(node);
4371 return;
4372 }
anthony43f425d2012-02-26 12:58:58 +00004373
4374 node->next = cli_wand->image_info_stack;
4375 cli_wand->image_info_stack = node;
4376
4377 return;
4378 }
anthonyce8dcb32012-03-21 13:20:31 +00004379 if (LocaleCompare(")",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004380 /* pop images from stack */
4381 Stack
4382 *node;
4383
anthony43f425d2012-02-26 12:58:58 +00004384 node = (void *)cli_wand->image_list_stack;
4385 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004386 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004387 cli_wand->image_list_stack = node->next;
4388
4389 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4390 cli_wand->wand.images= (Image *)node->data;
4391 node = (Stack *)RelinquishMagickMemory(node);
4392
4393 /* handle respect-parenthesis - of the previous 'push' settings */
4394 node = cli_wand->image_info_stack;
4395 if ( node != (Stack *)NULL)
4396 {
anthonyce8dcb32012-03-21 13:20:31 +00004397 if (IsMagickTrue(GetImageOption((ImageInfo *)node->data,
4398 "respect-parenthesis")) != MagickFalse )
4399 { option="}"; fprintf(stderr, "close\n"); }
anthony43f425d2012-02-26 12:58:58 +00004400 else
4401 return;
4402 }
4403 else
4404 return;
4405 }
anthonyce8dcb32012-03-21 13:20:31 +00004406 if (LocaleCompare("}",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004407 /* pop image_info settings from stack */
4408 Stack
4409 *node;
4410
4411 node = (void *)cli_wand->image_info_stack;
4412 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004413 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004414 cli_wand->image_info_stack = node->next;
4415
4416 (void) DestroyImageInfo(cli_wand->wand.image_info);
4417 cli_wand->wand.image_info = (ImageInfo *)node->data;
4418 node = (Stack *)RelinquishMagickMemory(node);
4419
4420 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4421 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4422 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4423
4424 return;
4425 }
anthonyce8dcb32012-03-21 13:20:31 +00004426 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004427 Image
4428 *new_images;
4429
4430 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004431 arg1="-1";
4432 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004433 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004434 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004435 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004436 new_images = (Image *)cli_wand->image_list_stack->data;
4437 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004438 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4439 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004440 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004441 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony43f425d2012-02-26 12:58:58 +00004442 AppendImageToList(&cli_wand->wand.images,new_images);
4443 return;
4444 }
anthony319dac62012-03-06 04:12:44 +00004445 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthonyce8dcb32012-03-21 13:20:31 +00004446 ( LocaleCompare("--",option) == 0 ) ) {
anthonyafa3dfc2012-03-03 11:31:30 +00004447#if !USE_WAND_METHODS
anthony43f425d2012-02-26 12:58:58 +00004448 Image *
4449 new_images;
4450
anthony43f425d2012-02-26 12:58:58 +00004451 if (cli_wand->wand.image_info->ping != MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004452 new_images=PingImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004453 else
anthony92c93bd2012-03-19 14:02:47 +00004454 new_images=ReadImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004455 AppendImageToList(&cli_wand->wand.images, new_images);
4456#else
4457 /* read images using MagickWand method - no ping */
4458 /* This is not working! - it locks up in a CPU loop! */
4459 MagickSetLastIterator(&cli_wand->wand);
anthony24aa8822012-03-11 00:56:06 +00004460 MagickReadImage(&cli_wand->wand,arg1);
anthony43f425d2012-02-26 12:58:58 +00004461 MagickSetFirstIterator(&cli_wand->wand);
4462#endif
4463 return;
4464 }
anthonyafa3dfc2012-03-03 11:31:30 +00004465 /* No-op options */
4466 if (LocaleCompare("noop",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004467 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004468 if (LocaleCompare("sans",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004469 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004470 if (LocaleCompare("sans0",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004471 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004472 if (LocaleCompare("sans2",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004473 return;
anthonyce8dcb32012-03-21 13:20:31 +00004474 if (LocaleCompare("list",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004475 /* FUTURE: This should really be built into the MagickCore
4476 It does not actually require any wand or images at all!
4477 */
4478 ssize_t
4479 list;
4480
anthony24aa8822012-03-11 00:56:06 +00004481 list=ParseCommandOption(MagickListOptions,MagickFalse, arg1);
anthony43f425d2012-02-26 12:58:58 +00004482 switch (list)
4483 {
4484 case MagickCoderOptions:
4485 {
anthony92c93bd2012-03-19 14:02:47 +00004486 (void) ListCoderInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004487 break;
4488 }
4489 case MagickColorOptions:
4490 {
anthony92c93bd2012-03-19 14:02:47 +00004491 (void) ListColorInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004492 break;
4493 }
4494 case MagickConfigureOptions:
4495 {
anthony92c93bd2012-03-19 14:02:47 +00004496 (void) ListConfigureInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004497 break;
4498 }
4499 case MagickDelegateOptions:
4500 {
anthony92c93bd2012-03-19 14:02:47 +00004501 (void) ListDelegateInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004502 break;
4503 }
4504 case MagickFontOptions:
4505 {
anthony92c93bd2012-03-19 14:02:47 +00004506 (void) ListTypeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004507 break;
4508 }
4509 case MagickFormatOptions:
anthony92c93bd2012-03-19 14:02:47 +00004510 (void) ListMagickInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004511 break;
4512 case MagickLocaleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004513 (void) ListLocaleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004514 break;
4515 case MagickLogOptions:
anthony92c93bd2012-03-19 14:02:47 +00004516 (void) ListLogInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004517 break;
4518 case MagickMagicOptions:
anthony92c93bd2012-03-19 14:02:47 +00004519 (void) ListMagicInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004520 break;
4521 case MagickMimeOptions:
anthony92c93bd2012-03-19 14:02:47 +00004522 (void) ListMimeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004523 break;
4524 case MagickModuleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004525 (void) ListModuleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004526 break;
4527 case MagickPolicyOptions:
anthony92c93bd2012-03-19 14:02:47 +00004528 (void) ListPolicyInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004529 break;
4530 case MagickResourceOptions:
anthony92c93bd2012-03-19 14:02:47 +00004531 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004532 break;
4533 case MagickThresholdOptions:
anthony92c93bd2012-03-19 14:02:47 +00004534 (void) ListThresholdMaps((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004535 break;
4536 default:
4537 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
anthony92c93bd2012-03-19 14:02:47 +00004538 _exception);
anthony43f425d2012-02-26 12:58:58 +00004539 break;
4540 }
4541 return;
4542 }
4543
4544#if 0
4545 // adjust stack handling
4546 // Other 'special' options this should handle
4547 // "region" "list" "version"
4548 // It does not do "exit" however as due to its side-effect requirements
4549#endif
4550#if 0
4551 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
4552 MagickExceptionReturn(OptionError,"InvalidUseOfOption",option);
4553#endif
4554
anthony92c93bd2012-03-19 14:02:47 +00004555#undef _exception
anthony43f425d2012-02-26 12:58:58 +00004556}