blob: 395bcc91f7e399c1e6ea3ff1e5cb3dc335b4efc8 [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 */
anthony805a2d42011-09-25 08:25:12 +0000223 else {
224 x++; /* floating point argument */
225 }
226 }
227 error=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +0000228 /* control points and color values */
229 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
230 number_arguments=x;
anthony805a2d42011-09-25 08:25:12 +0000231 if ( error ) {
232 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000233 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000234 "Invalid number of Arguments");
235 return( (Image *)NULL);
236 }
237
238 /* Allocate and fill in the floating point arguments */
239 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
240 sizeof(*sparse_arguments));
241 if (sparse_arguments == (double *) NULL) {
242 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
243 "MemoryAllocationFailed","%s","SparseColorOption");
244 return( (Image *)NULL);
245 }
246 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
247 sizeof(*sparse_arguments));
248 p=arguments;
249 x=0;
250 while( *p != '\0' && x < number_arguments ) {
251 /* X coordinate */
252 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
253 if ( token[0] == '\0' ) break;
254 if ( isalpha((int) token[0]) || token[0] == '#' ) {
255 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000256 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000257 "Color found, instead of X-coord");
258 error = MagickTrue;
259 break;
260 }
cristydbdd0e32011-11-04 23:29:40 +0000261 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000262 /* Y coordinate */
263 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
264 if ( token[0] == '\0' ) break;
265 if ( isalpha((int) token[0]) || token[0] == '#' ) {
266 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000267 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000268 "Color found, instead of Y-coord");
269 error = MagickTrue;
270 break;
271 }
cristydbdd0e32011-11-04 23:29:40 +0000272 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000273 /* color name or function given in string argument */
274 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
275 if ( token[0] == '\0' ) break;
276 if ( isalpha((int) token[0]) || token[0] == '#' ) {
277 /* Color string given */
278 (void) QueryColorCompliance(token,AllCompliance,&color,
279 exception);
280 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
281 sparse_arguments[x++] = QuantumScale*color.red;
282 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
283 sparse_arguments[x++] = QuantumScale*color.green;
284 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
285 sparse_arguments[x++] = QuantumScale*color.blue;
286 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
287 (image->colorspace == CMYKColorspace))
288 sparse_arguments[x++] = QuantumScale*color.black;
289 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
290 (image->matte != MagickFalse))
291 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000292 }
anthony31f1bf72012-01-30 12:37:22 +0000293 else {
294 /* Colors given as a set of floating point values - experimental */
295 /* NB: token contains the first floating point value to use! */
296 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
297 {
298 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
299 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
300 break;
301 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
302 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000303 }
anthony31f1bf72012-01-30 12:37:22 +0000304 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
305 {
306 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
307 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
308 break;
309 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
310 token[0] = ','; /* used this token - get another */
311 }
312 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
313 {
314 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
315 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
316 break;
317 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
318 token[0] = ','; /* used this token - get another */
319 }
320 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
321 (image->colorspace == CMYKColorspace))
322 {
323 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
324 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
325 break;
326 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
327 token[0] = ','; /* used this token - get another */
328 }
329 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
330 (image->matte != MagickFalse))
331 {
332 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
333 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
334 break;
335 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
336 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000337 }
338 }
339 }
340 if ( number_arguments != x && !error ) {
341 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000342 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000343 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
344 return( (Image *)NULL);
345 }
346 if ( error )
347 return( (Image *)NULL);
348
anthony31f1bf72012-01-30 12:37:22 +0000349 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000350 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
351 exception);
352 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
353 return( sparse_image );
354}
355
356/*
357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
358% %
359% %
360% %
anthony43f425d2012-02-26 12:58:58 +0000361+ A c q u i r e W a n d C L I %
anthony805a2d42011-09-25 08:25:12 +0000362% %
363% %
364% %
365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366%
anthony43f425d2012-02-26 12:58:58 +0000367% AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
368% Wand). The given image_info and exception is included as is if provided.
anthony805a2d42011-09-25 08:25:12 +0000369%
anthony43f425d2012-02-26 12:58:58 +0000370% Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
371% needed.
372%
373% The format of the NewMagickWand method is:
anthonyafa3dfc2012-03-03 11:31:30 +0000374%
anthony43f425d2012-02-26 12:58:58 +0000375% MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
376% ExceptionInfo *exception)
377%
378*/
379WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
380 ExceptionInfo *exception)
381{
382 MagickCLI
383 *cli_wand;
384
385 /* precaution - as per NewMagickWand() */
386 {
387 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
388 const char *quantum = GetMagickQuantumDepth(&depth);
389 if (depth != MAGICKCORE_QUANTUM_DEPTH)
390 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
391 }
392
393 /* allocate memory for MgaickCLI */
394 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
395 if (cli_wand == (MagickCLI *) NULL)
396 {
397 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
398 GetExceptionMessage(errno));
399 return((MagickCLI *)NULL);
400 }
401
402 /* Initialize Wand Part of MagickCLI
403 FUTURE: this is a repeat of code from NewMagickWand()
404 However some parts may be given fro man external source!
405 */
406 cli_wand->wand.id=AcquireWandId();
407 (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
408 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
409 cli_wand->wand.images=NewImageList();
410 if ( image_info == (ImageInfo *)NULL)
411 cli_wand->wand.image_info=AcquireImageInfo();
412 else
413 cli_wand->wand.image_info=image_info;
414 if ( exception == (ExceptionInfo *)NULL)
415 cli_wand->wand.exception=AcquireExceptionInfo();
416 else
417 cli_wand->wand.exception=exception;
418 cli_wand->wand.debug=IsEventLogging();
419 cli_wand->wand.signature=WandSignature;
420
421 /* Initialize CLI Part of MagickCLI */
422 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
423 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
424 cli_wand->image_list_stack=(Stack *)NULL;
425 cli_wand->image_info_stack=(Stack *)NULL;
anthonyafa3dfc2012-03-03 11:31:30 +0000426 cli_wand->location="'%s' at unknown location";
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,
577% const char *option, const char *arg)
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%
anthony72feaa62012-01-17 06:46:23 +0000585% o arg: 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%
593% Or for handling command line arguments EG: +/-option ["arg"]
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,
609 const char *option,const char *arg)
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
anthony43f425d2012-02-26 12:58:58 +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)
anthonyafa3dfc2012-03-03 11:31:30 +0000621#define IfSetOption (*option=='-')
anthony72feaa62012-01-17 06:46:23 +0000622#define ArgOption(def) (IfSetOption?arg:(const char *)(def))
623#define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
anthonyafa3dfc2012-03-03 11:31:30 +0000624#define ArgBooleanNot (IfSetOption?MagickFalse:MagickTrue)
anthony74b1cfc2011-10-06 12:44:16 +0000625
anthonyafa3dfc2012-03-03 11:31:30 +0000626 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000627 {
628 case 'a':
629 {
anthonyafa3dfc2012-03-03 11:31:30 +0000630 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000631 {
anthony72feaa62012-01-17 06:46:23 +0000632 image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000633 break;
634 }
anthonyafa3dfc2012-03-03 11:31:30 +0000635 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000636 {
anthony31f1bf72012-01-30 12:37:22 +0000637 /* DEPRECIATED: draw_info setting only: for -draw and -transform */
anthony74b1cfc2011-10-06 12:44:16 +0000638 if (IfSetOption)
anthony72feaa62012-01-17 06:46:23 +0000639 (void) ParseAffineGeometry(arg,&draw_info->affine,exception);
anthony74b1cfc2011-10-06 12:44:16 +0000640 else
anthony72feaa62012-01-17 06:46:23 +0000641 GetAffineMatrix(&draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000642 break;
643 }
anthonyafa3dfc2012-03-03 11:31:30 +0000644 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000645 {
anthony1afdc7a2011-10-05 11:54:28 +0000646 image_info->antialias =
anthony72feaa62012-01-17 06:46:23 +0000647 draw_info->stroke_antialias =
648 draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000649 break;
650 }
anthony31f1bf72012-01-30 12:37:22 +0000651 if (LocaleCompare("attenuate",option+1) == 0)
652 {
anthonyafa3dfc2012-03-03 11:31:30 +0000653 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony31f1bf72012-01-30 12:37:22 +0000654 break;
655 }
anthonyafa3dfc2012-03-03 11:31:30 +0000656 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000657 {
anthonyafa3dfc2012-03-03 11:31:30 +0000658 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000659 break;
660 }
661 break;
662 }
663 case 'b':
664 {
anthonyafa3dfc2012-03-03 11:31:30 +0000665 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000666 {
anthony74b1cfc2011-10-06 12:44:16 +0000667 /* FUTURE: both image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000668 image_info only used directly for generating new images.
669 SyncImageSettings() used to set per-image attribute.
670
671 FUTURE: if image_info->background_color is not set then
672 we should fall back to image
673 Note that +background, means fall-back to image background
674 and only if not set fall back to BackgroundColor const.
anthony74b1cfc2011-10-06 12:44:16 +0000675 */
anthonyafa3dfc2012-03-03 11:31:30 +0000676 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000677 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
678 &image_info->background_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000679 break;
680 }
anthonyafa3dfc2012-03-03 11:31:30 +0000681 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000682 {
anthony74b1cfc2011-10-06 12:44:16 +0000683 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000684 as it is actually rarely used except in direct convolve operations
685 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000686
687 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000688 */
anthonyafa3dfc2012-03-03 11:31:30 +0000689 (void) SetImageOption(image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000690 break;
691 }
anthonyafa3dfc2012-03-03 11:31:30 +0000692 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000693 {
anthony72feaa62012-01-17 06:46:23 +0000694 /* Used as a image chromaticity setting
695 SyncImageSettings() used to set per-image attribute.
696 */
anthonyafa3dfc2012-03-03 11:31:30 +0000697 (void) SetImageOption(image_info,option+1,
698 IfSetOption ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +0000699 break;
700 }
anthonyafa3dfc2012-03-03 11:31:30 +0000701 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000702 {
anthonyafbaed72011-10-26 12:05:04 +0000703 /* Image chromaticity X,Y NB: Y=X if Y not defined
704 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000705 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000706 */
anthonyafa3dfc2012-03-03 11:31:30 +0000707 (void) SetImageOption(image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000708 break;
709 }
anthonyafa3dfc2012-03-03 11:31:30 +0000710 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000711 {
anthony72feaa62012-01-17 06:46:23 +0000712 /* FUTURE: both image_info attribute & ImageOption in use!
713 SyncImageSettings() used to set per-image attribute.
714 */
anthony74b1cfc2011-10-06 12:44:16 +0000715 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000716 {
anthonyafa3dfc2012-03-03 11:31:30 +0000717 (void) SetImageOption(image_info,option+1,arg);
anthony72feaa62012-01-17 06:46:23 +0000718 (void) QueryColorCompliance(arg,AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000719 &image_info->border_color,exception);
anthonydcf510d2011-10-30 13:51:40 +0000720 (void) QueryColorCompliance(arg,AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000721 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000722 break;
723 }
anthonyafa3dfc2012-03-03 11:31:30 +0000724 (void) DeleteImageOption(image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000725 (void) QueryColorCompliance(BorderColor,AllCompliance,
726 &image_info->border_color,exception);
727 (void) QueryColorCompliance(BorderColor,AllCompliance,
728 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000729 break;
730 }
anthonyafa3dfc2012-03-03 11:31:30 +0000731 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000732 {
anthonyfd706f92012-01-19 04:22:02 +0000733 /* DEPRECIATED - now "undercolor" */
anthony43f425d2012-02-26 12:58:58 +0000734 CLISettingOptionInfo(cli_wand,"undercolor",arg);
anthonyfd706f92012-01-19 04:22:02 +0000735 break;
anthony805a2d42011-09-25 08:25:12 +0000736 }
737 break;
738 }
739 case 'c':
740 {
anthonyafa3dfc2012-03-03 11:31:30 +0000741 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000742 {
743 MagickSizeType
744 limit;
745
746 limit=MagickResourceInfinity;
anthonydcf510d2011-10-30 13:51:40 +0000747 if (LocaleCompare("unlimited",arg) != 0)
cristy9b34e302011-11-05 02:15:45 +0000748 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg,100.0);
anthony805a2d42011-09-25 08:25:12 +0000749 (void) SetMagickResourceLimit(MemoryResource,limit);
750 (void) SetMagickResourceLimit(MapResource,2*limit);
751 break;
752 }
anthonyafa3dfc2012-03-03 11:31:30 +0000753 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000754 {
anthonyafa3dfc2012-03-03 11:31:30 +0000755 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000756 break;
757 }
anthonyafa3dfc2012-03-03 11:31:30 +0000758 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000759 {
anthony43f425d2012-02-26 12:58:58 +0000760 /* FUTURE: -channel mask {vaules}
761 This is applied to images in SimpleImageOperator!!!
762 Move it to SyncImageSettings() - or alternative
anthony31f1bf72012-01-30 12:37:22 +0000763 */
anthony74b1cfc2011-10-06 12:44:16 +0000764 image_info->channel=(ChannelType) (
anthonydcf510d2011-10-30 13:51:40 +0000765 IfSetOption ? ParseChannelOption(arg) : DefaultChannels );
anthony805a2d42011-09-25 08:25:12 +0000766 break;
767 }
anthonyafa3dfc2012-03-03 11:31:30 +0000768 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000769 {
anthonyafbaed72011-10-26 12:05:04 +0000770 /* Setting used for new images via AquireImage()
771 But also used as a SimpleImageOperator
772 Undefined colorspace means don't modify images on
773 read or as a operation */
anthony72feaa62012-01-17 06:46:23 +0000774 image_info->colorspace=(ColorspaceType) ParseCommandOption(
775 MagickColorspaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000776 break;
777 }
anthonyafa3dfc2012-03-03 11:31:30 +0000778 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000779 {
anthonyafa3dfc2012-03-03 11:31:30 +0000780 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000781 break;
782 }
anthonyafa3dfc2012-03-03 11:31:30 +0000783 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000784 {
anthony72feaa62012-01-17 06:46:23 +0000785 /* FUTURE: image_info should be used,
786 SyncImageSettings() used to set per-image attribute. - REMOVE
787
anthonyafbaed72011-10-26 12:05:04 +0000788 This setting should NOT be used to set image 'compose'
anthony72feaa62012-01-17 06:46:23 +0000789 "-layer" operators shoud use image_info if defined otherwise
790 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000791 */
anthonyafa3dfc2012-03-03 11:31:30 +0000792 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony965524b2011-10-07 12:34:14 +0000793 image_info->compose=(CompositeOperator) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000794 MagickComposeOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000795 break;
796 }
anthonyafa3dfc2012-03-03 11:31:30 +0000797 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000798 {
anthony5f867ae2011-10-09 10:28:34 +0000799 /* FUTURE: What should be used? image_info or ImageOption ???
800 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000801 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000802
803 The coders appears to use image_info, not Image_Option
804 however the image attribute (for save) is set from the
805 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000806
807 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000808 */
anthonyafa3dfc2012-03-03 11:31:30 +0000809 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000810 image_info->compression=(CompressionType) ParseCommandOption(
811 MagickCompressOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000812 break;
813 }
814 break;
815 }
816 case 'd':
817 {
anthonyafa3dfc2012-03-03 11:31:30 +0000818 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000819 {
anthony72feaa62012-01-17 06:46:23 +0000820 /* SyncImageSettings() used to set per-image attribute. */
821 (void) SetLogEventMask(ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000822 image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000823 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000824 break;
825 }
anthonyafa3dfc2012-03-03 11:31:30 +0000826 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000827 {
anthony72feaa62012-01-17 06:46:23 +0000828 /* DefineImageOption() equals SetImageOption() but with '='
829 It does not however set individual image options.
anthonyafa3dfc2012-03-03 11:31:30 +0000830 "-set" will set individual image options as well!
anthony5f867ae2011-10-09 10:28:34 +0000831 */
anthonydcf510d2011-10-30 13:51:40 +0000832 if (LocaleNCompare(arg,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000833 {
anthony5f867ae2011-10-09 10:28:34 +0000834 if (IfSetOption)
anthonyafa3dfc2012-03-03 11:31:30 +0000835 (void) DefineImageRegistry(StringRegistryType,arg+9,exception);
anthony5f867ae2011-10-09 10:28:34 +0000836 else
anthony72feaa62012-01-17 06:46:23 +0000837 (void) DeleteImageRegistry(arg+9);
anthony805a2d42011-09-25 08:25:12 +0000838 break;
839 }
anthony5f867ae2011-10-09 10:28:34 +0000840 if (IfSetOption)
anthony72feaa62012-01-17 06:46:23 +0000841 (void) DefineImageOption(image_info,arg);
anthony5f867ae2011-10-09 10:28:34 +0000842 else
anthony72feaa62012-01-17 06:46:23 +0000843 (void) DeleteImageOption(image_info,arg);
anthony805a2d42011-09-25 08:25:12 +0000844 break;
845 }
anthonyafa3dfc2012-03-03 11:31:30 +0000846 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000847 {
anthonyafbaed72011-10-26 12:05:04 +0000848 /* Only used for new images via AcquireImage()
849 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000850 */
anthonyafa3dfc2012-03-03 11:31:30 +0000851 (void) SetImageOption(image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000852 break;
853 }
anthonyafa3dfc2012-03-03 11:31:30 +0000854 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000855 {
anthony72feaa62012-01-17 06:46:23 +0000856 /* FUTURE: strings used in image_info attr and draw_info!
857 Basically as density can be in a XxY form!
858
859 SyncImageSettings() used to set per-image attribute.
860 */
anthonyafa3dfc2012-03-03 11:31:30 +0000861 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000862 (void) CloneString(&image_info->density,ArgOption(NULL));
863 (void) CloneString(&draw_info->density,image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000864 break;
865 }
anthonyafa3dfc2012-03-03 11:31:30 +0000866 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000867 {
anthony72feaa62012-01-17 06:46:23 +0000868 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
869 SyncImageSettings() used to set per-image attribute.
870 */
anthonydcf510d2011-10-30 13:51:40 +0000871 image_info->depth=IfSetOption?StringToUnsignedLong(arg)
anthony5f867ae2011-10-09 10:28:34 +0000872 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000873 break;
874 }
anthonyafa3dfc2012-03-03 11:31:30 +0000875 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000876 {
anthony6dc09cd2011-10-12 08:56:49 +0000877 /* Image Option is only used to set draw_info */
anthonyafa3dfc2012-03-03 11:31:30 +0000878 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
anthony5f867ae2011-10-09 10:28:34 +0000879 draw_info->direction=(DirectionType) ParseCommandOption(
880 MagickDirectionOptions,MagickFalse,
anthony72feaa62012-01-17 06:46:23 +0000881 ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000882 break;
883 }
anthonyafa3dfc2012-03-03 11:31:30 +0000884 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000885 {
anthony72feaa62012-01-17 06:46:23 +0000886 (void) CloneString(&image_info->server_name,ArgOption(NULL));
887 (void) CloneString(&draw_info->server_name,image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000888 break;
889 }
anthonyafa3dfc2012-03-03 11:31:30 +0000890 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000891 {
anthony72feaa62012-01-17 06:46:23 +0000892 /* only used in setting new images */
anthonyafa3dfc2012-03-03 11:31:30 +0000893 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000894 break;
895 }
anthonyafa3dfc2012-03-03 11:31:30 +0000896 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000897 {
anthony72feaa62012-01-17 06:46:23 +0000898 /* image_info attr (on/off), quantize_info attr (on/off)
899 but also ImageInfo and quantize_info method!
900 FUTURE: merge the duality of the dithering options
901 */
902 image_info->dither = quantize_info->dither = ArgBoolean;
anthonyafa3dfc2012-03-03 11:31:30 +0000903 (void) SetImageOption(image_info,option+1,ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000904 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000905 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000906 if (quantize_info->dither_method == NoDitherMethod)
anthony72feaa62012-01-17 06:46:23 +0000907 image_info->dither = quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000908 break;
909 }
910 break;
911 }
912 case 'e':
913 {
anthonyafa3dfc2012-03-03 11:31:30 +0000914 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000915 {
anthony72feaa62012-01-17 06:46:23 +0000916 (void) CloneString(&draw_info->encoding,ArgOption("undefined"));
anthonyafa3dfc2012-03-03 11:31:30 +0000917 (void) SetImageOption(image_info,option+1,draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000918 break;
919 }
anthonyafa3dfc2012-03-03 11:31:30 +0000920 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000921 {
anthony72feaa62012-01-17 06:46:23 +0000922 /* Both image_info attr and ImageInfo */
anthonyafa3dfc2012-03-03 11:31:30 +0000923 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000924 image_info->endian=(EndianType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000925 MagickEndianOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000926 break;
927 }
anthonyafa3dfc2012-03-03 11:31:30 +0000928 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000929 {
anthony72feaa62012-01-17 06:46:23 +0000930 (void) CloneString(&image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000931 break;
932 }
933 break;
934 }
935 case 'f':
936 {
anthonyafa3dfc2012-03-03 11:31:30 +0000937 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000938 {
anthony72feaa62012-01-17 06:46:23 +0000939 (void) CloneString(&draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000940 break;
941 }
anthonyafa3dfc2012-03-03 11:31:30 +0000942 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000943 {
anthonyfd706f92012-01-19 04:22:02 +0000944 /* Set "fill" OR "fill-pattern" in draw_info
945 The original fill color is preserved if a fill-pattern is given.
946 That way it does not effect other operations that directly using
947 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000948 */
anthony6dc09cd2011-10-12 08:56:49 +0000949 const char
anthony72feaa62012-01-17 06:46:23 +0000950 *value;
951
952 MagickBooleanType
953 status;
anthony6dc09cd2011-10-12 08:56:49 +0000954
955 ExceptionInfo
956 *sans;
957
anthonyfd706f92012-01-19 04:22:02 +0000958 PixelInfo
959 color;
960
anthony72feaa62012-01-17 06:46:23 +0000961 value = ArgOption("none");
anthonyafa3dfc2012-03-03 11:31:30 +0000962 (void) SetImageOption(image_info,option+1,value);
anthony6dc09cd2011-10-12 08:56:49 +0000963 if (draw_info->fill_pattern != (Image *) NULL)
964 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000965
966 /* is it a color or a image? -- ignore exceptions */
967 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +0000968 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000969 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000970
anthony6dc09cd2011-10-12 08:56:49 +0000971 if (status == MagickFalse)
anthony72feaa62012-01-17 06:46:23 +0000972 draw_info->fill_pattern=GetImageCache(image_info,value,exception);
anthonyfd706f92012-01-19 04:22:02 +0000973 else
974 draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000975 break;
976 }
anthonyafa3dfc2012-03-03 11:31:30 +0000977 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000978 {
anthony72feaa62012-01-17 06:46:23 +0000979 /* SyncImageSettings() used to set per-image attribute. */
anthonyafa3dfc2012-03-03 11:31:30 +0000980 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000981 break;
982 }
anthonyafa3dfc2012-03-03 11:31:30 +0000983 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000984 {
anthony72feaa62012-01-17 06:46:23 +0000985 (void) CloneString(&draw_info->font,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000986 (void) CloneString(&image_info->font,draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000987 break;
988 }
anthonyafa3dfc2012-03-03 11:31:30 +0000989 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000990 {
anthonydcf510d2011-10-30 13:51:40 +0000991 /* FUTURE: why the ping test, you could set ping after this! */
992 /*
anthony805a2d42011-09-25 08:25:12 +0000993 register const char
994 *q;
995
anthonydcf510d2011-10-30 13:51:40 +0000996 for (q=strchr(arg,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000997 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
998 image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000999 */
anthonyafa3dfc2012-03-03 11:31:30 +00001000 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001001 break;
1002 }
anthonyafa3dfc2012-03-03 11:31:30 +00001003 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001004 {
anthony72feaa62012-01-17 06:46:23 +00001005 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +00001006 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +00001007 SyncImageSettings() used to set per-image attribute.
1008
1009 Can't find anything else using image_info->fuzz directly!
anthony6613bf32011-10-15 07:24:44 +00001010 */
1011 if (IfSetOption)
cristy947cb4c2011-10-20 18:41:46 +00001012 {
anthony80c37752012-01-16 01:03:11 +00001013 image_info->fuzz=StringToDoubleInterval(arg,(double)
1014 QuantumRange+1.0);
anthonyafa3dfc2012-03-03 11:31:30 +00001015 (void) SetImageOption(image_info,option+1,arg);
cristy947cb4c2011-10-20 18:41:46 +00001016 break;
1017 }
1018 image_info->fuzz=0.0;
anthonyafa3dfc2012-03-03 11:31:30 +00001019 (void) SetImageOption(image_info,option+1,"0");
anthony805a2d42011-09-25 08:25:12 +00001020 break;
1021 }
1022 break;
1023 }
1024 case 'g':
1025 {
anthonyafa3dfc2012-03-03 11:31:30 +00001026 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001027 {
anthony72feaa62012-01-17 06:46:23 +00001028 /* SyncImageSettings() used to set per-image attribute. */
anthonyafa3dfc2012-03-03 11:31:30 +00001029 (void) SetImageOption(image_info,option+1,ArgOption("none"));
anthony6dc09cd2011-10-12 08:56:49 +00001030 draw_info->gravity=(GravityType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001031 MagickGravityOptions,MagickFalse,ArgOption("none"));
anthony805a2d42011-09-25 08:25:12 +00001032 break;
1033 }
anthonyafa3dfc2012-03-03 11:31:30 +00001034 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001035 {
anthonydcf510d2011-10-30 13:51:40 +00001036 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +00001037 SyncImageSettings() used to set per-image attribute.
1038 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +00001039 */
anthonyafa3dfc2012-03-03 11:31:30 +00001040 (void) SetImageOption(image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001041 break;
1042 }
1043 break;
1044 }
1045 case 'i':
1046 {
anthonyafa3dfc2012-03-03 11:31:30 +00001047 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001048 {
anthony72feaa62012-01-17 06:46:23 +00001049 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +00001050 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +00001051 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001052 */
anthonyafa3dfc2012-03-03 11:31:30 +00001053 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001054 break;
1055 }
anthonyafa3dfc2012-03-03 11:31:30 +00001056 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001057 {
anthony72feaa62012-01-17 06:46:23 +00001058 /* image_info is directly used by coders (so why an image setting?)
1059 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001060 */
anthonyafa3dfc2012-03-03 11:31:30 +00001061 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001062 image_info->interlace=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001063 MagickInterlaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001064 break;
1065 }
anthonyafa3dfc2012-03-03 11:31:30 +00001066 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001067 {
anthonyafa3dfc2012-03-03 11:31:30 +00001068 (void) SetImageOption(image_info,option+1, ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001069 draw_info->interline_spacing=StringToDouble(ArgOption("0"),
1070 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001071 break;
1072 }
anthonyafa3dfc2012-03-03 11:31:30 +00001073 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001074 {
anthonyfd706f92012-01-19 04:22:02 +00001075 /* SyncImageSettings() used to set per-image attribute. */
anthonyafa3dfc2012-03-03 11:31:30 +00001076 (void) SetImageOption(image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001077 break;
1078 }
anthonyafa3dfc2012-03-03 11:31:30 +00001079 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001080 {
anthonyafa3dfc2012-03-03 11:31:30 +00001081 (void) SetImageOption(image_info,option+1, ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001082 draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001083 break;
1084 }
1085 break;
1086 }
1087 case 'k':
1088 {
anthonyafa3dfc2012-03-03 11:31:30 +00001089 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001090 {
anthonyafa3dfc2012-03-03 11:31:30 +00001091 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001092 draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001093 break;
1094 }
1095 break;
1096 }
1097 case 'l':
1098 {
anthonyafa3dfc2012-03-03 11:31:30 +00001099 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001100 {
anthony72feaa62012-01-17 06:46:23 +00001101 /* only used for new images - not in SyncImageOptions() */
anthonyafa3dfc2012-03-03 11:31:30 +00001102 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001103 break;
1104 }
anthonyafa3dfc2012-03-03 11:31:30 +00001105 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001106 {
anthonydcf510d2011-10-30 13:51:40 +00001107 if (IfSetOption)
1108 (void) SetLogFormat(arg);
anthony805a2d42011-09-25 08:25:12 +00001109 break;
1110 }
anthonyafa3dfc2012-03-03 11:31:30 +00001111 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001112 {
anthony72feaa62012-01-17 06:46:23 +00001113 /* SyncImageSettings() used to set per-image attribute. */
anthonyafa3dfc2012-03-03 11:31:30 +00001114 (void) SetImageOption(image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001115 break;
1116 }
1117 break;
1118 }
1119 case 'm':
1120 {
anthonyafa3dfc2012-03-03 11:31:30 +00001121 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001122 {
anthony72feaa62012-01-17 06:46:23 +00001123 /* SyncImageSettings() used to set per-image attribute. */
anthonyafa3dfc2012-03-03 11:31:30 +00001124 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001125 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
1126 &image_info->matte_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001127 break;
1128 }
anthonyafa3dfc2012-03-03 11:31:30 +00001129 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001130 {
anthony31f1bf72012-01-30 12:37:22 +00001131 (void) SetImageInfoProgressMonitor(image_info, IfSetOption?
1132 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001133 break;
1134 }
anthonyafa3dfc2012-03-03 11:31:30 +00001135 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001136 {
anthony72feaa62012-01-17 06:46:23 +00001137 /* Setting (for some input coders)
1138 But also a special 'type' operator
1139 */
1140 image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001141 break;
1142 }
1143 break;
1144 }
1145 case 'o':
1146 {
anthonyafa3dfc2012-03-03 11:31:30 +00001147 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001148 {
anthony72feaa62012-01-17 06:46:23 +00001149 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001150 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001151 FUTURE: make set meta-data operator instead.
1152 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001153 */
anthonyafa3dfc2012-03-03 11:31:30 +00001154 (void) SetImageOption(image_info,option+1, ArgOption(NULL));
anthonydcf510d2011-10-30 13:51:40 +00001155 image_info->orientation=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001156 MagickOrientationOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001157 break;
1158 }
1159 }
1160 case 'p':
1161 {
anthonyafa3dfc2012-03-03 11:31:30 +00001162 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001163 {
anthony72feaa62012-01-17 06:46:23 +00001164 /* Only used for new images and image generators
1165 SyncImageSettings() used to set per-image attribute. ?????
1166 That last is WRONG!!!!
1167 */
anthony805a2d42011-09-25 08:25:12 +00001168 char
1169 *canonical_page,
1170 page[MaxTextExtent];
1171
1172 const char
1173 *image_option;
1174
1175 MagickStatusType
1176 flags;
1177
1178 RectangleInfo
1179 geometry;
1180
anthonydcf510d2011-10-30 13:51:40 +00001181 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001182 {
anthonyafa3dfc2012-03-03 11:31:30 +00001183 (void) DeleteImageOption(image_info,option+1);
anthony805a2d42011-09-25 08:25:12 +00001184 (void) CloneString(&image_info->page,(char *) NULL);
1185 break;
1186 }
1187 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1188 image_option=GetImageOption(image_info,"page");
1189 if (image_option != (const char *) NULL)
1190 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthonydcf510d2011-10-30 13:51:40 +00001191 canonical_page=GetPageGeometry(arg);
anthony805a2d42011-09-25 08:25:12 +00001192 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1193 canonical_page=DestroyString(canonical_page);
1194 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1195 (unsigned long) geometry.width,(unsigned long) geometry.height);
1196 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1197 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1198 (unsigned long) geometry.width,(unsigned long) geometry.height,
1199 (long) geometry.x,(long) geometry.y);
anthonyafa3dfc2012-03-03 11:31:30 +00001200 (void) SetImageOption(image_info,option+1,page);
anthony805a2d42011-09-25 08:25:12 +00001201 (void) CloneString(&image_info->page,page);
1202 break;
1203 }
anthonyafa3dfc2012-03-03 11:31:30 +00001204 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001205 {
anthony72feaa62012-01-17 06:46:23 +00001206 image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001207 break;
1208 }
anthonyafa3dfc2012-03-03 11:31:30 +00001209 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001210 {
anthony72feaa62012-01-17 06:46:23 +00001211 image_info->pointsize=draw_info->pointsize=
1212 StringToDouble(ArgOption("12"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001213 break;
1214 }
anthonyafa3dfc2012-03-03 11:31:30 +00001215 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001216 {
anthony72feaa62012-01-17 06:46:23 +00001217 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
anthony805a2d42011-09-25 08:25:12 +00001218 break;
1219 }
anthonydcf510d2011-10-30 13:51:40 +00001220 /* FUTURE: Only the 'preview' coder appears to use this
1221 * Depreciate the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001222 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001223 {
anthonydcf510d2011-10-30 13:51:40 +00001224 image_info->preview_type=UndefinedPreview;
1225 if (IfSetOption)
1226 image_info->preview_type=(PreviewType) ParseCommandOption(
1227 MagickPreviewOptions,MagickFalse,arg);
anthony805a2d42011-09-25 08:25:12 +00001228 break;
1229 }
anthonydcf510d2011-10-30 13:51:40 +00001230 */
anthony805a2d42011-09-25 08:25:12 +00001231 break;
1232 }
1233 case 'q':
1234 {
anthonyafa3dfc2012-03-03 11:31:30 +00001235 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001236 {
anthonyafa3dfc2012-03-03 11:31:30 +00001237 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
1238 image_info->quality=UNDEFINED_COMPRESSION_QUALITY;
anthony72feaa62012-01-17 06:46:23 +00001239 if (IfSetOption)
1240 image_info->quality=StringToUnsignedLong(arg);
anthony805a2d42011-09-25 08:25:12 +00001241 break;
1242 }
anthonyafa3dfc2012-03-03 11:31:30 +00001243 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001244 {
anthony72feaa62012-01-17 06:46:23 +00001245 /* Just a set direct in quantize_info */
anthonyafbaed72011-10-26 12:05:04 +00001246 quantize_info->colorspace=UndefinedColorspace;
1247 if (IfSetOption)
1248 quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
anthonydcf510d2011-10-30 13:51:40 +00001249 MagickColorspaceOptions,MagickFalse,arg);
anthonyafbaed72011-10-26 12:05:04 +00001250 break;
1251 }
anthonyafa3dfc2012-03-03 11:31:30 +00001252 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001253 {
anthonydcf510d2011-10-30 13:51:40 +00001254 /* FUTURE: if two -quiet is performed you can not do +quiet! */
anthony805a2d42011-09-25 08:25:12 +00001255 static WarningHandler
1256 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001257
anthonyafbaed72011-10-26 12:05:04 +00001258 WarningHandler
1259 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001260
anthonyafbaed72011-10-26 12:05:04 +00001261 if ( tmp != (WarningHandler) NULL)
1262 warning_handler = tmp; /* remember the old handler */
1263 if (!IfSetOption) /* set the old handler */
1264 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001265 break;
1266 }
1267 break;
1268 }
1269 case 'r':
1270 {
anthonyafa3dfc2012-03-03 11:31:30 +00001271 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001272 {
anthonydcf510d2011-10-30 13:51:40 +00001273 /* Image chromaticity X,Y NB: Y=X if Y not defined
1274 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001275 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001276 */
anthonyafa3dfc2012-03-03 11:31:30 +00001277 (void) SetImageOption(image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001278 break;
1279 }
anthonyafa3dfc2012-03-03 11:31:30 +00001280 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001281 {
1282 /* draw_info only setting */
anthonyafa3dfc2012-03-03 11:31:30 +00001283 draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001284 break;
1285 }
anthonyafa3dfc2012-03-03 11:31:30 +00001286 if (LocaleCompare("respect-parenthesis",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00001287 {
anthonyafa3dfc2012-03-03 11:31:30 +00001288 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony43f425d2012-02-26 12:58:58 +00001289 break;
1290 }
anthony805a2d42011-09-25 08:25:12 +00001291 break;
1292 }
1293 case 's':
1294 {
anthonyafa3dfc2012-03-03 11:31:30 +00001295 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001296 {
anthonyafbaed72011-10-26 12:05:04 +00001297 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony72feaa62012-01-17 06:46:23 +00001298 (void) CloneString(&image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001299 break;
1300 }
anthonyafa3dfc2012-03-03 11:31:30 +00001301 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001302 {
anthony72feaa62012-01-17 06:46:23 +00001303 /* SyncImageSettings() used to set per-image attribute.
1304 What ??? Why ????
1305 */
anthonyafa3dfc2012-03-03 11:31:30 +00001306 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001307 image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001308 break;
1309 }
anthonyafa3dfc2012-03-03 11:31:30 +00001310 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001311 {
anthonyafbaed72011-10-26 12:05:04 +00001312 SeedPseudoRandomGenerator(
anthonydcf510d2011-10-30 13:51:40 +00001313 IfSetOption ? (size_t) StringToUnsignedLong(arg)
anthonyafbaed72011-10-26 12:05:04 +00001314 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001315 break;
1316 }
anthonyafa3dfc2012-03-03 11:31:30 +00001317 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001318 {
anthonyafbaed72011-10-26 12:05:04 +00001319 /* FUTURE: string in image_info -- convert to Option ???
1320 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001321 */
anthony72feaa62012-01-17 06:46:23 +00001322 (void) CloneString(&image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001323 break;
1324 }
anthonyafa3dfc2012-03-03 11:31:30 +00001325 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001326 {
anthony72feaa62012-01-17 06:46:23 +00001327 draw_info->stretch=(StretchType) ParseCommandOption(
1328 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001329 break;
1330 }
anthonyafa3dfc2012-03-03 11:31:30 +00001331 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001332 {
anthonyafbaed72011-10-26 12:05:04 +00001333 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001334 UPDATE: ensure stroke color is not destroyed is a pattern
1335 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001336 */
1337 const char
anthony72feaa62012-01-17 06:46:23 +00001338 *value;
1339
1340 MagickBooleanType
1341 status;
anthonyafbaed72011-10-26 12:05:04 +00001342
1343 ExceptionInfo
1344 *sans;
1345
anthonyfd706f92012-01-19 04:22:02 +00001346 PixelInfo
1347 color;
1348
anthony72feaa62012-01-17 06:46:23 +00001349 value = ArgOption("none");
anthonyafa3dfc2012-03-03 11:31:30 +00001350 (void) SetImageOption(image_info,option+1,value);
anthony72feaa62012-01-17 06:46:23 +00001351 if (draw_info->stroke_pattern != (Image *) NULL)
1352 draw_info->stroke_pattern=DestroyImage(draw_info->stroke_pattern);
1353
1354 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001355 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +00001356 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001357 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001358
anthonyafbaed72011-10-26 12:05:04 +00001359 if (status == MagickFalse)
anthonyfd706f92012-01-19 04:22:02 +00001360 draw_info->stroke_pattern=GetImageCache(image_info,value,exception);
1361 else
1362 draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001363 break;
1364 }
anthonyafa3dfc2012-03-03 11:31:30 +00001365 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001366 {
anthonyafa3dfc2012-03-03 11:31:30 +00001367 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001368 draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1369 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001370 break;
1371 }
anthonyafa3dfc2012-03-03 11:31:30 +00001372 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001373 {
anthony72feaa62012-01-17 06:46:23 +00001374 draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1375 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001376 break;
1377 }
anthonyafa3dfc2012-03-03 11:31:30 +00001378 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001379 {
anthony72feaa62012-01-17 06:46:23 +00001380 image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001381 break;
1382 }
1383 break;
1384 }
1385 case 't':
1386 {
anthonyafa3dfc2012-03-03 11:31:30 +00001387 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001388 {
anthony72feaa62012-01-17 06:46:23 +00001389 /* SyncImageSettings() used to set per-image attribute. */
anthonyafa3dfc2012-03-03 11:31:30 +00001390 (void) SetImageOption(image_info,option+1,
anthonyafbaed72011-10-26 12:05:04 +00001391 IfSetOption ? "true" : "false");
anthony805a2d42011-09-25 08:25:12 +00001392 break;
1393 }
anthonyafa3dfc2012-03-03 11:31:30 +00001394 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001395 {
anthonyafbaed72011-10-26 12:05:04 +00001396 /* FUTURE: move image_info string to option splay-tree */
anthony72feaa62012-01-17 06:46:23 +00001397 (void) CloneString(&image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001398 break;
1399 }
anthonyafa3dfc2012-03-03 11:31:30 +00001400 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001401 {
anthony72feaa62012-01-17 06:46:23 +00001402 draw_info->fill_pattern=IfSetOption
1403 ?GetImageCache(image_info,arg,exception)
1404 :DestroyImage(draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001405 break;
1406 }
anthonyafa3dfc2012-03-03 11:31:30 +00001407 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001408 {
anthony72feaa62012-01-17 06:46:23 +00001409 /* SyncImageSettings() used to set per-image attribute. ??? */
anthonyafa3dfc2012-03-03 11:31:30 +00001410 (void) SetImageOption(image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001411 break;
1412 }
anthonyafa3dfc2012-03-03 11:31:30 +00001413 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001414 {
anthonyafbaed72011-10-26 12:05:04 +00001415 /* FUTURE: both image_info attribute & ImageOption in use!
1416 image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001417 SyncImageSettings() used to set per-image attribute.
1418
anthonyafbaed72011-10-26 12:05:04 +00001419 Note that +transparent-color, means fall-back to image
1420 attribute so ImageOption is deleted, not set to a default.
1421 */
anthonyafa3dfc2012-03-03 11:31:30 +00001422 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001423 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1424 &image_info->transparent_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001425 break;
1426 }
anthonyafa3dfc2012-03-03 11:31:30 +00001427 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001428 {
anthonyafa3dfc2012-03-03 11:31:30 +00001429 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony31f1bf72012-01-30 12:37:22 +00001430 quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1431 break;
1432 }
anthonyafa3dfc2012-03-03 11:31:30 +00001433 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001434 {
anthony72feaa62012-01-17 06:46:23 +00001435 /* SyncImageSettings() used to set per-image attribute. */
anthonyafa3dfc2012-03-03 11:31:30 +00001436 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001437 image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1438 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001439 break;
1440 }
1441 break;
1442 }
1443 case 'u':
1444 {
anthonyafa3dfc2012-03-03 11:31:30 +00001445 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001446 {
anthonyafa3dfc2012-03-03 11:31:30 +00001447 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001448 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1449 &draw_info->undercolor,exception);
anthony805a2d42011-09-25 08:25:12 +00001450 break;
1451 }
anthonyafa3dfc2012-03-03 11:31:30 +00001452 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001453 {
anthony72feaa62012-01-17 06:46:23 +00001454 /* SyncImageSettings() used to set per-image attribute.
1455 Should this effect draw_info X and Y resolution?
1456 FUTURE: this probably should be part of the density setting
1457 */
anthonyafa3dfc2012-03-03 11:31:30 +00001458 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001459 image_info->units=(ResolutionType) ParseCommandOption(
1460 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001461 break;
1462 }
1463 break;
1464 }
1465 case 'v':
1466 {
anthonyafa3dfc2012-03-03 11:31:30 +00001467 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001468 {
anthonyab3a50c2011-10-27 11:48:57 +00001469 /* FUTURE: Also an image artifact, set in Simple Operators.
1470 But artifact is only used in verbose output.
1471 */
anthonyafa3dfc2012-03-03 11:31:30 +00001472 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001473 image_info->verbose= ArgBoolean;
anthonyab3a50c2011-10-27 11:48:57 +00001474 image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001475 break;
1476 }
anthonyafa3dfc2012-03-03 11:31:30 +00001477 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001478 {
anthony72feaa62012-01-17 06:46:23 +00001479 /* FUTURE: Convert from image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001480 Only used by coder FPX
1481 */
anthony72feaa62012-01-17 06:46:23 +00001482 (void) CloneString(&image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001483 break;
1484 }
anthonyafa3dfc2012-03-03 11:31:30 +00001485 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001486 {
anthonyfd706f92012-01-19 04:22:02 +00001487 /* SyncImageSettings() used to set per-image attribute.
1488 This is VERY deep in the image caching structure.
1489 */
anthonyafa3dfc2012-03-03 11:31:30 +00001490 (void) SetImageOption(image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001491 break;
1492 }
1493 break;
1494 }
1495 case 'w':
1496 {
anthonyafa3dfc2012-03-03 11:31:30 +00001497 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001498 {
anthony72feaa62012-01-17 06:46:23 +00001499 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001500 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001501 */
anthony72feaa62012-01-17 06:46:23 +00001502 if (!IfSetOption)
1503 break;
anthonydcf510d2011-10-30 13:51:40 +00001504 draw_info->weight=StringToUnsignedLong(arg);
1505 if (LocaleCompare(arg,"all") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001506 draw_info->weight=0;
anthonydcf510d2011-10-30 13:51:40 +00001507 if (LocaleCompare(arg,"bold") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001508 draw_info->weight=700;
anthonydcf510d2011-10-30 13:51:40 +00001509 if (LocaleCompare(arg,"bolder") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001510 if (draw_info->weight <= 800)
1511 draw_info->weight+=100;
anthonydcf510d2011-10-30 13:51:40 +00001512 if (LocaleCompare(arg,"lighter") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001513 if (draw_info->weight >= 100)
1514 draw_info->weight-=100;
anthonydcf510d2011-10-30 13:51:40 +00001515 if (LocaleCompare(arg,"normal") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001516 draw_info->weight=400;
1517 break;
1518 }
anthonyafa3dfc2012-03-03 11:31:30 +00001519 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001520 {
anthony72feaa62012-01-17 06:46:23 +00001521 /* Used as a image chromaticity setting
1522 SyncImageSettings() used to set per-image attribute.
1523 */
anthonyafa3dfc2012-03-03 11:31:30 +00001524 (void) SetImageOption(image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001525 break;
1526 }
1527 break;
1528 }
1529 default:
1530 break;
1531 }
anthonyfd706f92012-01-19 04:22:02 +00001532#undef image_info
anthony43f425d2012-02-26 12:58:58 +00001533#undef exception
anthonyfd706f92012-01-19 04:22:02 +00001534#undef draw_info
1535#undef quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001536#undef IfSetOption
1537#undef ArgOption
1538#undef ArgBoolean
1539
anthony31f1bf72012-01-30 12:37:22 +00001540 return;
anthony805a2d42011-09-25 08:25:12 +00001541}
1542
1543/*
1544%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1545% %
1546% %
1547% %
anthony43f425d2012-02-26 12:58:58 +00001548+ 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 +00001549% %
1550% %
1551% %
1552%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1553%
anthony31f1bf72012-01-30 12:37:22 +00001554% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001555% the images in the CLI wand, with the settings that was previously saved in
1556% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001557%
1558% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001559% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001560%
anthonyd1447672012-01-19 05:33:53 +00001561% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001562%
anthony43f425d2012-02-26 12:58:58 +00001563% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001564% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001565%
1566% A description of each parameter follows:
1567%
anthony43f425d2012-02-26 12:58:58 +00001568% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001569%
anthonyfd706f92012-01-19 04:22:02 +00001570% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001571%
anthonyfd706f92012-01-19 04:22:02 +00001572% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001573%
anthony31f1bf72012-01-30 12:37:22 +00001574% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001575%
anthony31f1bf72012-01-30 12:37:22 +00001576% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001577%
anthonyafa3dfc2012-03-03 11:31:30 +00001578% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1579% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1580% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001581%
1582% Or for handling command line arguments EG: +/-option ["arg"]
anthonydcf510d2011-10-30 13:51:40 +00001583%
anthony43f425d2012-02-26 12:58:58 +00001584% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001585% argc,argv
1586% i=index in argv
1587%
anthony2052d272012-02-28 12:48:29 +00001588% option_info = GetCommandOptionInfo(argv[i]);
1589% count=option_info->type;
1590% option_type=option_info->flags;
1591%
1592% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001593% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001594% count>=1 ? argv[i+1] : (char *)NULL,
1595% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001596% i += count+1;
1597%
anthony805a2d42011-09-25 08:25:12 +00001598*/
anthony31f1bf72012-01-30 12:37:22 +00001599
1600/*
1601 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001602 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001603
1604 The image in the list may be modified in three different ways...
1605 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1606 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1607 * one image replace by a list of images (-separate and -crop only!)
1608
anthonyafa3dfc2012-03-03 11:31:30 +00001609 In each case the result replaces the single original image in the list, as
1610 well as the pointer to the modified image (last image added if replaced by a
1611 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001612
1613 As the image pointed to may be replaced, the first image in the list may
1614 also change. GetFirstImageInList() should be used by caller if they wish
1615 return the Image pointer to the first image in list.
1616*/
anthony43f425d2012-02-26 12:58:58 +00001617static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001618 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001619{
1620 Image *
1621 new_image;
1622
anthony805a2d42011-09-25 08:25:12 +00001623 GeometryInfo
1624 geometry_info;
1625
1626 RectangleInfo
1627 geometry;
1628
1629 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001630 flags;
1631
anthony43f425d2012-02-26 12:58:58 +00001632#define image_info (cli_wand->wand.image_info)
1633#define image (cli_wand->wand.images)
1634#define exception (cli_wand->wand.exception)
1635#define draw_info (cli_wand->draw_info)
1636#define quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001637#define IfNormalOp (*option=='-')
1638#define IfPlusOp (*option!='-')
1639#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
1640#define plus_alt_op (IfNormalOp?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001641
anthony43f425d2012-02-26 12:58:58 +00001642 assert(cli_wand != (MagickCLI *) NULL);
1643 assert(cli_wand->signature == WandSignature);
1644 assert(cli_wand->wand.signature == WandSignature);
1645 assert(image != (Image *) NULL); /* an image must be present */
1646 if (cli_wand->wand.debug != MagickFalse)
1647 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001648
anthony805a2d42011-09-25 08:25:12 +00001649 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001650
anthonydcf510d2011-10-30 13:51:40 +00001651 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001652
anthonyfd706f92012-01-19 04:22:02 +00001653 /* FUTURE: We may need somthing a little more optimized than this!
1654 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1655 */
anthony31f1bf72012-01-30 12:37:22 +00001656 (void) SyncImageSettings(image_info,image,exception);
anthonydcf510d2011-10-30 13:51:40 +00001657
anthonyafa3dfc2012-03-03 11:31:30 +00001658 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001659 {
1660 case 'a':
1661 {
anthonyafa3dfc2012-03-03 11:31:30 +00001662 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001663 {
anthonyfd706f92012-01-19 04:22:02 +00001664 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001665 if ((flags & SigmaValue) == 0)
1666 geometry_info.sigma=1.0;
1667 if ((flags & XiValue) == 0)
1668 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001669 new_image=AdaptiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001670 geometry_info.sigma,geometry_info.xi,exception);
1671 break;
1672 }
anthonyafa3dfc2012-03-03 11:31:30 +00001673 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001674 {
anthony31f1bf72012-01-30 12:37:22 +00001675 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
1676 new_image=AdaptiveResizeImage(image,geometry.width,geometry.height,
anthonyfd706f92012-01-19 04:22:02 +00001677 exception);
anthony805a2d42011-09-25 08:25:12 +00001678 break;
1679 }
anthonyafa3dfc2012-03-03 11:31:30 +00001680 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001681 {
anthonyfd706f92012-01-19 04:22:02 +00001682 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001683 if ((flags & SigmaValue) == 0)
1684 geometry_info.sigma=1.0;
1685 if ((flags & XiValue) == 0)
1686 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001687 new_image=AdaptiveSharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001688 geometry_info.sigma,geometry_info.xi,exception);
1689 break;
1690 }
anthonyafa3dfc2012-03-03 11:31:30 +00001691 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001692 {
1693 AlphaChannelType
1694 alpha_type;
1695
anthony805a2d42011-09-25 08:25:12 +00001696 alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
anthonyfd706f92012-01-19 04:22:02 +00001697 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00001698 (void) SetImageAlphaChannel(image,alpha_type,exception);
anthony805a2d42011-09-25 08:25:12 +00001699 break;
1700 }
anthonyafa3dfc2012-03-03 11:31:30 +00001701 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001702 {
1703 char
1704 *text,
1705 geometry[MaxTextExtent];
1706
anthony805a2d42011-09-25 08:25:12 +00001707 SetGeometryInfo(&geometry_info);
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=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00001711 text=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00001712 exception);
1713 if (text == (char *) NULL)
1714 break;
1715 (void) CloneString(&draw_info->text,text);
1716 text=DestroyString(text);
1717 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1718 geometry_info.xi,geometry_info.psi);
1719 (void) CloneString(&draw_info->geometry,geometry);
1720 draw_info->affine.sx=cos(DegreesToRadians(
1721 fmod(geometry_info.rho,360.0)));
1722 draw_info->affine.rx=sin(DegreesToRadians(
1723 fmod(geometry_info.rho,360.0)));
1724 draw_info->affine.ry=(-sin(DegreesToRadians(
1725 fmod(geometry_info.sigma,360.0))));
1726 draw_info->affine.sy=cos(DegreesToRadians(
1727 fmod(geometry_info.sigma,360.0)));
anthony31f1bf72012-01-30 12:37:22 +00001728 (void) AnnotateImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00001729 GetAffineMatrix(&draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001730 break;
1731 }
anthonyafa3dfc2012-03-03 11:31:30 +00001732 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001733 {
anthony31f1bf72012-01-30 12:37:22 +00001734 (void) AutoGammaImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001735 break;
1736 }
anthonyafa3dfc2012-03-03 11:31:30 +00001737 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001738 {
anthony31f1bf72012-01-30 12:37:22 +00001739 (void) AutoLevelImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001740 break;
1741 }
anthonyafa3dfc2012-03-03 11:31:30 +00001742 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001743 {
anthonyafa3dfc2012-03-03 11:31:30 +00001744 /* This should probbaly be a MagickCore function */
anthony31f1bf72012-01-30 12:37:22 +00001745 switch (image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001746 {
1747 case TopRightOrientation:
1748 {
anthony31f1bf72012-01-30 12:37:22 +00001749 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001750 break;
1751 }
1752 case BottomRightOrientation:
1753 {
anthony31f1bf72012-01-30 12:37:22 +00001754 new_image=RotateImage(image,180.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001755 break;
1756 }
1757 case BottomLeftOrientation:
1758 {
anthony31f1bf72012-01-30 12:37:22 +00001759 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001760 break;
1761 }
1762 case LeftTopOrientation:
1763 {
anthony31f1bf72012-01-30 12:37:22 +00001764 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001765 break;
1766 }
1767 case RightTopOrientation:
1768 {
anthony31f1bf72012-01-30 12:37:22 +00001769 new_image=RotateImage(image,90.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001770 break;
1771 }
1772 case RightBottomOrientation:
1773 {
anthony31f1bf72012-01-30 12:37:22 +00001774 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001775 break;
1776 }
1777 case LeftBottomOrientation:
1778 {
anthony31f1bf72012-01-30 12:37:22 +00001779 new_image=RotateImage(image,270.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001780 break;
1781 }
1782 default:
1783 break;
1784 }
1785 if (new_image != (Image *) NULL)
1786 new_image->orientation=TopLeftOrientation;
1787 break;
1788 }
1789 break;
1790 }
1791 case 'b':
1792 {
anthonyafa3dfc2012-03-03 11:31:30 +00001793 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001794 {
anthony31f1bf72012-01-30 12:37:22 +00001795 (void) BlackThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001796 break;
1797 }
anthonyafa3dfc2012-03-03 11:31:30 +00001798 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001799 {
anthony805a2d42011-09-25 08:25:12 +00001800 geometry_info.rho=1.5;
anthonyafa3dfc2012-03-03 11:31:30 +00001801 if (IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001802 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00001803 new_image=BlueShiftImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00001804 break;
1805 }
anthonyafa3dfc2012-03-03 11:31:30 +00001806 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001807 {
anthony74b1cfc2011-10-06 12:44:16 +00001808 /* FUTURE: use of "bias" in a blur is non-sensible */
anthonyfd706f92012-01-19 04:22:02 +00001809 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001810 if ((flags & SigmaValue) == 0)
1811 geometry_info.sigma=1.0;
1812 if ((flags & XiValue) == 0)
1813 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001814 new_image=BlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001815 geometry_info.sigma,geometry_info.xi,exception);
1816 break;
1817 }
anthonyafa3dfc2012-03-03 11:31:30 +00001818 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001819 {
anthony31f1bf72012-01-30 12:37:22 +00001820 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001821 compose;
1822
1823 const char*
anthony5f867ae2011-10-09 10:28:34 +00001824 value;
1825
1826 value=GetImageOption(image_info,"compose");
1827 if (value != (const char *) NULL)
1828 compose=(CompositeOperator) ParseCommandOption(
1829 MagickComposeOptions,MagickFalse,value);
1830 else
1831 compose=OverCompositeOp; /* use Over not image->compose */
1832
anthony31f1bf72012-01-30 12:37:22 +00001833 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001834 if ((flags & SigmaValue) == 0)
1835 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00001836 new_image=BorderImage(image,&geometry,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00001837 break;
1838 }
anthonyafa3dfc2012-03-03 11:31:30 +00001839 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001840 {
1841 double
1842 brightness,
1843 contrast;
1844
1845 GeometryInfo
1846 geometry_info;
1847
1848 MagickStatusType
1849 flags;
1850
anthonyfd706f92012-01-19 04:22:02 +00001851 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001852 brightness=geometry_info.rho;
1853 contrast=0.0;
1854 if ((flags & SigmaValue) != 0)
1855 contrast=geometry_info.sigma;
anthony31f1bf72012-01-30 12:37:22 +00001856 (void) BrightnessContrastImage(image,brightness,contrast,
anthony805a2d42011-09-25 08:25:12 +00001857 exception);
anthony805a2d42011-09-25 08:25:12 +00001858 break;
1859 }
1860 break;
1861 }
1862 case 'c':
1863 {
anthonyafa3dfc2012-03-03 11:31:30 +00001864 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001865 {
1866 char
1867 *color_correction_collection;
1868
1869 /*
1870 Color correct with a color decision list.
1871 */
anthonyfd706f92012-01-19 04:22:02 +00001872 color_correction_collection=FileToString(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00001873 if (color_correction_collection == (char *) NULL)
1874 break;
anthony31f1bf72012-01-30 12:37:22 +00001875 (void) ColorDecisionListImage(image,color_correction_collection,
anthony805a2d42011-09-25 08:25:12 +00001876 exception);
anthony805a2d42011-09-25 08:25:12 +00001877 break;
1878 }
anthonyafa3dfc2012-03-03 11:31:30 +00001879 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001880 {
anthonyfd706f92012-01-19 04:22:02 +00001881 /* The "channel" setting has already been set
anthonyd1447672012-01-19 05:33:53 +00001882 FUTURE: This probably should be part of WandSettingOptionInfo()
anthonyfd706f92012-01-19 04:22:02 +00001883 or SyncImageSettings().
1884 */
anthony31f1bf72012-01-30 12:37:22 +00001885 SetPixelChannelMapMask(image,image_info->channel);
anthony805a2d42011-09-25 08:25:12 +00001886 break;
1887 }
anthonyafa3dfc2012-03-03 11:31:30 +00001888 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001889 {
anthonyfd706f92012-01-19 04:22:02 +00001890 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001891 if ((flags & SigmaValue) == 0)
1892 geometry_info.sigma=1.0;
1893 if ((flags & XiValue) == 0)
1894 geometry_info.xi=1.0;
anthony31f1bf72012-01-30 12:37:22 +00001895 new_image=CharcoalImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001896 geometry_info.sigma,geometry_info.xi,exception);
1897 break;
1898 }
anthonyafa3dfc2012-03-03 11:31:30 +00001899 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001900 {
anthony31f1bf72012-01-30 12:37:22 +00001901 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
1902 new_image=ChopImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001903 break;
1904 }
anthonyafa3dfc2012-03-03 11:31:30 +00001905 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001906 {
anthony31f1bf72012-01-30 12:37:22 +00001907 (void) ClampImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001908 break;
1909 }
anthonyafa3dfc2012-03-03 11:31:30 +00001910 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001911 {
anthonyafa3dfc2012-03-03 11:31:30 +00001912 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00001913 (void) ClipImage(image,exception);
anthony43f425d2012-02-26 12:58:58 +00001914 else /* "+mask" remove the write mask */
anthony31f1bf72012-01-30 12:37:22 +00001915 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00001916 break;
1917 }
anthonyafa3dfc2012-03-03 11:31:30 +00001918 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001919 {
1920 CacheView
1921 *mask_view;
1922
1923 Image
1924 *mask_image;
1925
1926 register Quantum
1927 *restrict q;
1928
1929 register ssize_t
1930 x;
1931
1932 ssize_t
1933 y;
1934
anthonyafa3dfc2012-03-03 11:31:30 +00001935 if (IfPlusOp) {
1936 /* "+clip-mask" Remove the write mask */
1937 (void) SetImageMask(image,(Image *) NULL,exception);
1938 break;
1939 }
anthonyfd706f92012-01-19 04:22:02 +00001940 mask_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001941 if (mask_image == (Image *) NULL)
1942 break;
anthonyfd706f92012-01-19 04:22:02 +00001943 if (SetImageStorageClass(mask_image,DirectClass,exception)
1944 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001945 break;
anthony43f425d2012-02-26 12:58:58 +00001946 /* Create a write mask from cli_wandp-mask image */
anthonyfd706f92012-01-19 04:22:02 +00001947 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00001948 mask_view=AcquireCacheView(mask_image);
1949 for (y=0; y < (ssize_t) mask_image->rows; y++)
1950 {
1951 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1952 exception);
1953 if (q == (Quantum *) NULL)
1954 break;
1955 for (x=0; x < (ssize_t) mask_image->columns; x++)
1956 {
1957 if (mask_image->matte == MagickFalse)
1958 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1959 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1960 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1961 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1962 q+=GetPixelChannels(mask_image);
1963 }
1964 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1965 break;
1966 }
anthonyfd706f92012-01-19 04:22:02 +00001967 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001968 mask_view=DestroyCacheView(mask_view);
1969 mask_image->matte=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00001970 (void) SetImageMask(image,mask_image,exception);
anthony805a2d42011-09-25 08:25:12 +00001971 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00001972 break;
1973 }
anthonyafa3dfc2012-03-03 11:31:30 +00001974 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001975 {
anthonyafa3dfc2012-03-03 11:31:30 +00001976 (void) ClipImagePath(image,arg1,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00001977 break;
1978 }
anthonyafa3dfc2012-03-03 11:31:30 +00001979 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001980 {
anthony31f1bf72012-01-30 12:37:22 +00001981 new_image=ColorizeImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00001982 break;
1983 }
anthonyafa3dfc2012-03-03 11:31:30 +00001984 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001985 {
1986 KernelInfo
1987 *kernel;
1988
anthonyfd706f92012-01-19 04:22:02 +00001989 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00001990 if (kernel == (KernelInfo *) NULL)
1991 break;
anthony31f1bf72012-01-30 12:37:22 +00001992 new_image=ColorMatrixImage(image,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00001993 kernel=DestroyKernelInfo(kernel);
1994 break;
1995 }
anthonyafa3dfc2012-03-03 11:31:30 +00001996 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001997 {
anthonyfd706f92012-01-19 04:22:02 +00001998 /* Reduce the number of colors in the image.
1999 FUTURE: also provide 'plus version with image 'color counts'
2000 */
2001 quantize_info->number_colors=StringToUnsignedLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00002002 if (quantize_info->number_colors == 0)
2003 break;
anthony31f1bf72012-01-30 12:37:22 +00002004 if ((image->storage_class == DirectClass) ||
2005 image->colors > quantize_info->number_colors)
2006 (void) QuantizeImage(quantize_info,image,exception);
anthony805a2d42011-09-25 08:25:12 +00002007 else
anthony31f1bf72012-01-30 12:37:22 +00002008 (void) CompressImageColormap(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002009 break;
2010 }
anthonyafa3dfc2012-03-03 11:31:30 +00002011 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002012 {
anthony31f1bf72012-01-30 12:37:22 +00002013 /* WARNING: this is both a image_info setting (already done)
2014 and a operator to change image colorspace.
2015
2016 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002017 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002018
anthonyd2cdc862011-10-07 14:07:17 +00002019 Note that +colorspace sets "undefined" or no effect on
2020 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002021 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002022 */
anthony31f1bf72012-01-30 12:37:22 +00002023 (void) TransformImageColorspace(image,
anthonyafa3dfc2012-03-03 11:31:30 +00002024 IfNormalOp ? image_info->colorspace : RGBColorspace,
anthony6613bf32011-10-15 07:24:44 +00002025 exception);
anthony805a2d42011-09-25 08:25:12 +00002026 break;
2027 }
anthonyafa3dfc2012-03-03 11:31:30 +00002028 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002029 {
anthonyafa3dfc2012-03-03 11:31:30 +00002030 (void) ContrastImage(image,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002031 break;
2032 }
anthonyafa3dfc2012-03-03 11:31:30 +00002033 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002034 {
2035 double
2036 black_point,
2037 white_point;
2038
2039 MagickStatusType
2040 flags;
2041
anthonyfd706f92012-01-19 04:22:02 +00002042 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002043 black_point=geometry_info.rho;
2044 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2045 black_point;
2046 if ((flags & PercentValue) != 0)
2047 {
anthony31f1bf72012-01-30 12:37:22 +00002048 black_point*=(double) image->columns*image->rows/100.0;
2049 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002050 }
anthony31f1bf72012-01-30 12:37:22 +00002051 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00002052 white_point;
anthony31f1bf72012-01-30 12:37:22 +00002053 (void) ContrastStretchImage(image,black_point,white_point,
anthony805a2d42011-09-25 08:25:12 +00002054 exception);
anthony805a2d42011-09-25 08:25:12 +00002055 break;
2056 }
anthonyafa3dfc2012-03-03 11:31:30 +00002057 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002058 {
2059 KernelInfo
2060 *kernel_info;
2061
anthonyfd706f92012-01-19 04:22:02 +00002062 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002063 if (kernel_info == (KernelInfo *) NULL)
2064 break;
anthony31f1bf72012-01-30 12:37:22 +00002065 kernel_info->bias=image->bias;
2066 new_image=ConvolveImage(image,kernel_info,exception);
anthony805a2d42011-09-25 08:25:12 +00002067 kernel_info=DestroyKernelInfo(kernel_info);
2068 break;
2069 }
anthonyafa3dfc2012-03-03 11:31:30 +00002070 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002071 {
anthony31f1bf72012-01-30 12:37:22 +00002072 /* WARNING: This can generate multiple images! */
2073 new_image=CropImageToTiles(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002074 break;
2075 }
anthonyafa3dfc2012-03-03 11:31:30 +00002076 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002077 {
anthony31f1bf72012-01-30 12:37:22 +00002078 (void) CycleColormapImage(image,(ssize_t) StringToLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00002079 exception);
2080 break;
2081 }
2082 break;
2083 }
2084 case 'd':
2085 {
anthonyafa3dfc2012-03-03 11:31:30 +00002086 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002087 {
2088 StringInfo
2089 *passkey;
2090
anthonyfd706f92012-01-19 04:22:02 +00002091 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00002092 if (passkey != (StringInfo *) NULL)
2093 {
anthony31f1bf72012-01-30 12:37:22 +00002094 (void) PasskeyDecipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00002095 passkey=DestroyStringInfo(passkey);
2096 }
2097 break;
2098 }
anthonyafa3dfc2012-03-03 11:31:30 +00002099 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002100 {
anthonydcf510d2011-10-30 13:51:40 +00002101 /* The image_info->depth setting has already been set
2102 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002103
anthonydcf510d2011-10-30 13:51:40 +00002104 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2105 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002106
anthonyfd706f92012-01-19 04:22:02 +00002107 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002108 */
anthony31f1bf72012-01-30 12:37:22 +00002109 (void) SetImageDepth(image,image_info->depth,exception);
anthony805a2d42011-09-25 08:25:12 +00002110 break;
2111 }
anthonyafa3dfc2012-03-03 11:31:30 +00002112 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002113 {
2114 double
2115 threshold;
2116
anthonyafa3dfc2012-03-03 11:31:30 +00002117 if (IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00002118 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyafa3dfc2012-03-03 11:31:30 +00002119 else
2120 threshold=40.0*QuantumRange/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002121 new_image=DeskewImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00002122 break;
2123 }
anthonyafa3dfc2012-03-03 11:31:30 +00002124 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002125 {
anthony31f1bf72012-01-30 12:37:22 +00002126 new_image=DespeckleImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002127 break;
2128 }
anthonyafa3dfc2012-03-03 11:31:30 +00002129 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002130 {
2131 char
2132 *args,
2133 token[MaxTextExtent];
2134
2135 const char
2136 *p;
2137
2138 DistortImageMethod
2139 method;
2140
2141 double
2142 *arguments;
2143
2144 register ssize_t
2145 x;
2146
2147 size_t
2148 number_arguments;
2149
anthony805a2d42011-09-25 08:25:12 +00002150 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
anthonyfd706f92012-01-19 04:22:02 +00002151 MagickFalse,arg1);
anthony80c37752012-01-16 01:03:11 +00002152 if (method == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002153 {
anthony80c37752012-01-16 01:03:11 +00002154 double
2155 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002156 /* Special Case - Argument is actually a resize geometry!
2157 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002158 ** FUTURE: make a separate special resize operator
anthony805a2d42011-09-25 08:25:12 +00002159 */
anthony31f1bf72012-01-30 12:37:22 +00002160 (void) ParseRegionGeometry(image,arg2,&geometry,
anthony80c37752012-01-16 01:03:11 +00002161 exception);
2162 resize_args[0]=(double) geometry.width;
2163 resize_args[1]=(double) geometry.height;
anthony31f1bf72012-01-30 12:37:22 +00002164 new_image=DistortImage(image,method,(size_t)2,
anthony80c37752012-01-16 01:03:11 +00002165 resize_args,MagickTrue,exception);
anthony805a2d42011-09-25 08:25:12 +00002166 break;
2167 }
anthonyfd706f92012-01-19 04:22:02 +00002168 /* handle percent arguments */
anthony31f1bf72012-01-30 12:37:22 +00002169 args=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002170 exception);
2171 if (args == (char *) NULL)
2172 break;
anthonyfd706f92012-01-19 04:22:02 +00002173 /* convert arguments into an array of doubles
2174 FUTURE: make this a separate function.
2175 Also make use of new 'sentinal' feature to avoid need for
2176 tokenization.
2177 */
anthony805a2d42011-09-25 08:25:12 +00002178 p=(char *) args;
2179 for (x=0; *p != '\0'; x++)
2180 {
2181 GetMagickToken(p,&p,token);
2182 if (*token == ',')
2183 GetMagickToken(p,&p,token);
2184 }
2185 number_arguments=(size_t) x;
2186 arguments=(double *) AcquireQuantumMemory(number_arguments,
2187 sizeof(*arguments));
2188 if (arguments == (double *) NULL)
2189 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002190 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002191 (void) ResetMagickMemory(arguments,0,number_arguments*
2192 sizeof(*arguments));
2193 p=(char *) args;
2194 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2195 {
2196 GetMagickToken(p,&p,token);
2197 if (*token == ',')
2198 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002199 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002200 }
2201 args=DestroyString(args);
anthony31f1bf72012-01-30 12:37:22 +00002202 new_image=DistortImage(image,method,number_arguments,arguments,
anthonyfd706f92012-01-19 04:22:02 +00002203 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002204 arguments=(double *) RelinquishMagickMemory(arguments);
2205 break;
2206 }
anthonyafa3dfc2012-03-03 11:31:30 +00002207 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002208 {
anthonyfd706f92012-01-19 04:22:02 +00002209 (void) CloneString(&draw_info->primitive,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002210 (void) DrawImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00002211 (void) CloneString(&draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002212 break;
2213 }
2214 break;
2215 }
2216 case 'e':
2217 {
anthonyafa3dfc2012-03-03 11:31:30 +00002218 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002219 {
anthonyfd706f92012-01-19 04:22:02 +00002220 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002221 if ((flags & SigmaValue) == 0)
2222 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002223 new_image=EdgeImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002224 geometry_info.sigma,exception);
2225 break;
2226 }
anthonyafa3dfc2012-03-03 11:31:30 +00002227 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002228 {
anthonyfd706f92012-01-19 04:22:02 +00002229 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002230 if ((flags & SigmaValue) == 0)
2231 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002232 new_image=EmbossImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002233 geometry_info.sigma,exception);
2234 break;
2235 }
anthonyafa3dfc2012-03-03 11:31:30 +00002236 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002237 {
2238 StringInfo
2239 *passkey;
2240
anthonyfd706f92012-01-19 04:22:02 +00002241 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00002242 if (passkey != (StringInfo *) NULL)
2243 {
anthony31f1bf72012-01-30 12:37:22 +00002244 (void) PasskeyEncipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00002245 passkey=DestroyStringInfo(passkey);
2246 }
2247 break;
2248 }
anthonyafa3dfc2012-03-03 11:31:30 +00002249 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002250 {
anthony31f1bf72012-01-30 12:37:22 +00002251 new_image=EnhanceImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002252 break;
2253 }
anthonyafa3dfc2012-03-03 11:31:30 +00002254 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002255 {
anthony31f1bf72012-01-30 12:37:22 +00002256 (void) EqualizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002257 break;
2258 }
anthonyafa3dfc2012-03-03 11:31:30 +00002259 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002260 {
2261 double
2262 constant;
2263
2264 MagickEvaluateOperator
2265 op;
2266
anthony805a2d42011-09-25 08:25:12 +00002267 op=(MagickEvaluateOperator) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00002268 MagickEvaluateOptions,MagickFalse,arg1);
2269 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002270 (void) EvaluateImage(image,op,constant,exception);
anthony805a2d42011-09-25 08:25:12 +00002271 break;
2272 }
anthonyafa3dfc2012-03-03 11:31:30 +00002273 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002274 {
anthony31f1bf72012-01-30 12:37:22 +00002275 flags=ParseGravityGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002276 if (geometry.width == 0)
anthony31f1bf72012-01-30 12:37:22 +00002277 geometry.width=image->columns;
anthony805a2d42011-09-25 08:25:12 +00002278 if (geometry.height == 0)
anthony31f1bf72012-01-30 12:37:22 +00002279 geometry.height=image->rows;
2280 new_image=ExtentImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002281 break;
2282 }
2283 break;
2284 }
2285 case 'f':
2286 {
anthonyafa3dfc2012-03-03 11:31:30 +00002287 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002288 {
anthony31f1bf72012-01-30 12:37:22 +00002289 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002290 if (IfPlusOp) {
anthony31f1bf72012-01-30 12:37:22 +00002291 (void) DeleteImageArtifact(image,"identify:features");
2292 break;
2293 }
2294 (void) SetImageArtifact(image,"identify:features","true");
2295 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002296 break;
2297 }
anthonyafa3dfc2012-03-03 11:31:30 +00002298 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002299 {
anthony31f1bf72012-01-30 12:37:22 +00002300 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002301 break;
2302 }
anthonyafa3dfc2012-03-03 11:31:30 +00002303 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002304 {
anthony31f1bf72012-01-30 12:37:22 +00002305 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002306 break;
2307 }
anthonyafa3dfc2012-03-03 11:31:30 +00002308 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002309 {
2310 PixelInfo
2311 target;
2312
anthony31f1bf72012-01-30 12:37:22 +00002313 (void) ParsePageGeometry(image,arg1,&geometry,exception);
anthonyfd706f92012-01-19 04:22:02 +00002314 (void) QueryColorCompliance(arg2,AllCompliance,&target,exception);
anthony31f1bf72012-01-30 12:37:22 +00002315 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
anthonyfd706f92012-01-19 04:22:02 +00002316 geometry.y,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002317 break;
2318 }
anthonyafa3dfc2012-03-03 11:31:30 +00002319 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002320 {
2321 FrameInfo
2322 frame_info;
2323
anthony31f1bf72012-01-30 12:37:22 +00002324 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002325 compose;
2326
2327 const char*
2328 value;
2329
2330 value=GetImageOption(image_info,"compose");
2331 if (value != (const char *) NULL)
2332 compose=(CompositeOperator) ParseCommandOption(
2333 MagickComposeOptions,MagickFalse,value);
2334 else
2335 compose=OverCompositeOp; /* use Over not image->compose */
2336
anthony31f1bf72012-01-30 12:37:22 +00002337 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002338 frame_info.width=geometry.width;
2339 frame_info.height=geometry.height;
2340 if ((flags & HeightValue) == 0)
2341 frame_info.height=geometry.width;
2342 frame_info.outer_bevel=geometry.x;
2343 frame_info.inner_bevel=geometry.y;
2344 frame_info.x=(ssize_t) frame_info.width;
2345 frame_info.y=(ssize_t) frame_info.height;
anthony31f1bf72012-01-30 12:37:22 +00002346 frame_info.width=image->columns+2*frame_info.width;
2347 frame_info.height=image->rows+2*frame_info.height;
2348 new_image=FrameImage(image,&frame_info,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00002349 break;
2350 }
anthonyafa3dfc2012-03-03 11:31:30 +00002351 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002352 {
2353 char
2354 *arguments,
2355 token[MaxTextExtent];
2356
2357 const char
2358 *p;
2359
2360 double
2361 *parameters;
2362
2363 MagickFunction
2364 function;
2365
2366 register ssize_t
2367 x;
2368
2369 size_t
2370 number_parameters;
2371
cristy947cb4c2011-10-20 18:41:46 +00002372 /*
2373 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002374 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002375 */
anthony805a2d42011-09-25 08:25:12 +00002376 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
anthonyfd706f92012-01-19 04:22:02 +00002377 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002378 arguments=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002379 exception);
2380 if (arguments == (char *) NULL)
2381 break;
2382 p=(char *) arguments;
2383 for (x=0; *p != '\0'; x++)
2384 {
2385 GetMagickToken(p,&p,token);
2386 if (*token == ',')
2387 GetMagickToken(p,&p,token);
2388 }
2389 number_parameters=(size_t) x;
2390 parameters=(double *) AcquireQuantumMemory(number_parameters,
2391 sizeof(*parameters));
2392 if (parameters == (double *) NULL)
2393 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002394 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002395 (void) ResetMagickMemory(parameters,0,number_parameters*
2396 sizeof(*parameters));
2397 p=(char *) arguments;
2398 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2399 {
2400 GetMagickToken(p,&p,token);
2401 if (*token == ',')
2402 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002403 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002404 }
2405 arguments=DestroyString(arguments);
anthony31f1bf72012-01-30 12:37:22 +00002406 (void) FunctionImage(image,function,number_parameters,parameters,
anthony805a2d42011-09-25 08:25:12 +00002407 exception);
2408 parameters=(double *) RelinquishMagickMemory(parameters);
2409 break;
2410 }
2411 break;
2412 }
2413 case 'g':
2414 {
anthonyafa3dfc2012-03-03 11:31:30 +00002415 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002416 {
anthonyafa3dfc2012-03-03 11:31:30 +00002417 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00002418 (void) GammaImage(image,StringToDouble(arg1,(char **) NULL),
anthonyfd706f92012-01-19 04:22:02 +00002419 exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002420 else
2421 image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002422 break;
2423 }
anthonyafa3dfc2012-03-03 11:31:30 +00002424 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2425 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002426 {
anthonyfd706f92012-01-19 04:22:02 +00002427 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002428 if ((flags & SigmaValue) == 0)
2429 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002430 new_image=GaussianBlurImage(image,geometry_info.rho,
cristyd89705a2012-01-20 02:52:24 +00002431 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00002432 break;
2433 }
anthonyafa3dfc2012-03-03 11:31:30 +00002434 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002435 {
anthonyfd706f92012-01-19 04:22:02 +00002436 /*
anthony31f1bf72012-01-30 12:37:22 +00002437 Record Image offset for composition. (A Setting)
2438 Resize last image. (ListOperator)
2439 FUTURE: Why if no 'offset' does this resize ALL images?
2440 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002441 */
anthonyafa3dfc2012-03-03 11:31:30 +00002442 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002443 { /* remove the previous composition geometry offset! */
anthony31f1bf72012-01-30 12:37:22 +00002444 if (image->geometry != (char *) NULL)
2445 image->geometry=DestroyString(image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002446 break;
2447 }
anthony31f1bf72012-01-30 12:37:22 +00002448 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002449 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony31f1bf72012-01-30 12:37:22 +00002450 (void) CloneString(&image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002451 else
anthony31f1bf72012-01-30 12:37:22 +00002452 new_image=ResizeImage(image,geometry.width,geometry.height,
2453 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002454 break;
2455 }
anthony805a2d42011-09-25 08:25:12 +00002456 break;
2457 }
2458 case 'h':
2459 {
anthonyafa3dfc2012-03-03 11:31:30 +00002460 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002461 {
anthonyafa3dfc2012-03-03 11:31:30 +00002462 (void) SetImageArtifact(image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002463 break;
2464 }
2465 break;
2466 }
2467 case 'i':
2468 {
anthonyafa3dfc2012-03-03 11:31:30 +00002469 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002470 {
anthony31f1bf72012-01-30 12:37:22 +00002471 const char
2472 *format,
anthony805a2d42011-09-25 08:25:12 +00002473 *text;
2474
anthony31f1bf72012-01-30 12:37:22 +00002475 format=GetImageOption(image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002476 if (format == (char *) NULL)
2477 {
anthony31f1bf72012-01-30 12:37:22 +00002478 (void) IdentifyImage(image,stdout,image_info->verbose,
anthony805a2d42011-09-25 08:25:12 +00002479 exception);
2480 break;
2481 }
anthony31f1bf72012-01-30 12:37:22 +00002482 text=InterpretImageProperties(image_info,image,format,exception);
anthony805a2d42011-09-25 08:25:12 +00002483 if (text == (char *) NULL)
2484 break;
2485 (void) fputs(text,stdout);
2486 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002487 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002488 break;
2489 }
anthonyafa3dfc2012-03-03 11:31:30 +00002490 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002491 {
anthonyfd706f92012-01-19 04:22:02 +00002492 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002493 new_image=ImplodeImage(image,geometry_info.rho,
2494 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002495 break;
2496 }
anthonyafa3dfc2012-03-03 11:31:30 +00002497 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002498 {
anthony31f1bf72012-01-30 12:37:22 +00002499 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2500 new_image=InterpolativeResizeImage(image,geometry.width,
2501 geometry.height,image->interpolate,exception);
cristy947cb4c2011-10-20 18:41:46 +00002502 break;
2503 }
anthony805a2d42011-09-25 08:25:12 +00002504 break;
2505 }
2506 case 'l':
2507 {
anthonyafa3dfc2012-03-03 11:31:30 +00002508 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002509 {
anthonyfd706f92012-01-19 04:22:02 +00002510 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002511 if ((flags & PercentValue) != 0)
2512 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002513 new_image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
2514 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2515 exception);
anthony805a2d42011-09-25 08:25:12 +00002516 break;
2517 }
anthonyafa3dfc2012-03-03 11:31:30 +00002518 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002519 {
2520 MagickRealType
2521 black_point,
2522 gamma,
2523 white_point;
2524
2525 MagickStatusType
2526 flags;
2527
anthonyfd706f92012-01-19 04:22:02 +00002528 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002529 black_point=geometry_info.rho;
2530 white_point=(MagickRealType) QuantumRange;
2531 if ((flags & SigmaValue) != 0)
2532 white_point=geometry_info.sigma;
2533 gamma=1.0;
2534 if ((flags & XiValue) != 0)
2535 gamma=geometry_info.xi;
2536 if ((flags & PercentValue) != 0)
2537 {
2538 black_point*=(MagickRealType) (QuantumRange/100.0);
2539 white_point*=(MagickRealType) (QuantumRange/100.0);
2540 }
2541 if ((flags & SigmaValue) == 0)
2542 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002543 if (IfPlusOp || ((flags & AspectValue) != 0))
2544 (void) LevelizeImage(image,black_point,white_point,gamma,exception);
anthony805a2d42011-09-25 08:25:12 +00002545 else
anthonyafa3dfc2012-03-03 11:31:30 +00002546 (void) LevelImage(image,black_point,white_point,gamma,exception);
anthony805a2d42011-09-25 08:25:12 +00002547 break;
2548 }
anthonyafa3dfc2012-03-03 11:31:30 +00002549 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002550 {
2551 char
2552 token[MaxTextExtent];
2553
2554 const char
2555 *p;
2556
2557 PixelInfo
2558 black_point,
2559 white_point;
2560
anthonyfd706f92012-01-19 04:22:02 +00002561 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002562 GetMagickToken(p,&p,token); /* get black point color */
2563 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002564 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002565 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002566 else
cristy269c9412011-10-13 23:41:15 +00002567 (void) QueryColorCompliance("#000000",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002568 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002569 if (isalpha((int) token[0]) || (token[0] == '#'))
2570 GetMagickToken(p,&p,token);
2571 if (*token == '\0')
2572 white_point=black_point; /* set everything to that color */
2573 else
2574 {
2575 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2576 GetMagickToken(p,&p,token); /* Get white point color. */
2577 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002578 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002579 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002580 else
cristy269c9412011-10-13 23:41:15 +00002581 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002582 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002583 }
anthony31f1bf72012-01-30 12:37:22 +00002584 (void) LevelImageColors(image,&black_point,&white_point,
2585 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002586 break;
2587 }
anthonyafa3dfc2012-03-03 11:31:30 +00002588 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002589 {
2590 double
2591 black_point,
2592 white_point;
2593
2594 MagickStatusType
2595 flags;
2596
anthonyfd706f92012-01-19 04:22:02 +00002597 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002598 black_point=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002599 white_point=(MagickRealType) image->columns*image->rows;
anthony805a2d42011-09-25 08:25:12 +00002600 if ((flags & SigmaValue) != 0)
2601 white_point=geometry_info.sigma;
2602 if ((flags & PercentValue) != 0)
2603 {
anthony31f1bf72012-01-30 12:37:22 +00002604 black_point*=(double) image->columns*image->rows/100.0;
2605 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002606 }
2607 if ((flags & SigmaValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00002608 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00002609 black_point;
anthony31f1bf72012-01-30 12:37:22 +00002610 (void) LinearStretchImage(image,black_point,white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002611 break;
2612 }
anthonyafa3dfc2012-03-03 11:31:30 +00002613 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002614 {
anthony31f1bf72012-01-30 12:37:22 +00002615 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002616 if ((flags & XValue) == 0)
2617 geometry.x=1;
2618 if ((flags & YValue) == 0)
2619 geometry.y=0;
anthony31f1bf72012-01-30 12:37:22 +00002620 new_image=LiquidRescaleImage(image,geometry.width,
anthony805a2d42011-09-25 08:25:12 +00002621 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2622 break;
2623 }
anthonyafa3dfc2012-03-03 11:31:30 +00002624 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002625 {
anthonyafa3dfc2012-03-03 11:31:30 +00002626 (void) SetImageArtifact(image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002627 break;
2628 }
2629 break;
2630 }
2631 case 'm':
2632 {
anthonyafa3dfc2012-03-03 11:31:30 +00002633 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002634 {
2635 Image
2636 *remap_image;
2637
anthony31f1bf72012-01-30 12:37:22 +00002638 /* DEPRECIATED use -remap */
anthonyfd706f92012-01-19 04:22:02 +00002639 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002640 if (remap_image == (Image *) NULL)
2641 break;
anthony31f1bf72012-01-30 12:37:22 +00002642 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002643 remap_image=DestroyImage(remap_image);
2644 break;
2645 }
anthonyafa3dfc2012-03-03 11:31:30 +00002646 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002647 {
2648 Image
2649 *mask;
2650
anthonyafa3dfc2012-03-03 11:31:30 +00002651 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002652 { /* Remove a mask. */
2653 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00002654 break;
2655 }
anthony31f1bf72012-01-30 12:37:22 +00002656 /* Set the image mask. */
anthonyfd706f92012-01-19 04:22:02 +00002657 mask=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002658 if (mask == (Image *) NULL)
2659 break;
anthony31f1bf72012-01-30 12:37:22 +00002660 (void) SetImageMask(image,mask,exception);
anthony805a2d42011-09-25 08:25:12 +00002661 mask=DestroyImage(mask);
2662 break;
2663 }
anthonyafa3dfc2012-03-03 11:31:30 +00002664 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002665 {
anthony31f1bf72012-01-30 12:37:22 +00002666 /* DEPRECIATED */
anthonyafa3dfc2012-03-03 11:31:30 +00002667 (void) SetImageAlphaChannel(image,IfNormalOp ? SetAlphaChannel :
2668 DeactivateAlphaChannel, exception);
anthony805a2d42011-09-25 08:25:12 +00002669 break;
2670 }
anthonyafa3dfc2012-03-03 11:31:30 +00002671 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002672 {
anthonyfd706f92012-01-19 04:22:02 +00002673 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002674 if ((flags & SigmaValue) == 0)
2675 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002676 new_image=StatisticImage(image,ModeStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002677 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2678 break;
2679 }
anthonyafa3dfc2012-03-03 11:31:30 +00002680 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002681 {
anthony31f1bf72012-01-30 12:37:22 +00002682 (void) ModulateImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002683 break;
2684 }
anthonyafa3dfc2012-03-03 11:31:30 +00002685 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002686 {
anthonyafa3dfc2012-03-03 11:31:30 +00002687 (void) SetImageProgressMonitor(image, IfNormalOp ? MonitorProgress :
2688 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002689 break;
2690 }
anthonyafa3dfc2012-03-03 11:31:30 +00002691 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002692 {
anthony31f1bf72012-01-30 12:37:22 +00002693 (void) SetImageType(image,BilevelType,exception);
anthony805a2d42011-09-25 08:25:12 +00002694 break;
2695 }
anthonyafa3dfc2012-03-03 11:31:30 +00002696 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002697 {
2698 char
2699 token[MaxTextExtent];
2700
2701 const char
2702 *p;
2703
2704 KernelInfo
2705 *kernel;
2706
2707 MorphologyMethod
2708 method;
2709
2710 ssize_t
2711 iterations;
2712
anthonyfd706f92012-01-19 04:22:02 +00002713 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002714 GetMagickToken(p,&p,token);
2715 method=(MorphologyMethod) ParseCommandOption(
2716 MagickMorphologyOptions,MagickFalse,token);
2717 iterations=1L;
2718 GetMagickToken(p,&p,token);
2719 if ((*p == ':') || (*p == ','))
2720 GetMagickToken(p,&p,token);
2721 if ((*p != '\0'))
2722 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002723 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002724 if (kernel == (KernelInfo *) NULL)
2725 {
2726 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00002727 OptionError,"UnabletoParseKernel","morphology");
anthony805a2d42011-09-25 08:25:12 +00002728 break;
2729 }
anthony31f1bf72012-01-30 12:37:22 +00002730 new_image=MorphologyImage(image,method,iterations,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00002731 kernel=DestroyKernelInfo(kernel);
2732 break;
2733 }
anthonyafa3dfc2012-03-03 11:31:30 +00002734 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002735 {
anthonyfd706f92012-01-19 04:22:02 +00002736 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002737 if ((flags & SigmaValue) == 0)
2738 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002739 new_image=MotionBlurImage(image,geometry_info.rho,
2740 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2741 exception);
anthony805a2d42011-09-25 08:25:12 +00002742 break;
2743 }
2744 break;
2745 }
2746 case 'n':
2747 {
anthonyafa3dfc2012-03-03 11:31:30 +00002748 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002749 {
anthony31f1bf72012-01-30 12:37:22 +00002750 (void) NegateImage(image, plus_alt_op, exception);
anthony805a2d42011-09-25 08:25:12 +00002751 break;
2752 }
anthonyafa3dfc2012-03-03 11:31:30 +00002753 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002754 {
anthonyafa3dfc2012-03-03 11:31:30 +00002755 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002756 {
anthonyfd706f92012-01-19 04:22:02 +00002757 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002758 if ((flags & SigmaValue) == 0)
2759 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002760 new_image=StatisticImage(image,NonpeakStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002761 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2762 }
2763 else
2764 {
2765 NoiseType
2766 noise;
2767
anthony31f1bf72012-01-30 12:37:22 +00002768 double
2769 attenuate;
2770
2771 const char*
2772 value;
2773
anthony805a2d42011-09-25 08:25:12 +00002774 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
anthony31f1bf72012-01-30 12:37:22 +00002775 MagickFalse,arg1),
2776
2777 value=GetImageOption(image_info,"attenuate");
2778 if (value != (const char *) NULL)
2779 attenuate=StringToDouble(value,(char **) NULL);
2780 else
2781 attenuate=1.0;
2782
2783 new_image=AddNoiseImage(image,noise,attenuate,exception);
anthony805a2d42011-09-25 08:25:12 +00002784 }
2785 break;
2786 }
anthonyafa3dfc2012-03-03 11:31:30 +00002787 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002788 {
anthony31f1bf72012-01-30 12:37:22 +00002789 (void) NormalizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002790 break;
2791 }
2792 break;
2793 }
2794 case 'o':
2795 {
anthonyafa3dfc2012-03-03 11:31:30 +00002796 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002797 {
2798 PixelInfo
2799 target;
2800
anthony31f1bf72012-01-30 12:37:22 +00002801 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
2802 (void) OpaquePaintImage(image,&target,&draw_info->fill,plus_alt_op,
2803 exception);
anthony805a2d42011-09-25 08:25:12 +00002804 break;
2805 }
anthonyafa3dfc2012-03-03 11:31:30 +00002806 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002807 {
anthony31f1bf72012-01-30 12:37:22 +00002808 (void) OrderedPosterizeImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002809 break;
2810 }
2811 break;
2812 }
2813 case 'p':
2814 {
anthonyafa3dfc2012-03-03 11:31:30 +00002815 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002816 {
anthonyfd706f92012-01-19 04:22:02 +00002817 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002818 new_image=OilPaintImage(image,geometry_info.rho,geometry_info.sigma,
2819 exception);
anthony805a2d42011-09-25 08:25:12 +00002820 break;
2821 }
anthonyafa3dfc2012-03-03 11:31:30 +00002822 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002823 {
cristye9e3d382011-12-14 01:50:13 +00002824 const char
2825 *caption;
2826
anthony805a2d42011-09-25 08:25:12 +00002827 double
2828 angle;
2829
anthonyafa3dfc2012-03-03 11:31:30 +00002830 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002831 {
2832 RandomInfo
2833 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002834
anthony31f1bf72012-01-30 12:37:22 +00002835 random_info=AcquireRandomInfo();
2836 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2837 random_info=DestroyRandomInfo(random_info);
2838 }
2839 else
anthony805a2d42011-09-25 08:25:12 +00002840 {
2841 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00002842 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002843 angle=geometry_info.rho;
2844 }
anthony31f1bf72012-01-30 12:37:22 +00002845 caption=GetImageProperty(image,"caption",exception);
2846 new_image=PolaroidImage(image,draw_info,caption,angle,
2847 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002848 break;
2849 }
anthonyafa3dfc2012-03-03 11:31:30 +00002850 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002851 {
anthony31f1bf72012-01-30 12:37:22 +00002852 (void) ParseGeometry(arg1,&geometry_info);
2853 (void) PosterizeImage(image,(size_t) geometry_info.rho,
2854 quantize_info->dither,exception);
anthony805a2d42011-09-25 08:25:12 +00002855 break;
2856 }
anthonyafa3dfc2012-03-03 11:31:30 +00002857 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002858 {
2859 PreviewType
cristy947cb4c2011-10-20 18:41:46 +00002860 preview_type;
anthony170fce92011-10-20 11:50:23 +00002861
anthony31f1bf72012-01-30 12:37:22 +00002862 /* FUTURE: should be a 'Genesis' option?
2863 Option however is also in WandSettingOptionInfo()
cristy947cb4c2011-10-20 18:41:46 +00002864 */
anthony31f1bf72012-01-30 12:37:22 +00002865 preview_type=UndefinedPreview;
anthonyafa3dfc2012-03-03 11:31:30 +00002866 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00002867 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2868 MagickFalse,arg1);
2869 new_image=PreviewImage(image,preview_type,exception);
anthony805a2d42011-09-25 08:25:12 +00002870 break;
2871 }
anthonyafa3dfc2012-03-03 11:31:30 +00002872 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002873 {
2874 const char
2875 *name;
2876
2877 const StringInfo
2878 *profile;
2879
2880 Image
2881 *profile_image;
2882
2883 ImageInfo
2884 *profile_info;
2885
anthonyafa3dfc2012-03-03 11:31:30 +00002886 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002887 { /* Remove a profile from the image. */
2888 (void) ProfileImage(image,arg1,(const unsigned char *)
cristy092d71c2011-10-14 18:01:29 +00002889 NULL,0,exception);
anthony805a2d42011-09-25 08:25:12 +00002890 break;
2891 }
anthony31f1bf72012-01-30 12:37:22 +00002892 /* Associate a profile with the image. */
anthony805a2d42011-09-25 08:25:12 +00002893 profile_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00002894 profile=GetImageProfile(image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002895 if (profile != (StringInfo *) NULL)
2896 profile_info->profile=(void *) CloneStringInfo(profile);
anthonyfd706f92012-01-19 04:22:02 +00002897 profile_image=GetImageCache(profile_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002898 profile_info=DestroyImageInfo(profile_info);
2899 if (profile_image == (Image *) NULL)
2900 {
2901 StringInfo
2902 *profile;
2903
2904 profile_info=CloneImageInfo(image_info);
anthonyfd706f92012-01-19 04:22:02 +00002905 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002906 MaxTextExtent);
2907 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
2908 if (profile != (StringInfo *) NULL)
2909 {
anthony31f1bf72012-01-30 12:37:22 +00002910 (void) ProfileImage(image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002911 GetStringInfoDatum(profile),(size_t)
cristy092d71c2011-10-14 18:01:29 +00002912 GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002913 profile=DestroyStringInfo(profile);
2914 }
2915 profile_info=DestroyImageInfo(profile_info);
2916 break;
2917 }
2918 ResetImageProfileIterator(profile_image);
2919 name=GetNextImageProfile(profile_image);
2920 while (name != (const char *) NULL)
2921 {
2922 profile=GetImageProfile(profile_image,name);
2923 if (profile != (StringInfo *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002924 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
cristy092d71c2011-10-14 18:01:29 +00002925 (size_t) GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002926 name=GetNextImageProfile(profile_image);
2927 }
2928 profile_image=DestroyImage(profile_image);
2929 break;
2930 }
2931 break;
2932 }
anthony805a2d42011-09-25 08:25:12 +00002933 case 'r':
2934 {
anthonyafa3dfc2012-03-03 11:31:30 +00002935 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002936 {
anthonyfd706f92012-01-19 04:22:02 +00002937 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002938 new_image=RadialBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002939 geometry_info.sigma,exception);
2940 break;
2941 }
anthonyafa3dfc2012-03-03 11:31:30 +00002942 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002943 {
anthony31f1bf72012-01-30 12:37:22 +00002944 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002945 if ((flags & SigmaValue) == 0)
2946 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00002947 (void) RaiseImage(image,&geometry,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002948 break;
2949 }
anthonyafa3dfc2012-03-03 11:31:30 +00002950 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002951 {
anthony31f1bf72012-01-30 12:37:22 +00002952 (void) RandomThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002953 break;
2954 }
anthonyafa3dfc2012-03-03 11:31:30 +00002955 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002956 {
2957 Image
2958 *remap_image;
2959
anthonyfd706f92012-01-19 04:22:02 +00002960 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002961 if (remap_image == (Image *) NULL)
2962 break;
anthony31f1bf72012-01-30 12:37:22 +00002963 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002964 remap_image=DestroyImage(remap_image);
2965 break;
2966 }
anthonyafa3dfc2012-03-03 11:31:30 +00002967 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002968 {
anthonyafa3dfc2012-03-03 11:31:30 +00002969 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00002970 (void) ResetImagePage(image,arg1);
2971 else
2972 (void) ParseAbsoluteGeometry("0x0+0+0",&image->page);
anthony805a2d42011-09-25 08:25:12 +00002973 break;
2974 }
anthonyafa3dfc2012-03-03 11:31:30 +00002975 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002976 {
anthony31f1bf72012-01-30 12:37:22 +00002977 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00002978 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002979 if ((flags & SigmaValue) == 0)
2980 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002981 new_image=ResampleImage(image,geometry_info.rho,
2982 geometry_info.sigma,image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002983 break;
2984 }
anthonyafa3dfc2012-03-03 11:31:30 +00002985 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002986 {
anthonyafbaed72011-10-26 12:05:04 +00002987 /* FUTURE: remove blur argument - no longer used */
anthony31f1bf72012-01-30 12:37:22 +00002988 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2989 new_image=ResizeImage(image,geometry.width,geometry.height,
2990 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002991 break;
2992 }
anthonyafa3dfc2012-03-03 11:31:30 +00002993 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002994 {
anthony31f1bf72012-01-30 12:37:22 +00002995 (void) ParsePageGeometry(image,arg1,&geometry,exception);
2996 new_image=RollImage(image,geometry.x,geometry.y,exception);
anthony805a2d42011-09-25 08:25:12 +00002997 break;
2998 }
anthonyafa3dfc2012-03-03 11:31:30 +00002999 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003000 {
anthonyfd706f92012-01-19 04:22:02 +00003001 if (strchr(arg1,'>') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003002 if (image->columns <= image->rows)
anthony805a2d42011-09-25 08:25:12 +00003003 break;
anthonyfd706f92012-01-19 04:22:02 +00003004 if (strchr(arg1,'<') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003005 if (image->columns >= image->rows)
anthony805a2d42011-09-25 08:25:12 +00003006 break;
anthonyafbaed72011-10-26 12:05:04 +00003007
anthonyfd706f92012-01-19 04:22:02 +00003008 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003009 new_image=RotateImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00003010 break;
3011 }
3012 break;
3013 }
3014 case 's':
3015 {
anthonyafa3dfc2012-03-03 11:31:30 +00003016 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003017 {
anthony31f1bf72012-01-30 12:37:22 +00003018 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3019 new_image=SampleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00003020 exception);
3021 break;
3022 }
anthonyafa3dfc2012-03-03 11:31:30 +00003023 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003024 {
anthony31f1bf72012-01-30 12:37:22 +00003025 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3026 new_image=ScaleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00003027 exception);
3028 break;
3029 }
anthonyafa3dfc2012-03-03 11:31:30 +00003030 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003031 {
anthonyfd706f92012-01-19 04:22:02 +00003032 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003033 if ((flags & PercentValue) != 0)
3034 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00003035 new_image=SelectiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003036 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3037 break;
3038 }
anthonyafa3dfc2012-03-03 11:31:30 +00003039 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003040 {
anthony31f1bf72012-01-30 12:37:22 +00003041 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003042 /* FUTURE - this may be replaced by a "-channel" method */
anthony31f1bf72012-01-30 12:37:22 +00003043 new_image=SeparateImages(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003044 break;
3045 }
anthonyafa3dfc2012-03-03 11:31:30 +00003046 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003047 {
3048 double
3049 threshold;
3050
anthonyfd706f92012-01-19 04:22:02 +00003051 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00003052 new_image=SepiaToneImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00003053 break;
3054 }
anthonyafa3dfc2012-03-03 11:31:30 +00003055 if (LocaleCompare("segment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003056 {
anthonyfd706f92012-01-19 04:22:02 +00003057 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003058 if ((flags & SigmaValue) == 0)
3059 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003060 (void) SegmentImage(image,image->colorspace,
anthony805a2d42011-09-25 08:25:12 +00003061 image_info->verbose,geometry_info.rho,geometry_info.sigma,
3062 exception);
3063 break;
3064 }
anthonyafa3dfc2012-03-03 11:31:30 +00003065 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003066 {
3067 char
3068 *value;
3069
anthonyafa3dfc2012-03-03 11:31:30 +00003070 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00003071 {
anthonyfd706f92012-01-19 04:22:02 +00003072 if (LocaleNCompare(arg1,"registry:",9) == 0)
3073 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003074 else
anthony31f1bf72012-01-30 12:37:22 +00003075 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003076 {
anthonyfd706f92012-01-19 04:22:02 +00003077 (void) DeleteImageOption(image_info,arg1+7);
anthony31f1bf72012-01-30 12:37:22 +00003078 (void) DeleteImageArtifact(image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003079 }
3080 else
anthony31f1bf72012-01-30 12:37:22 +00003081 (void) DeleteImageProperty(image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003082 break;
3083 }
anthony31f1bf72012-01-30 12:37:22 +00003084 value=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00003085 exception);
3086 if (value == (char *) NULL)
3087 break;
anthonyfd706f92012-01-19 04:22:02 +00003088 if (LocaleNCompare(arg1,"registry:",9) == 0)
3089 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony805a2d42011-09-25 08:25:12 +00003090 exception);
3091 else
anthonyfd706f92012-01-19 04:22:02 +00003092 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003093 {
anthonyfd706f92012-01-19 04:22:02 +00003094 (void) SetImageOption(image_info,arg1+7,value);
anthony31f1bf72012-01-30 12:37:22 +00003095 (void) SetImageArtifact(image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003096 }
3097 else
anthony31f1bf72012-01-30 12:37:22 +00003098 (void) SetImageProperty(image,arg1,value,exception);
anthony805a2d42011-09-25 08:25:12 +00003099 value=DestroyString(value);
3100 break;
3101 }
anthonyafa3dfc2012-03-03 11:31:30 +00003102 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003103 {
anthonyfd706f92012-01-19 04:22:02 +00003104 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003105 if ((flags & SigmaValue) == 0)
3106 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003107 new_image=ShadeImage(image,normal_op,geometry_info.rho,
3108 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00003109 break;
3110 }
anthonyafa3dfc2012-03-03 11:31:30 +00003111 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003112 {
anthonyfd706f92012-01-19 04:22:02 +00003113 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003114 if ((flags & SigmaValue) == 0)
3115 geometry_info.sigma=1.0;
3116 if ((flags & XiValue) == 0)
3117 geometry_info.xi=4.0;
3118 if ((flags & PsiValue) == 0)
3119 geometry_info.psi=4.0;
anthony31f1bf72012-01-30 12:37:22 +00003120 new_image=ShadowImage(image,geometry_info.rho,
3121 geometry_info.sigma,image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003122 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
3123 exception);
anthony805a2d42011-09-25 08:25:12 +00003124 break;
3125 }
anthonyafa3dfc2012-03-03 11:31:30 +00003126 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003127 {
anthonyfd706f92012-01-19 04:22:02 +00003128 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003129 if ((flags & SigmaValue) == 0)
3130 geometry_info.sigma=1.0;
3131 if ((flags & XiValue) == 0)
3132 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00003133 new_image=SharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003134 geometry_info.sigma,geometry_info.xi,exception);
3135 break;
3136 }
anthonyafa3dfc2012-03-03 11:31:30 +00003137 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003138 {
anthony31f1bf72012-01-30 12:37:22 +00003139 flags=ParsePageGeometry(image,arg1,&geometry,exception);
3140 new_image=ShaveImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003141 break;
3142 }
anthonyafa3dfc2012-03-03 11:31:30 +00003143 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003144 {
anthonyfd706f92012-01-19 04:22:02 +00003145 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003146 if ((flags & SigmaValue) == 0)
3147 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00003148 new_image=ShearImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003149 geometry_info.sigma,exception);
3150 break;
3151 }
anthonyafa3dfc2012-03-03 11:31:30 +00003152 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003153 {
anthonyfd706f92012-01-19 04:22:02 +00003154 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003155 if ((flags & SigmaValue) == 0)
3156 geometry_info.sigma=(double) QuantumRange/2.0;
3157 if ((flags & PercentValue) != 0)
3158 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3159 100.0;
anthony31f1bf72012-01-30 12:37:22 +00003160 (void) SigmoidalContrastImage(image,normal_op,geometry_info.rho,
3161 geometry_info.sigma,
anthony805a2d42011-09-25 08:25:12 +00003162 exception);
3163 break;
3164 }
anthonyafa3dfc2012-03-03 11:31:30 +00003165 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003166 {
anthonyfd706f92012-01-19 04:22:02 +00003167 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003168 if ((flags & SigmaValue) == 0)
3169 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003170 new_image=SketchImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003171 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3172 break;
3173 }
anthonyafa3dfc2012-03-03 11:31:30 +00003174 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003175 {
anthony31f1bf72012-01-30 12:37:22 +00003176 (void) SolarizeImage(image,StringToDoubleInterval(arg1,(double)
3177 QuantumRange+1.0),exception);
anthony805a2d42011-09-25 08:25:12 +00003178 break;
3179 }
anthonyafa3dfc2012-03-03 11:31:30 +00003180 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003181 {
3182 SparseColorMethod
3183 method;
3184
3185 char
3186 *arguments;
3187
anthony805a2d42011-09-25 08:25:12 +00003188 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003189 MagickSparseColorOptions,MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003190 arguments=InterpretImageProperties(image_info,image,arg2,exception);
anthony805a2d42011-09-25 08:25:12 +00003191 if (arguments == (char *) NULL)
3192 break;
anthony31f1bf72012-01-30 12:37:22 +00003193 new_image=SparseColorOption(image,method,arguments,exception);
anthony805a2d42011-09-25 08:25:12 +00003194 arguments=DestroyString(arguments);
3195 break;
3196 }
anthonyafa3dfc2012-03-03 11:31:30 +00003197 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003198 {
anthony31f1bf72012-01-30 12:37:22 +00003199 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
3200 new_image=SpliceImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003201 break;
3202 }
anthonyafa3dfc2012-03-03 11:31:30 +00003203 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003204 {
anthonyfd706f92012-01-19 04:22:02 +00003205 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003206 new_image=SpreadImage(image,geometry_info.rho,image->interpolate,
3207 exception);
anthony805a2d42011-09-25 08:25:12 +00003208 break;
3209 }
anthonyafa3dfc2012-03-03 11:31:30 +00003210 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003211 {
3212 StatisticType
3213 type;
3214
anthony805a2d42011-09-25 08:25:12 +00003215 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
anthonyfd706f92012-01-19 04:22:02 +00003216 MagickFalse,arg1);
3217 (void) ParseGeometry(arg2,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003218 new_image=StatisticImage(image,type,(size_t) geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003219 (size_t) geometry_info.sigma,exception);
3220 break;
3221 }
anthonyafa3dfc2012-03-03 11:31:30 +00003222 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003223 {
anthony31f1bf72012-01-30 12:37:22 +00003224 (void) StripImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003225 break;
3226 }
anthonyafa3dfc2012-03-03 11:31:30 +00003227 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003228 {
anthonyfd706f92012-01-19 04:22:02 +00003229 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003230 new_image=SwirlImage(image,geometry_info.rho,
3231 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003232 break;
3233 }
3234 break;
3235 }
3236 case 't':
3237 {
anthonyafa3dfc2012-03-03 11:31:30 +00003238 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003239 {
3240 double
3241 threshold;
3242
anthonyafa3dfc2012-03-03 11:31:30 +00003243 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003244 threshold=(double) QuantumRange/2;
3245 else
anthonyfd706f92012-01-19 04:22:02 +00003246 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00003247 (void) BilevelImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00003248 break;
3249 }
anthonyafa3dfc2012-03-03 11:31:30 +00003250 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003251 {
anthony31f1bf72012-01-30 12:37:22 +00003252 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3253 new_image=ThumbnailImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00003254 exception);
3255 break;
3256 }
anthonyafa3dfc2012-03-03 11:31:30 +00003257 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003258 {
anthony31f1bf72012-01-30 12:37:22 +00003259 new_image=TintImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00003260 break;
3261 }
anthonyafa3dfc2012-03-03 11:31:30 +00003262 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003263 {
anthonyfd706f92012-01-19 04:22:02 +00003264 /* DEPRECIATED */
anthony31f1bf72012-01-30 12:37:22 +00003265 new_image=AffineTransformImage(image,&draw_info->affine,
anthony805a2d42011-09-25 08:25:12 +00003266 exception);
3267 break;
3268 }
anthonyafa3dfc2012-03-03 11:31:30 +00003269 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003270 {
3271 PixelInfo
3272 target;
3273
anthony31f1bf72012-01-30 12:37:22 +00003274 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
3275 (void) TransparentPaintImage(image,&target,(Quantum)
3276 TransparentAlpha,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003277 break;
3278 }
anthonyafa3dfc2012-03-03 11:31:30 +00003279 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003280 {
anthony31f1bf72012-01-30 12:37:22 +00003281 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003282 break;
3283 }
anthonyafa3dfc2012-03-03 11:31:30 +00003284 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003285 {
anthony31f1bf72012-01-30 12:37:22 +00003286 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003287 break;
3288 }
anthonyafa3dfc2012-03-03 11:31:30 +00003289 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003290 {
anthony31f1bf72012-01-30 12:37:22 +00003291 new_image=TrimImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003292 break;
3293 }
anthonyafa3dfc2012-03-03 11:31:30 +00003294 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003295 {
anthonyab3a50c2011-10-27 11:48:57 +00003296 /* Note that "type" setting should have already been defined */
anthony31f1bf72012-01-30 12:37:22 +00003297 (void) SetImageType(image,image_info->type,exception);
anthony805a2d42011-09-25 08:25:12 +00003298 break;
3299 }
3300 break;
3301 }
3302 case 'u':
3303 {
anthonyafa3dfc2012-03-03 11:31:30 +00003304 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003305 {
anthony31f1bf72012-01-30 12:37:22 +00003306 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00003307 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003308 {
anthony31f1bf72012-01-30 12:37:22 +00003309 (void) DeleteImageArtifact(image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003310 break;
3311 }
anthony31f1bf72012-01-30 12:37:22 +00003312 (void) SetImageArtifact(image,"identify:unique-colors","true");
3313 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003314 break;
3315 }
anthonyafa3dfc2012-03-03 11:31:30 +00003316 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003317 {
anthony31f1bf72012-01-30 12:37:22 +00003318 new_image=UniqueImageColors(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003319 break;
3320 }
anthonyafa3dfc2012-03-03 11:31:30 +00003321 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003322 {
anthonyfd706f92012-01-19 04:22:02 +00003323 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003324 if ((flags & SigmaValue) == 0)
3325 geometry_info.sigma=1.0;
3326 if ((flags & XiValue) == 0)
3327 geometry_info.xi=1.0;
3328 if ((flags & PsiValue) == 0)
3329 geometry_info.psi=0.05;
anthony31f1bf72012-01-30 12:37:22 +00003330 new_image=UnsharpMaskImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003331 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3332 break;
3333 }
3334 break;
3335 }
3336 case 'v':
3337 {
anthonyafa3dfc2012-03-03 11:31:30 +00003338 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003339 {
anthonyafa3dfc2012-03-03 11:31:30 +00003340 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony31f1bf72012-01-30 12:37:22 +00003341 three places! ImageArtifact ImageOption image_info->verbose
anthonyafa3dfc2012-03-03 11:31:30 +00003342 Some how new images also get this artifact presumably here
anthony31f1bf72012-01-30 12:37:22 +00003343 */
anthonyafa3dfc2012-03-03 11:31:30 +00003344 (void) SetImageArtifact(image,option+1,
3345 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003346 break;
3347 }
anthonyafa3dfc2012-03-03 11:31:30 +00003348 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003349 {
anthonyfd706f92012-01-19 04:22:02 +00003350 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003351 if ((flags & SigmaValue) == 0)
3352 geometry_info.sigma=1.0;
3353 if ((flags & XiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003354 geometry_info.xi=0.1*image->columns;
anthony805a2d42011-09-25 08:25:12 +00003355 if ((flags & PsiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003356 geometry_info.psi=0.1*image->rows;
3357 new_image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
3358 image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3359 (ssize_t) ceil(geometry_info.psi-0.5),exception);
anthony805a2d42011-09-25 08:25:12 +00003360 break;
3361 }
anthony805a2d42011-09-25 08:25:12 +00003362 break;
3363 }
3364 case 'w':
3365 {
anthonyafa3dfc2012-03-03 11:31:30 +00003366 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003367 {
anthonyfd706f92012-01-19 04:22:02 +00003368 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003369 if ((flags & SigmaValue) == 0)
3370 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003371 new_image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
3372 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003373 break;
3374 }
anthonyafa3dfc2012-03-03 11:31:30 +00003375 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003376 {
anthony31f1bf72012-01-30 12:37:22 +00003377 (void) WhiteThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003378 break;
3379 }
3380 break;
3381 }
3382 default:
3383 break;
3384 }
3385 /*
3386 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003387 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003388 */
3389 if (new_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003390 ReplaceImageInListReturnLast(&image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003391
anthony31f1bf72012-01-30 12:37:22 +00003392 return;
anthonyfd706f92012-01-19 04:22:02 +00003393#undef image_info
3394#undef draw_info
3395#undef quantize_info
anthony31f1bf72012-01-30 12:37:22 +00003396#undef image
anthonyfd706f92012-01-19 04:22:02 +00003397#undef exception
anthonyafa3dfc2012-03-03 11:31:30 +00003398#undef IfNormalOp
3399#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003400#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003401#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003402}
anthonyfd706f92012-01-19 04:22:02 +00003403
anthony43f425d2012-02-26 12:58:58 +00003404WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003405 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003406{
3407 size_t
anthony43f425d2012-02-26 12:58:58 +00003408 n,
anthony31f1bf72012-01-30 12:37:22 +00003409 i;
3410
anthony43f425d2012-02-26 12:58:58 +00003411 assert(cli_wand != (MagickCLI *) NULL);
3412 assert(cli_wand->signature == WandSignature);
3413 assert(cli_wand->wand.signature == WandSignature);
3414 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3415 if (cli_wand->wand.debug != MagickFalse)
3416 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003417
anthonyafa3dfc2012-03-03 11:31:30 +00003418#if !USE_WAND_METHODS
3419 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003420 i=0;
anthony43f425d2012-02-26 12:58:58 +00003421 n=GetImageListLength(cli_wand->wand.images);
3422 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003423 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003424 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003425 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003426 if ( cli_wand->wand.images->next == (Image *) NULL )
3427 break;
3428 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003429 }
anthony43f425d2012-02-26 12:58:58 +00003430 assert( i == n );
3431 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003432#else
3433 MagickResetIterator(&cli_wand->wand);
3434 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3435 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3436 MagickResetIterator(&cli_wand->wand);
3437#endif
anthony31f1bf72012-01-30 12:37:22 +00003438 return;
anthony805a2d42011-09-25 08:25:12 +00003439}
3440
3441/*
3442%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3443% %
3444% %
3445% %
anthony43f425d2012-02-26 12:58:58 +00003446+ 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 +00003447% %
3448% %
3449% %
3450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3451%
anthony43f425d2012-02-26 12:58:58 +00003452% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003453% entire image list as a whole. The result is often a complete replacment
3454% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003455%
3456% The format of the MogrifyImage method is:
3457%
anthony43f425d2012-02-26 12:58:58 +00003458% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003459% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003460%
3461% A description of each parameter follows:
3462%
anthony43f425d2012-02-26 12:58:58 +00003463% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003464%
anthony36a8c2c2012-02-10 00:08:44 +00003465% o option: The option string for the operation
3466%
anthony31f1bf72012-01-30 12:37:22 +00003467% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003468%
anthony8b10b462012-02-08 12:32:44 +00003469% NOTE: only "limit" currently uses two arguments.
3470%
3471% Example usage...
3472%
anthonyafa3dfc2012-03-03 11:31:30 +00003473% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3474% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003475%
3476% Or for handling command line arguments EG: +/-option ["arg"]
3477%
anthony43f425d2012-02-26 12:58:58 +00003478% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003479% argc,argv
3480% i=index in argv
3481%
anthony2052d272012-02-28 12:48:29 +00003482% option_info = GetCommandOptionInfo(argv[i]);
3483% count=option_info->type;
3484% option_type=option_info->flags;
3485%
3486% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003487% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003488% count>=1 ? argv[i+1] : (char *)NULL,
3489% count>=2 ? argv[i+2] : (char *)NULL );
3490% i += count+1;
3491%
anthony805a2d42011-09-25 08:25:12 +00003492*/
anthony43f425d2012-02-26 12:58:58 +00003493WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003494 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003495{
anthony31f1bf72012-01-30 12:37:22 +00003496 Image
3497 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003498
anthony43f425d2012-02-26 12:58:58 +00003499#define image_info (cli_wand->wand.image_info)
3500#define images (cli_wand->wand.images)
3501#define exception (cli_wand->wand.exception)
3502#define draw_info (cli_wand->draw_info)
3503#define quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003504#define IfNormalOp (*option=='-')
3505#define IfPlusOp (*option!='-')
3506#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003507
anthony43f425d2012-02-26 12:58:58 +00003508 assert(cli_wand != (MagickCLI *) NULL);
3509 assert(cli_wand->signature == WandSignature);
3510 assert(cli_wand->wand.signature == WandSignature);
3511 assert(images != (Image *) NULL); /* images must be present */
3512 if (cli_wand->wand.debug != MagickFalse)
3513 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003514
3515 (void) SyncImagesSettings(image_info,images,exception);
3516
3517 new_images=NewImageList();
3518
anthonyafa3dfc2012-03-03 11:31:30 +00003519 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003520 {
3521 case 'a':
3522 {
anthonyafa3dfc2012-03-03 11:31:30 +00003523 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003524 {
anthony31f1bf72012-01-30 12:37:22 +00003525 new_images=AppendImages(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003526 break;
3527 }
anthonyafa3dfc2012-03-03 11:31:30 +00003528 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003529 {
anthony31f1bf72012-01-30 12:37:22 +00003530 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003531 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003532 break;
3533 }
3534 break;
3535 }
3536 case 'c':
3537 {
cristyd04e7bf2012-03-03 19:19:12 +00003538 if (LocaleCompare("channel-ops",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003539 {
anthony319dac62012-03-06 04:12:44 +00003540 (void) SyncImagesSettings(mogrify_info,*images,exception);
3541 new_images=ChannelOperationImage(*images,argv[i+1],exception);
cristy87c02f42012-02-24 00:19:10 +00003542 break;
3543 }
anthonyafa3dfc2012-03-03 11:31:30 +00003544 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003545 {
anthony805a2d42011-09-25 08:25:12 +00003546 Image
anthony31f1bf72012-01-30 12:37:22 +00003547 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003548
anthonyafa3dfc2012-03-03 11:31:30 +00003549 /* FUTURE - make this a compose option, and thus can be used
3550 with layers compose or even compose last image over all other
3551 images.
cristy87c02f42012-02-24 00:19:10 +00003552 */
anthony31f1bf72012-01-30 12:37:22 +00003553 new_images=RemoveFirstImageFromList(&images);
3554 clut_image=RemoveLastImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003555 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003556 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003557 break;
anthony31f1bf72012-01-30 12:37:22 +00003558 (void) ClutImage(new_images,clut_image,images->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003559 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003560 break;
3561 }
anthonyafa3dfc2012-03-03 11:31:30 +00003562 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003563 {
anthony31f1bf72012-01-30 12:37:22 +00003564 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003565 break;
3566 }
anthonyafa3dfc2012-03-03 11:31:30 +00003567 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003568 {
anthony43f425d2012-02-26 12:58:58 +00003569 /* FUTURE - this may be replaced by a 'channel' method */
anthony31f1bf72012-01-30 12:37:22 +00003570 new_images=CombineImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003571 break;
3572 }
anthonyafa3dfc2012-03-03 11:31:30 +00003573 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003574 {
3575 Image
3576 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003577 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003578
3579 RectangleInfo
3580 geometry;
3581
anthony31f1bf72012-01-30 12:37:22 +00003582 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003583 compose;
3584
3585 const char*
3586 value;
3587
3588 value=GetImageOption(image_info,"compose");
3589 if (value != (const char *) NULL)
3590 compose=(CompositeOperator) ParseCommandOption(
3591 MagickComposeOptions,MagickFalse,value);
3592 else
anthony31f1bf72012-01-30 12:37:22 +00003593 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003594
anthony31f1bf72012-01-30 12:37:22 +00003595 new_images=RemoveFirstImageFromList(&images);
3596 source_image=RemoveFirstImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003597 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003598 if (source_image == (Image *) NULL)
3599 break;
anthonye8f56492012-02-12 12:39:02 +00003600
anthony31f1bf72012-01-30 12:37:22 +00003601 /* FUTURE - this should not be here! - should be part of -geometry */
3602 (void) TransformImage(&source_image,(char *) NULL,
3603 source_image->geometry,exception);
anthony5f867ae2011-10-09 10:28:34 +00003604
anthony31f1bf72012-01-30 12:37:22 +00003605 SetGeometry(source_image,&geometry);
3606 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3607 GravityAdjustGeometry(new_images->columns,new_images->rows,
3608 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003609
anthony31f1bf72012-01-30 12:37:22 +00003610 mask_image=RemoveFirstImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003611 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003612 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003613 if ((compose == DisplaceCompositeOp) ||
3614 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003615 { /* Merge Y displacement into X displace/distort map. */
3616 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony6613bf32011-10-15 07:24:44 +00003617 mask_image,0,0,exception);
anthony805a2d42011-09-25 08:25:12 +00003618 mask_image=DestroyImage(mask_image);
3619 }
3620 else
3621 {
3622 /*
3623 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003624 */
cristy1539afd2012-01-30 01:32:59 +00003625 (void) NegateImage(mask_image,MagickFalse,exception);
anthony31f1bf72012-01-30 12:37:22 +00003626 (void) SetImageMask(new_images,mask_image,exception);
cristy1539afd2012-01-30 01:32:59 +00003627 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003628 }
3629 }
anthony31f1bf72012-01-30 12:37:22 +00003630 (void) CompositeImage(new_images,compose,source_image,geometry.x,
3631 geometry.y,exception);
3632 (void) SetImageMask(new_images,(Image *) NULL,exception);
3633 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003634 break;
3635 }
3636 break;
3637 }
3638 case 'd':
3639 {
anthonyafa3dfc2012-03-03 11:31:30 +00003640 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003641 {
anthony31f1bf72012-01-30 12:37:22 +00003642 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003643 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003644 break;
3645 }
anthonyafa3dfc2012-03-03 11:31:30 +00003646 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003647 {
anthonyafa3dfc2012-03-03 11:31:30 +00003648 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003649 DeleteImages(&images,arg1,exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003650 else
3651 DeleteImages(&images,"-1",exception);
anthony805a2d42011-09-25 08:25:12 +00003652 break;
3653 }
anthonyafa3dfc2012-03-03 11:31:30 +00003654 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003655 {
anthonyafa3dfc2012-03-03 11:31:30 +00003656 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003657 {
3658 const char
3659 *p;
3660
3661 size_t
3662 number_duplicates;
3663
anthony31f1bf72012-01-30 12:37:22 +00003664 number_duplicates=(size_t) StringToLong(arg1);
3665 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003666 if (p == (const char *) NULL)
anthony36a8c2c2012-02-10 00:08:44 +00003667 new_images=DuplicateImages(images,number_duplicates,
anthony805a2d42011-09-25 08:25:12 +00003668 "-1",exception);
3669 else
anthony36a8c2c2012-02-10 00:08:44 +00003670 new_images=DuplicateImages(images,number_duplicates,p,
anthony805a2d42011-09-25 08:25:12 +00003671 exception);
3672 }
anthonyafa3dfc2012-03-03 11:31:30 +00003673 else
3674 new_images=DuplicateImages(images,1,"-1",exception);
anthony36a8c2c2012-02-10 00:08:44 +00003675 AppendImageToList(&images, new_images);
3676 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003677 break;
3678 }
3679 break;
3680 }
3681 case 'e':
3682 {
anthonyafa3dfc2012-03-03 11:31:30 +00003683 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003684 {
anthony805a2d42011-09-25 08:25:12 +00003685 MagickEvaluateOperator
anthony31f1bf72012-01-30 12:37:22 +00003686 method;
anthony805a2d42011-09-25 08:25:12 +00003687
anthony31f1bf72012-01-30 12:37:22 +00003688 method=(MagickEvaluateOperator) ParseCommandOption(
3689 MagickEvaluateOptions,MagickFalse,arg1);
3690 new_images=EvaluateImages(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003691 break;
3692 }
3693 break;
3694 }
3695 case 'f':
3696 {
anthonyafa3dfc2012-03-03 11:31:30 +00003697 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003698 {
anthony31f1bf72012-01-30 12:37:22 +00003699 new_images=ForwardFourierTransformImage(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003700 break;
3701 }
anthonyafa3dfc2012-03-03 11:31:30 +00003702 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003703 {
anthony319dac62012-03-06 04:12:44 +00003704 /* REDIRECTED to use -layers flatten instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003705 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003706 break;
3707 }
anthonyafa3dfc2012-03-03 11:31:30 +00003708 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003709 {
anthony31f1bf72012-01-30 12:37:22 +00003710 new_images=FxImage(images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003711 break;
3712 }
3713 break;
3714 }
3715 case 'h':
3716 {
anthonyafa3dfc2012-03-03 11:31:30 +00003717 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003718 {
anthony31f1bf72012-01-30 12:37:22 +00003719 /* FUTURE - make this a compose option (and thus layers compose )
3720 or perhaps compose last image over all other images.
3721 */
anthony805a2d42011-09-25 08:25:12 +00003722 Image
anthony31f1bf72012-01-30 12:37:22 +00003723 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003724
anthony31f1bf72012-01-30 12:37:22 +00003725 new_images=RemoveFirstImageFromList(&images);
3726 hald_image=RemoveLastImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003727 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003728 break;
3729 (void) HaldClutImage(new_images,hald_image,exception);
anthony805a2d42011-09-25 08:25:12 +00003730 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003731 break;
3732 }
3733 break;
3734 }
3735 case 'i':
3736 {
anthonyafa3dfc2012-03-03 11:31:30 +00003737 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003738 {
3739 Image
anthony805a2d42011-09-25 08:25:12 +00003740 *magnitude_image,
3741 *phase_image;
3742
anthony31f1bf72012-01-30 12:37:22 +00003743 magnitude_image=RemoveFirstImageFromList(&images);
3744 phase_image=RemoveFirstImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003745 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003746 if (phase_image == (Image *) NULL)
3747 break;
3748 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
3749 normal_op,exception);
3750 magnitude_image=DestroyImage(magnitude_image);
3751 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003752 break;
3753 }
anthonyafa3dfc2012-03-03 11:31:30 +00003754 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003755 {
3756 Image
anthony31f1bf72012-01-30 12:37:22 +00003757 *insert_image,
3758 *index_image;
3759
3760 ssize_t
3761 index;
anthony805a2d42011-09-25 08:25:12 +00003762
3763 index=0;
anthony31f1bf72012-01-30 12:37:22 +00003764 insert_image=RemoveLastImageFromList(&images);
anthonyafa3dfc2012-03-03 11:31:30 +00003765 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003766 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003767 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003768 if (index == 0)
anthony31f1bf72012-01-30 12:37:22 +00003769 PrependImageToList(&images,insert_image);
anthony43f425d2012-02-26 12:58:58 +00003770 else if (index == (ssize_t) GetImageListLength(images))
3771 AppendImageToList(&images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003772 else
anthony43f425d2012-02-26 12:58:58 +00003773 {
3774 index_image=GetImageFromList(images,index-1);
3775 if (index_image == (Image *) NULL)
3776 {
3777 (void) ThrowMagickException(exception,GetMagickModule(),
3778 OptionError,"NoSuchImage","'%s'",arg1);
3779 break;
3780 }
3781 InsertImageInList(&index_image,insert_image);
3782 }
anthony31f1bf72012-01-30 12:37:22 +00003783 images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003784 break;
3785 }
anthony805a2d42011-09-25 08:25:12 +00003786 break;
3787 }
3788 case 'l':
3789 {
anthonyafa3dfc2012-03-03 11:31:30 +00003790 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003791 {
anthony805a2d42011-09-25 08:25:12 +00003792 ImageLayerMethod
3793 method;
3794
anthony805a2d42011-09-25 08:25:12 +00003795 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
anthony31f1bf72012-01-30 12:37:22 +00003796 MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00003797 switch (method)
3798 {
3799 case CoalesceLayer:
3800 {
anthony31f1bf72012-01-30 12:37:22 +00003801 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003802 break;
3803 }
3804 case CompareAnyLayer:
3805 case CompareClearLayer:
3806 case CompareOverlayLayer:
3807 default:
3808 {
anthony31f1bf72012-01-30 12:37:22 +00003809 new_images=CompareImagesLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003810 break;
3811 }
3812 case MergeLayer:
3813 case FlattenLayer:
3814 case MosaicLayer:
3815 case TrimBoundsLayer:
3816 {
anthony31f1bf72012-01-30 12:37:22 +00003817 new_images=MergeImageLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003818 break;
3819 }
3820 case DisposeLayer:
3821 {
anthony31f1bf72012-01-30 12:37:22 +00003822 new_images=DisposeImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003823 break;
3824 }
3825 case OptimizeImageLayer:
3826 {
anthony31f1bf72012-01-30 12:37:22 +00003827 new_images=OptimizeImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003828 break;
3829 }
3830 case OptimizePlusLayer:
3831 {
anthony31f1bf72012-01-30 12:37:22 +00003832 new_images=OptimizePlusImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003833 break;
3834 }
3835 case OptimizeTransLayer:
3836 {
anthony31f1bf72012-01-30 12:37:22 +00003837 OptimizeImageTransparency(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003838 break;
3839 }
3840 case RemoveDupsLayer:
3841 {
anthony31f1bf72012-01-30 12:37:22 +00003842 RemoveDuplicateLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003843 break;
3844 }
3845 case RemoveZeroLayer:
3846 {
anthony31f1bf72012-01-30 12:37:22 +00003847 RemoveZeroDelayLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003848 break;
3849 }
3850 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003851 { /* General Purpose, GIF Animation Optimizer. */
3852 new_images=CoalesceImages(images,exception);
3853 if (new_images == (Image *) NULL)
3854 break;
3855 images=DestroyImageList(images);
3856 images=OptimizeImageLayers(new_images,exception);
3857 if (images == (Image *) NULL)
3858 break;
3859 new_images=DestroyImageList(new_images);
3860 OptimizeImageTransparency(images,exception);
3861 (void) RemapImages(quantize_info,images,(Image *) NULL,
anthony805a2d42011-09-25 08:25:12 +00003862 exception);
3863 break;
3864 }
3865 case CompositeLayer:
3866 {
anthony805a2d42011-09-25 08:25:12 +00003867 Image
3868 *source;
3869
3870 RectangleInfo
3871 geometry;
3872
anthony31f1bf72012-01-30 12:37:22 +00003873 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003874 compose;
3875
3876 const char*
3877 value;
3878
3879 value=GetImageOption(image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003880 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003881 if (value != (const char *) NULL)
3882 compose=(CompositeOperator) ParseCommandOption(
3883 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003884
anthony31f1bf72012-01-30 12:37:22 +00003885 /* Split image sequence at the first 'NULL:' image. */
3886 source=images;
anthony805a2d42011-09-25 08:25:12 +00003887 while (source != (Image *) NULL)
3888 {
3889 source=GetNextImageInList(source);
3890 if ((source != (Image *) NULL) &&
3891 (LocaleCompare(source->magick,"NULL") == 0))
3892 break;
3893 }
3894 if (source != (Image *) NULL)
3895 {
3896 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3897 (GetNextImageInList(source) == (Image *) NULL))
3898 source=(Image *) NULL;
3899 else
anthony31f1bf72012-01-30 12:37:22 +00003900 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003901 source=SplitImageList(source->previous);
3902 DeleteImageFromList(&source);
3903 }
3904 }
3905 if (source == (Image *) NULL)
3906 {
3907 (void) ThrowMagickException(exception,GetMagickModule(),
3908 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003909 break;
3910 }
anthony31f1bf72012-01-30 12:37:22 +00003911 /* Adjust offset with gravity and virtual canvas. */
3912 SetGeometry(images,&geometry);
3913 (void) ParseAbsoluteGeometry(images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003914 geometry.width=source->page.width != 0 ?
3915 source->page.width : source->columns;
3916 geometry.height=source->page.height != 0 ?
3917 source->page.height : source->rows;
anthony31f1bf72012-01-30 12:37:22 +00003918 GravityAdjustGeometry(images->page.width != 0 ?
3919 images->page.width : images->columns,
3920 images->page.height != 0 ? images->page.height :
3921 images->rows,images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003922
anthony31f1bf72012-01-30 12:37:22 +00003923 /* Compose the two image sequences together */
3924 CompositeLayers(images,compose,source,geometry.x,geometry.y,
anthony805a2d42011-09-25 08:25:12 +00003925 exception);
3926 source=DestroyImageList(source);
3927 break;
3928 }
3929 }
anthony805a2d42011-09-25 08:25:12 +00003930 break;
3931 }
anthonyafa3dfc2012-03-03 11:31:30 +00003932 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00003933 {
3934 MagickSizeType
3935 limit;
3936
3937 ResourceType
3938 type;
3939
anthony72feaa62012-01-17 06:46:23 +00003940 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
anthony31f1bf72012-01-30 12:37:22 +00003941 MagickFalse,arg1);
anthony72feaa62012-01-17 06:46:23 +00003942 limit=MagickResourceInfinity;
anthony31f1bf72012-01-30 12:37:22 +00003943 if (LocaleCompare("unlimited",arg2) != 0)
3944 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthony72feaa62012-01-17 06:46:23 +00003945 (void) SetMagickResourceLimit(type,limit);
3946 break;
3947 }
anthony805a2d42011-09-25 08:25:12 +00003948 break;
3949 }
3950 case 'm':
3951 {
anthonyafa3dfc2012-03-03 11:31:30 +00003952 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003953 {
anthony31f1bf72012-01-30 12:37:22 +00003954 /* DEPRECIATED use +remap */
3955 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00003956 break;
3957 }
anthonyafa3dfc2012-03-03 11:31:30 +00003958 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003959 {
3960 Image
3961 *morph_image;
3962
anthony31f1bf72012-01-30 12:37:22 +00003963 morph_image=MorphImages(images,StringToUnsignedLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00003964 exception);
3965 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003966 break;
3967 images=DestroyImageList(images);
3968 images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00003969 break;
3970 }
anthonyafa3dfc2012-03-03 11:31:30 +00003971 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003972 {
anthony319dac62012-03-06 04:12:44 +00003973 /* REDIRECTED to use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003974 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003975 break;
3976 }
3977 break;
3978 }
3979 case 'p':
3980 {
anthonyafa3dfc2012-03-03 11:31:30 +00003981 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003982 {
3983 char
3984 *string;
3985
anthony31f1bf72012-01-30 12:37:22 +00003986 string=InterpretImageProperties(image_info,images,arg1,
anthony805a2d42011-09-25 08:25:12 +00003987 exception);
3988 if (string == (char *) NULL)
3989 break;
3990 (void) FormatLocaleFile(stdout,"%s",string);
3991 string=DestroyString(string);
3992 }
anthonyafa3dfc2012-03-03 11:31:30 +00003993 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003994 {
3995 char
3996 **arguments;
3997
3998 int
3999 j,
4000 number_arguments;
4001
anthony31f1bf72012-01-30 12:37:22 +00004002 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004003 if (arguments == (char **) NULL)
4004 break;
anthony31f1bf72012-01-30 12:37:22 +00004005 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004006 {
4007 char
4008 breaker,
4009 quote,
4010 *token;
4011
4012 const char
4013 *arguments;
4014
4015 int
4016 next,
4017 status;
4018
4019 size_t
4020 length;
4021
4022 TokenInfo
4023 *token_info;
4024
4025 /*
4026 Support old style syntax, filter="-option arg".
4027 */
anthony31f1bf72012-01-30 12:37:22 +00004028 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004029 token=(char *) NULL;
4030 if (~length >= (MaxTextExtent-1))
4031 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4032 sizeof(*token));
4033 if (token == (char *) NULL)
4034 break;
4035 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004036 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004037 token_info=AcquireTokenInfo();
4038 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4039 "\"",'\0',&breaker,&next,&quote);
4040 token_info=DestroyTokenInfo(token_info);
4041 if (status == 0)
4042 {
4043 const char
4044 *argv;
4045
4046 argv=(&(arguments[next]));
anthony31f1bf72012-01-30 12:37:22 +00004047 (void) InvokeDynamicImageFilter(token,&images,1,&argv,
anthony805a2d42011-09-25 08:25:12 +00004048 exception);
4049 }
4050 token=DestroyString(token);
4051 break;
4052 }
4053 (void) SubstituteString(&arguments[1],"-","");
anthony31f1bf72012-01-30 12:37:22 +00004054 (void) InvokeDynamicImageFilter(arguments[1],&images,
anthony805a2d42011-09-25 08:25:12 +00004055 number_arguments-2,(const char **) arguments+2,exception);
4056 for (j=0; j < number_arguments; j++)
4057 arguments[j]=DestroyString(arguments[j]);
4058 arguments=(char **) RelinquishMagickMemory(arguments);
4059 break;
4060 }
4061 break;
4062 }
4063 case 'r':
4064 {
anthonyafa3dfc2012-03-03 11:31:30 +00004065 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004066 {
anthony31f1bf72012-01-30 12:37:22 +00004067 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
4068 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
4069 break;
4070 }
anthonyafa3dfc2012-03-03 11:31:30 +00004071 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004072 {
4073 ReverseImageList(&images);
anthony805a2d42011-09-25 08:25:12 +00004074 break;
4075 }
4076 break;
4077 }
4078 case 's':
4079 {
anthonyafa3dfc2012-03-03 11:31:30 +00004080 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004081 {
4082 Image
4083 *smush_image;
4084
4085 ssize_t
4086 offset;
4087
anthony31f1bf72012-01-30 12:37:22 +00004088 offset=(ssize_t) StringToLong(arg1);
4089 smush_image=SmushImages(images,normal_op,offset,exception);
anthony805a2d42011-09-25 08:25:12 +00004090 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004091 break;
4092 images=DestroyImageList(images);
4093 images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004094 break;
4095 }
anthonyafa3dfc2012-03-03 11:31:30 +00004096 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004097 {
4098 Image
4099 *p,
4100 *q,
4101 *swap;
4102
4103 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004104 index,
anthony805a2d42011-09-25 08:25:12 +00004105 swap_index;
4106
anthony31f1bf72012-01-30 12:37:22 +00004107 index=-1;
4108 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004109 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004110 {
4111 GeometryInfo
4112 geometry_info;
4113
4114 MagickStatusType
4115 flags;
4116
4117 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004118 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004119 index=(ssize_t) geometry_info.rho;
4120 if ((flags & SigmaValue) != 0)
4121 swap_index=(ssize_t) geometry_info.sigma;
4122 }
anthony31f1bf72012-01-30 12:37:22 +00004123 p=GetImageFromList(images,index);
4124 q=GetImageFromList(images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004125 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4126 {
4127 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +00004128 OptionError,"NoSuchImage","'%s'",images->filename);
anthony805a2d42011-09-25 08:25:12 +00004129 break;
4130 }
4131 if (p == q)
4132 break;
4133 swap=CloneImage(p,0,0,MagickTrue,exception);
4134 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4135 ReplaceImageInList(&q,swap);
anthony31f1bf72012-01-30 12:37:22 +00004136 images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004137 break;
4138 }
4139 break;
4140 }
4141 case 'w':
4142 {
anthonyafa3dfc2012-03-03 11:31:30 +00004143 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004144 {
4145 char
4146 key[MaxTextExtent];
4147
4148 Image
4149 *write_images;
4150
4151 ImageInfo
4152 *write_info;
4153
anthony31f1bf72012-01-30 12:37:22 +00004154 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004155 (void) DeleteImageRegistry(key);
anthony31f1bf72012-01-30 12:37:22 +00004156 write_images=images;
anthonyafa3dfc2012-03-03 11:31:30 +00004157 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00004158 write_images=CloneImageList(images,exception);
anthony805a2d42011-09-25 08:25:12 +00004159 write_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00004160 (void) WriteImages(write_info,write_images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00004161 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004162 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004163 write_images=DestroyImageList(write_images);
4164 break;
4165 }
4166 break;
4167 }
4168 default:
4169 break;
4170 }
anthony31f1bf72012-01-30 12:37:22 +00004171 if (new_images == (Image *) NULL)
4172 return;
anthony805a2d42011-09-25 08:25:12 +00004173
anthony31f1bf72012-01-30 12:37:22 +00004174 if (images != (Image *) NULL)
4175 images=DestroyImageList(images);
anthony43f425d2012-02-26 12:58:58 +00004176 images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004177 return;
4178
4179#undef image_info
anthony31f1bf72012-01-30 12:37:22 +00004180#undef images
4181#undef exception
anthony43f425d2012-02-26 12:58:58 +00004182#undef draw_info
4183#undef quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004184#undef IfNormalOp
4185#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004186#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004187}
anthony43f425d2012-02-26 12:58:58 +00004188
4189/*
4190%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4191% %
4192% %
4193% %
4194+ C L I S p e c i a l O p e r a t i o n s %
4195% %
4196% %
4197% %
4198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4199%
4200% CLISpecialOption() Applies operations that may involve empty image lists
4201% and or stacks of image lists or image_info settings.
4202%
anthonyafa3dfc2012-03-03 11:31:30 +00004203% The classic operators of this type is -read, and image stack operators,
4204% which can be applied to empty image lists.
4205%
4206% Note: unlike other Operators, these may involve other special 'option'
4207% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004208%
4209% The format of the CLISpecialOption method is:
4210%
4211% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
4212% const char *arg)
4213%
4214% A description of each parameter follows:
4215%
4216% o cli_wand: the main CLI Wand to use.
4217%
4218% o option: The special option (with any switch char) to process
4219%
4220% o arg: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004221%
anthony2052d272012-02-28 12:48:29 +00004222% Example Usage...
4223%
4224% CLISpecialOperator(cli_wand,"-read", "rose:");
anthony2052d272012-02-28 12:48:29 +00004225%
4226% Or for handling command line arguments EG: +/-option ["arg"]
4227%
4228% cli_wand
4229% argc,argv
4230% i=index in argv
4231%
4232% option_info = GetCommandOptionInfo(argv[i]);
4233% count=option_info->type;
4234% option_type=option_info->flags;
4235%
4236% if ( (option_type & SpecialOptionFlag) != 0 )
4237% CLISpecialOperator(cli_wand,argv[i],
4238% count>=1 ? argv[i+1] : (char *)NULL);
4239% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004240%
4241*/
4242
anthony43f425d2012-02-26 12:58:58 +00004243WandExport void CLISpecialOperator(MagickCLI *cli_wand,
4244 const char *option, const char *arg)
4245{
4246#define exception (cli_wand->wand.exception)
4247
4248 assert(cli_wand != (MagickCLI *) NULL);
4249 assert(cli_wand->signature == WandSignature);
4250 assert(cli_wand->wand.signature == WandSignature);
4251 if (cli_wand->wand.debug != MagickFalse)
4252 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4253
anthonyafa3dfc2012-03-03 11:31:30 +00004254 if (LocaleCompare("(",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004255 {
4256 /* stack 'push' images */
4257 Stack
4258 *node;
4259
4260 size_t
4261 size;
4262
4263 const char*
4264 value;
4265
4266 size=0;
4267 node=cli_wand->image_list_stack;
4268 for ( ; node != (Stack *)NULL; node=node->next)
4269 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004270 if ( size >= MAX_STACK_DEPTH )
anthony43f425d2012-02-26 12:58:58 +00004271 {
4272 ThrowMagickException(exception,GetMagickModule(),
4273 OptionError,"ParenthesisNestedTooDeeply", option);
4274 return;
4275 }
4276 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4277 if (node == (Stack *) NULL)
4278 {
4279 ThrowMagickException(exception,GetMagickModule(),
4280 ResourceLimitFatalError,"MemoryAllocationFailed", "PushImages");
4281 return;
4282 }
4283 node->data = (void *)cli_wand->wand.images;
4284 cli_wand->wand.images = NewImageList();
4285 node->next = cli_wand->image_list_stack;
4286 cli_wand->image_list_stack = node;
4287
4288 /* handle respect-parenthesis */
4289 value=GetImageOption(cli_wand->wand.image_info,"respect-parenthesis");
4290 if (value != (const char *) NULL)
4291 option="{";
4292 else
4293 return;
4294 }
anthonyafa3dfc2012-03-03 11:31:30 +00004295 if (LocaleCompare("{",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004296 {
4297 /* stack 'push' of image_info settings */
4298 Stack
4299 *node;
4300
4301 size_t
4302 size;
4303
4304 size=0;
4305 node=cli_wand->image_info_stack;
4306 for ( ; node != (Stack *)NULL; node=node->next)
4307 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004308 if ( size >= MAX_STACK_DEPTH ) {
4309 ThrowMagickException(exception,GetMagickModule(),
4310 OptionError,"ParenthesisNestedTooDeeply", option);
4311 return;
4312 }
anthony43f425d2012-02-26 12:58:58 +00004313 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthonyafa3dfc2012-03-03 11:31:30 +00004314 if (node == (Stack *) NULL) {
4315 ThrowMagickException(exception,GetMagickModule(),
4316 ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
4317 return;
4318 }
anthony43f425d2012-02-26 12:58:58 +00004319
4320 node->data = (void *)cli_wand->wand.image_info;
4321 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004322 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4323 ThrowMagickException(exception,GetMagickModule(),
4324 ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
4325 cli_wand->wand.image_info = (ImageInfo *)node->data;
4326 node = (Stack *)RelinquishMagickMemory(node);
4327 return;
4328 }
anthony43f425d2012-02-26 12:58:58 +00004329
4330 node->next = cli_wand->image_info_stack;
4331 cli_wand->image_info_stack = node;
4332
4333 return;
4334 }
anthonyafa3dfc2012-03-03 11:31:30 +00004335 if (LocaleCompare(")",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004336 {
4337 /* pop images from stack */
4338 Stack
4339 *node;
4340
4341 const char*
4342 value;
4343
4344 node = (void *)cli_wand->image_list_stack;
4345 if ( node == (Stack *)NULL)
4346 {
4347 ThrowMagickException(exception,GetMagickModule(),
4348 OptionError,"UnbalancedParenthesis", option);
4349 return;
4350 }
4351 cli_wand->image_list_stack = node->next;
4352
4353 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4354 cli_wand->wand.images= (Image *)node->data;
4355 node = (Stack *)RelinquishMagickMemory(node);
4356
4357 /* handle respect-parenthesis - of the previous 'push' settings */
4358 node = cli_wand->image_info_stack;
4359 if ( node != (Stack *)NULL)
4360 {
4361 value=GetImageOption((ImageInfo *)node->data,"respect-parenthesis");
4362 if (value != (const char *) NULL)
4363 option="}";
4364 else
4365 return;
4366 }
4367 else
4368 return;
4369 }
anthonyafa3dfc2012-03-03 11:31:30 +00004370 if (LocaleCompare("}",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004371 {
4372 /* pop image_info settings from stack */
4373 Stack
4374 *node;
4375
4376 node = (void *)cli_wand->image_info_stack;
4377 if ( node == (Stack *)NULL)
4378 {
4379 ThrowMagickException(exception,GetMagickModule(),
4380 OptionError,"UnbalancedParenthesis", option);
4381 return;
4382 }
4383 cli_wand->image_info_stack = node->next;
4384
4385 (void) DestroyImageInfo(cli_wand->wand.image_info);
4386 cli_wand->wand.image_info = (ImageInfo *)node->data;
4387 node = (Stack *)RelinquishMagickMemory(node);
4388
4389 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4390 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4391 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4392
4393 return;
4394 }
anthonyafa3dfc2012-03-03 11:31:30 +00004395 if (LocaleCompare("clone",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004396 {
4397 Image
4398 *new_images;
4399
4400 if (*option == '+')
4401 arg="-1";
4402 if (IsSceneGeometry(arg,MagickFalse) == MagickFalse)
4403 {
4404 ThrowMagickException(exception,GetMagickModule(),
4405 OptionError,"InvalidArgument", "'%s': %s", option, arg);
4406 return;
4407 }
4408 if ( cli_wand->image_list_stack == (Stack *)NULL)
4409 {
4410 ThrowMagickException(exception,GetMagickModule(),
4411 OptionError,"UnableToCloneImage", option);
4412 return;
4413 }
4414 new_images = (Image *)cli_wand->image_list_stack->data;
4415 if (new_images == (Image *) NULL)
4416 {
4417 ThrowMagickException(exception,GetMagickModule(),
4418 OptionError,"UnableToCloneImage", option);
4419 return;
4420 }
4421 new_images=CloneImages(new_images,arg,exception);
4422 if (new_images == (Image *) NULL)
4423 {
4424 ThrowMagickException(exception,GetMagickModule(),
4425 OptionError,"NoSuchImage",option);
4426 return;
4427 }
4428 AppendImageToList(&cli_wand->wand.images,new_images);
4429 return;
4430 }
anthony319dac62012-03-06 04:12:44 +00004431 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4432 ( LocaleCompare("--",option) == 0 ) )
anthony43f425d2012-02-26 12:58:58 +00004433 {
anthonyafa3dfc2012-03-03 11:31:30 +00004434#if !USE_WAND_METHODS
anthony43f425d2012-02-26 12:58:58 +00004435 Image *
4436 new_images;
4437
anthony43f425d2012-02-26 12:58:58 +00004438 if (cli_wand->wand.image_info->ping != MagickFalse)
anthonyafa3dfc2012-03-03 11:31:30 +00004439 new_images=PingImages(cli_wand->wand.image_info,arg,exception);
anthony43f425d2012-02-26 12:58:58 +00004440 else
anthonyafa3dfc2012-03-03 11:31:30 +00004441 new_images=ReadImages(cli_wand->wand.image_info,arg,exception);
anthony43f425d2012-02-26 12:58:58 +00004442 AppendImageToList(&cli_wand->wand.images, new_images);
4443#else
4444 /* read images using MagickWand method - no ping */
4445 /* This is not working! - it locks up in a CPU loop! */
4446 MagickSetLastIterator(&cli_wand->wand);
4447 MagickReadImage(&cli_wand->wand,arg);
4448 MagickSetFirstIterator(&cli_wand->wand);
4449#endif
4450 return;
4451 }
anthonyafa3dfc2012-03-03 11:31:30 +00004452 /* No-op options */
4453 if (LocaleCompare("noop",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004454 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004455 if (LocaleCompare("sans",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004456 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004457 if (LocaleCompare("sans0",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004458 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004459 if (LocaleCompare("sans2",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004460 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004461 if (LocaleCompare("list",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004462 {
4463 /* FUTURE: This should really be built into the MagickCore
4464 It does not actually require any wand or images at all!
4465 */
4466 ssize_t
4467 list;
4468
4469 list=ParseCommandOption(MagickListOptions,MagickFalse, arg);
4470 switch (list)
4471 {
4472 case MagickCoderOptions:
4473 {
4474 (void) ListCoderInfo((FILE *) NULL,exception);
4475 break;
4476 }
4477 case MagickColorOptions:
4478 {
4479 (void) ListColorInfo((FILE *) NULL,exception);
4480 break;
4481 }
4482 case MagickConfigureOptions:
4483 {
4484 (void) ListConfigureInfo((FILE *) NULL,exception);
4485 break;
4486 }
4487 case MagickDelegateOptions:
4488 {
4489 (void) ListDelegateInfo((FILE *) NULL,exception);
4490 break;
4491 }
4492 case MagickFontOptions:
4493 {
4494 (void) ListTypeInfo((FILE *) NULL,exception);
4495 break;
4496 }
4497 case MagickFormatOptions:
4498 (void) ListMagickInfo((FILE *) NULL,exception);
4499 break;
4500 case MagickLocaleOptions:
4501 (void) ListLocaleInfo((FILE *) NULL,exception);
4502 break;
4503 case MagickLogOptions:
4504 (void) ListLogInfo((FILE *) NULL,exception);
4505 break;
4506 case MagickMagicOptions:
4507 (void) ListMagicInfo((FILE *) NULL,exception);
4508 break;
4509 case MagickMimeOptions:
4510 (void) ListMimeInfo((FILE *) NULL,exception);
4511 break;
4512 case MagickModuleOptions:
4513 (void) ListModuleInfo((FILE *) NULL,exception);
4514 break;
4515 case MagickPolicyOptions:
4516 (void) ListPolicyInfo((FILE *) NULL,exception);
4517 break;
4518 case MagickResourceOptions:
4519 (void) ListMagickResourceInfo((FILE *) NULL,exception);
4520 break;
4521 case MagickThresholdOptions:
4522 (void) ListThresholdMaps((FILE *) NULL,exception);
4523 break;
4524 default:
4525 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4526 exception);
4527 break;
4528 }
4529 return;
4530 }
4531
4532#if 0
4533 // adjust stack handling
4534 // Other 'special' options this should handle
4535 // "region" "list" "version"
4536 // It does not do "exit" however as due to its side-effect requirements
4537#endif
4538#if 0
4539 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
4540 MagickExceptionReturn(OptionError,"InvalidUseOfOption",option);
4541#endif
4542
4543#undef image_info
4544#undef images
4545#undef exception
4546}