blob: 59ecb75fc8a949915956c57a9b8dfb42d40c1ead [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";
anthony1cdc5b72012-03-03 02:31:18 +0000427 cli_wand->filename="";
428 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("channel-extract",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00001889 {
1890 puts("stand by...");
1891 break;
1892 }
anthonyafa3dfc2012-03-03 11:31:30 +00001893 if (LocaleCompare("channel-swap",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00001894 {
1895 puts("stand by...");
1896 break;
1897 }
anthonyafa3dfc2012-03-03 11:31:30 +00001898 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001899 {
anthonyfd706f92012-01-19 04:22:02 +00001900 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001901 if ((flags & SigmaValue) == 0)
1902 geometry_info.sigma=1.0;
1903 if ((flags & XiValue) == 0)
1904 geometry_info.xi=1.0;
anthony31f1bf72012-01-30 12:37:22 +00001905 new_image=CharcoalImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001906 geometry_info.sigma,geometry_info.xi,exception);
1907 break;
1908 }
anthonyafa3dfc2012-03-03 11:31:30 +00001909 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001910 {
anthony31f1bf72012-01-30 12:37:22 +00001911 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
1912 new_image=ChopImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001913 break;
1914 }
anthonyafa3dfc2012-03-03 11:31:30 +00001915 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001916 {
anthony31f1bf72012-01-30 12:37:22 +00001917 (void) ClampImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001918 break;
1919 }
anthonyafa3dfc2012-03-03 11:31:30 +00001920 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001921 {
anthonyafa3dfc2012-03-03 11:31:30 +00001922 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00001923 (void) ClipImage(image,exception);
anthony43f425d2012-02-26 12:58:58 +00001924 else /* "+mask" remove the write mask */
anthony31f1bf72012-01-30 12:37:22 +00001925 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00001926 break;
1927 }
anthonyafa3dfc2012-03-03 11:31:30 +00001928 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001929 {
1930 CacheView
1931 *mask_view;
1932
1933 Image
1934 *mask_image;
1935
1936 register Quantum
1937 *restrict q;
1938
1939 register ssize_t
1940 x;
1941
1942 ssize_t
1943 y;
1944
anthonyafa3dfc2012-03-03 11:31:30 +00001945 if (IfPlusOp) {
1946 /* "+clip-mask" Remove the write mask */
1947 (void) SetImageMask(image,(Image *) NULL,exception);
1948 break;
1949 }
anthonyfd706f92012-01-19 04:22:02 +00001950 mask_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001951 if (mask_image == (Image *) NULL)
1952 break;
anthonyfd706f92012-01-19 04:22:02 +00001953 if (SetImageStorageClass(mask_image,DirectClass,exception)
1954 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001955 break;
anthony43f425d2012-02-26 12:58:58 +00001956 /* Create a write mask from cli_wandp-mask image */
anthonyfd706f92012-01-19 04:22:02 +00001957 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00001958 mask_view=AcquireCacheView(mask_image);
1959 for (y=0; y < (ssize_t) mask_image->rows; y++)
1960 {
1961 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1962 exception);
1963 if (q == (Quantum *) NULL)
1964 break;
1965 for (x=0; x < (ssize_t) mask_image->columns; x++)
1966 {
1967 if (mask_image->matte == MagickFalse)
1968 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1969 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1970 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1971 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1972 q+=GetPixelChannels(mask_image);
1973 }
1974 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1975 break;
1976 }
anthonyfd706f92012-01-19 04:22:02 +00001977 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001978 mask_view=DestroyCacheView(mask_view);
1979 mask_image->matte=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00001980 (void) SetImageMask(image,mask_image,exception);
anthony805a2d42011-09-25 08:25:12 +00001981 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00001982 break;
1983 }
anthonyafa3dfc2012-03-03 11:31:30 +00001984 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001985 {
anthonyafa3dfc2012-03-03 11:31:30 +00001986 (void) ClipImagePath(image,arg1,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00001987 break;
1988 }
anthonyafa3dfc2012-03-03 11:31:30 +00001989 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001990 {
anthony31f1bf72012-01-30 12:37:22 +00001991 new_image=ColorizeImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00001992 break;
1993 }
anthonyafa3dfc2012-03-03 11:31:30 +00001994 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001995 {
1996 KernelInfo
1997 *kernel;
1998
anthonyfd706f92012-01-19 04:22:02 +00001999 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002000 if (kernel == (KernelInfo *) NULL)
2001 break;
anthony31f1bf72012-01-30 12:37:22 +00002002 new_image=ColorMatrixImage(image,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00002003 kernel=DestroyKernelInfo(kernel);
2004 break;
2005 }
anthonyafa3dfc2012-03-03 11:31:30 +00002006 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002007 {
anthonyfd706f92012-01-19 04:22:02 +00002008 /* Reduce the number of colors in the image.
2009 FUTURE: also provide 'plus version with image 'color counts'
2010 */
2011 quantize_info->number_colors=StringToUnsignedLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00002012 if (quantize_info->number_colors == 0)
2013 break;
anthony31f1bf72012-01-30 12:37:22 +00002014 if ((image->storage_class == DirectClass) ||
2015 image->colors > quantize_info->number_colors)
2016 (void) QuantizeImage(quantize_info,image,exception);
anthony805a2d42011-09-25 08:25:12 +00002017 else
anthony31f1bf72012-01-30 12:37:22 +00002018 (void) CompressImageColormap(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002019 break;
2020 }
anthonyafa3dfc2012-03-03 11:31:30 +00002021 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002022 {
anthony31f1bf72012-01-30 12:37:22 +00002023 /* WARNING: this is both a image_info setting (already done)
2024 and a operator to change image colorspace.
2025
2026 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002027 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002028
anthonyd2cdc862011-10-07 14:07:17 +00002029 Note that +colorspace sets "undefined" or no effect on
2030 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002031 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002032 */
anthony31f1bf72012-01-30 12:37:22 +00002033 (void) TransformImageColorspace(image,
anthonyafa3dfc2012-03-03 11:31:30 +00002034 IfNormalOp ? image_info->colorspace : RGBColorspace,
anthony6613bf32011-10-15 07:24:44 +00002035 exception);
anthony805a2d42011-09-25 08:25:12 +00002036 break;
2037 }
anthonyafa3dfc2012-03-03 11:31:30 +00002038 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002039 {
anthonyafa3dfc2012-03-03 11:31:30 +00002040 (void) ContrastImage(image,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002041 break;
2042 }
anthonyafa3dfc2012-03-03 11:31:30 +00002043 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002044 {
2045 double
2046 black_point,
2047 white_point;
2048
2049 MagickStatusType
2050 flags;
2051
anthonyfd706f92012-01-19 04:22:02 +00002052 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002053 black_point=geometry_info.rho;
2054 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2055 black_point;
2056 if ((flags & PercentValue) != 0)
2057 {
anthony31f1bf72012-01-30 12:37:22 +00002058 black_point*=(double) image->columns*image->rows/100.0;
2059 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002060 }
anthony31f1bf72012-01-30 12:37:22 +00002061 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00002062 white_point;
anthony31f1bf72012-01-30 12:37:22 +00002063 (void) ContrastStretchImage(image,black_point,white_point,
anthony805a2d42011-09-25 08:25:12 +00002064 exception);
anthony805a2d42011-09-25 08:25:12 +00002065 break;
2066 }
anthonyafa3dfc2012-03-03 11:31:30 +00002067 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002068 {
2069 KernelInfo
2070 *kernel_info;
2071
anthonyfd706f92012-01-19 04:22:02 +00002072 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002073 if (kernel_info == (KernelInfo *) NULL)
2074 break;
anthony31f1bf72012-01-30 12:37:22 +00002075 kernel_info->bias=image->bias;
2076 new_image=ConvolveImage(image,kernel_info,exception);
anthony805a2d42011-09-25 08:25:12 +00002077 kernel_info=DestroyKernelInfo(kernel_info);
2078 break;
2079 }
anthonyafa3dfc2012-03-03 11:31:30 +00002080 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002081 {
anthony31f1bf72012-01-30 12:37:22 +00002082 /* WARNING: This can generate multiple images! */
2083 new_image=CropImageToTiles(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002084 break;
2085 }
anthonyafa3dfc2012-03-03 11:31:30 +00002086 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002087 {
anthony31f1bf72012-01-30 12:37:22 +00002088 (void) CycleColormapImage(image,(ssize_t) StringToLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00002089 exception);
2090 break;
2091 }
2092 break;
2093 }
2094 case 'd':
2095 {
anthonyafa3dfc2012-03-03 11:31:30 +00002096 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002097 {
2098 StringInfo
2099 *passkey;
2100
anthonyfd706f92012-01-19 04:22:02 +00002101 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00002102 if (passkey != (StringInfo *) NULL)
2103 {
anthony31f1bf72012-01-30 12:37:22 +00002104 (void) PasskeyDecipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00002105 passkey=DestroyStringInfo(passkey);
2106 }
2107 break;
2108 }
anthonyafa3dfc2012-03-03 11:31:30 +00002109 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002110 {
anthonydcf510d2011-10-30 13:51:40 +00002111 /* The image_info->depth setting has already been set
2112 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002113
anthonydcf510d2011-10-30 13:51:40 +00002114 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2115 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002116
anthonyfd706f92012-01-19 04:22:02 +00002117 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002118 */
anthony31f1bf72012-01-30 12:37:22 +00002119 (void) SetImageDepth(image,image_info->depth,exception);
anthony805a2d42011-09-25 08:25:12 +00002120 break;
2121 }
anthonyafa3dfc2012-03-03 11:31:30 +00002122 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002123 {
2124 double
2125 threshold;
2126
anthonyafa3dfc2012-03-03 11:31:30 +00002127 if (IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00002128 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyafa3dfc2012-03-03 11:31:30 +00002129 else
2130 threshold=40.0*QuantumRange/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002131 new_image=DeskewImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00002132 break;
2133 }
anthonyafa3dfc2012-03-03 11:31:30 +00002134 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002135 {
anthony31f1bf72012-01-30 12:37:22 +00002136 new_image=DespeckleImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002137 break;
2138 }
anthonyafa3dfc2012-03-03 11:31:30 +00002139 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002140 {
2141 char
2142 *args,
2143 token[MaxTextExtent];
2144
2145 const char
2146 *p;
2147
2148 DistortImageMethod
2149 method;
2150
2151 double
2152 *arguments;
2153
2154 register ssize_t
2155 x;
2156
2157 size_t
2158 number_arguments;
2159
anthony805a2d42011-09-25 08:25:12 +00002160 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
anthonyfd706f92012-01-19 04:22:02 +00002161 MagickFalse,arg1);
anthony80c37752012-01-16 01:03:11 +00002162 if (method == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002163 {
anthony80c37752012-01-16 01:03:11 +00002164 double
2165 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002166 /* Special Case - Argument is actually a resize geometry!
2167 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002168 ** FUTURE: make a separate special resize operator
anthony805a2d42011-09-25 08:25:12 +00002169 */
anthony31f1bf72012-01-30 12:37:22 +00002170 (void) ParseRegionGeometry(image,arg2,&geometry,
anthony80c37752012-01-16 01:03:11 +00002171 exception);
2172 resize_args[0]=(double) geometry.width;
2173 resize_args[1]=(double) geometry.height;
anthony31f1bf72012-01-30 12:37:22 +00002174 new_image=DistortImage(image,method,(size_t)2,
anthony80c37752012-01-16 01:03:11 +00002175 resize_args,MagickTrue,exception);
anthony805a2d42011-09-25 08:25:12 +00002176 break;
2177 }
anthonyfd706f92012-01-19 04:22:02 +00002178 /* handle percent arguments */
anthony31f1bf72012-01-30 12:37:22 +00002179 args=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002180 exception);
2181 if (args == (char *) NULL)
2182 break;
anthonyfd706f92012-01-19 04:22:02 +00002183 /* convert arguments into an array of doubles
2184 FUTURE: make this a separate function.
2185 Also make use of new 'sentinal' feature to avoid need for
2186 tokenization.
2187 */
anthony805a2d42011-09-25 08:25:12 +00002188 p=(char *) args;
2189 for (x=0; *p != '\0'; x++)
2190 {
2191 GetMagickToken(p,&p,token);
2192 if (*token == ',')
2193 GetMagickToken(p,&p,token);
2194 }
2195 number_arguments=(size_t) x;
2196 arguments=(double *) AcquireQuantumMemory(number_arguments,
2197 sizeof(*arguments));
2198 if (arguments == (double *) NULL)
2199 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002200 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002201 (void) ResetMagickMemory(arguments,0,number_arguments*
2202 sizeof(*arguments));
2203 p=(char *) args;
2204 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2205 {
2206 GetMagickToken(p,&p,token);
2207 if (*token == ',')
2208 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002209 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002210 }
2211 args=DestroyString(args);
anthony31f1bf72012-01-30 12:37:22 +00002212 new_image=DistortImage(image,method,number_arguments,arguments,
anthonyfd706f92012-01-19 04:22:02 +00002213 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002214 arguments=(double *) RelinquishMagickMemory(arguments);
2215 break;
2216 }
anthonyafa3dfc2012-03-03 11:31:30 +00002217 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002218 {
anthonyfd706f92012-01-19 04:22:02 +00002219 (void) CloneString(&draw_info->primitive,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002220 (void) DrawImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00002221 (void) CloneString(&draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002222 break;
2223 }
2224 break;
2225 }
2226 case 'e':
2227 {
anthonyafa3dfc2012-03-03 11:31:30 +00002228 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002229 {
anthonyfd706f92012-01-19 04:22:02 +00002230 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002231 if ((flags & SigmaValue) == 0)
2232 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002233 new_image=EdgeImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002234 geometry_info.sigma,exception);
2235 break;
2236 }
anthonyafa3dfc2012-03-03 11:31:30 +00002237 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002238 {
anthonyfd706f92012-01-19 04:22:02 +00002239 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002240 if ((flags & SigmaValue) == 0)
2241 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002242 new_image=EmbossImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002243 geometry_info.sigma,exception);
2244 break;
2245 }
anthonyafa3dfc2012-03-03 11:31:30 +00002246 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002247 {
2248 StringInfo
2249 *passkey;
2250
anthonyfd706f92012-01-19 04:22:02 +00002251 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00002252 if (passkey != (StringInfo *) NULL)
2253 {
anthony31f1bf72012-01-30 12:37:22 +00002254 (void) PasskeyEncipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00002255 passkey=DestroyStringInfo(passkey);
2256 }
2257 break;
2258 }
anthonyafa3dfc2012-03-03 11:31:30 +00002259 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002260 {
anthony31f1bf72012-01-30 12:37:22 +00002261 new_image=EnhanceImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002262 break;
2263 }
anthonyafa3dfc2012-03-03 11:31:30 +00002264 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002265 {
anthony31f1bf72012-01-30 12:37:22 +00002266 (void) EqualizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002267 break;
2268 }
anthonyafa3dfc2012-03-03 11:31:30 +00002269 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002270 {
2271 double
2272 constant;
2273
2274 MagickEvaluateOperator
2275 op;
2276
anthony805a2d42011-09-25 08:25:12 +00002277 op=(MagickEvaluateOperator) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00002278 MagickEvaluateOptions,MagickFalse,arg1);
2279 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002280 (void) EvaluateImage(image,op,constant,exception);
anthony805a2d42011-09-25 08:25:12 +00002281 break;
2282 }
anthonyafa3dfc2012-03-03 11:31:30 +00002283 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002284 {
anthony31f1bf72012-01-30 12:37:22 +00002285 flags=ParseGravityGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002286 if (geometry.width == 0)
anthony31f1bf72012-01-30 12:37:22 +00002287 geometry.width=image->columns;
anthony805a2d42011-09-25 08:25:12 +00002288 if (geometry.height == 0)
anthony31f1bf72012-01-30 12:37:22 +00002289 geometry.height=image->rows;
2290 new_image=ExtentImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002291 break;
2292 }
2293 break;
2294 }
2295 case 'f':
2296 {
anthonyafa3dfc2012-03-03 11:31:30 +00002297 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002298 {
anthony31f1bf72012-01-30 12:37:22 +00002299 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002300 if (IfPlusOp) {
anthony31f1bf72012-01-30 12:37:22 +00002301 (void) DeleteImageArtifact(image,"identify:features");
2302 break;
2303 }
2304 (void) SetImageArtifact(image,"identify:features","true");
2305 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002306 break;
2307 }
anthonyafa3dfc2012-03-03 11:31:30 +00002308 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002309 {
anthony31f1bf72012-01-30 12:37:22 +00002310 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002311 break;
2312 }
anthonyafa3dfc2012-03-03 11:31:30 +00002313 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002314 {
anthony31f1bf72012-01-30 12:37:22 +00002315 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002316 break;
2317 }
anthonyafa3dfc2012-03-03 11:31:30 +00002318 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002319 {
2320 PixelInfo
2321 target;
2322
anthony31f1bf72012-01-30 12:37:22 +00002323 (void) ParsePageGeometry(image,arg1,&geometry,exception);
anthonyfd706f92012-01-19 04:22:02 +00002324 (void) QueryColorCompliance(arg2,AllCompliance,&target,exception);
anthony31f1bf72012-01-30 12:37:22 +00002325 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
anthonyfd706f92012-01-19 04:22:02 +00002326 geometry.y,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002327 break;
2328 }
anthonyafa3dfc2012-03-03 11:31:30 +00002329 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002330 {
2331 FrameInfo
2332 frame_info;
2333
anthony31f1bf72012-01-30 12:37:22 +00002334 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002335 compose;
2336
2337 const char*
2338 value;
2339
2340 value=GetImageOption(image_info,"compose");
2341 if (value != (const char *) NULL)
2342 compose=(CompositeOperator) ParseCommandOption(
2343 MagickComposeOptions,MagickFalse,value);
2344 else
2345 compose=OverCompositeOp; /* use Over not image->compose */
2346
anthony31f1bf72012-01-30 12:37:22 +00002347 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002348 frame_info.width=geometry.width;
2349 frame_info.height=geometry.height;
2350 if ((flags & HeightValue) == 0)
2351 frame_info.height=geometry.width;
2352 frame_info.outer_bevel=geometry.x;
2353 frame_info.inner_bevel=geometry.y;
2354 frame_info.x=(ssize_t) frame_info.width;
2355 frame_info.y=(ssize_t) frame_info.height;
anthony31f1bf72012-01-30 12:37:22 +00002356 frame_info.width=image->columns+2*frame_info.width;
2357 frame_info.height=image->rows+2*frame_info.height;
2358 new_image=FrameImage(image,&frame_info,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00002359 break;
2360 }
anthonyafa3dfc2012-03-03 11:31:30 +00002361 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002362 {
2363 char
2364 *arguments,
2365 token[MaxTextExtent];
2366
2367 const char
2368 *p;
2369
2370 double
2371 *parameters;
2372
2373 MagickFunction
2374 function;
2375
2376 register ssize_t
2377 x;
2378
2379 size_t
2380 number_parameters;
2381
cristy947cb4c2011-10-20 18:41:46 +00002382 /*
2383 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002384 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002385 */
anthony805a2d42011-09-25 08:25:12 +00002386 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
anthonyfd706f92012-01-19 04:22:02 +00002387 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002388 arguments=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002389 exception);
2390 if (arguments == (char *) NULL)
2391 break;
2392 p=(char *) arguments;
2393 for (x=0; *p != '\0'; x++)
2394 {
2395 GetMagickToken(p,&p,token);
2396 if (*token == ',')
2397 GetMagickToken(p,&p,token);
2398 }
2399 number_parameters=(size_t) x;
2400 parameters=(double *) AcquireQuantumMemory(number_parameters,
2401 sizeof(*parameters));
2402 if (parameters == (double *) NULL)
2403 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002404 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002405 (void) ResetMagickMemory(parameters,0,number_parameters*
2406 sizeof(*parameters));
2407 p=(char *) arguments;
2408 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2409 {
2410 GetMagickToken(p,&p,token);
2411 if (*token == ',')
2412 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002413 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002414 }
2415 arguments=DestroyString(arguments);
anthony31f1bf72012-01-30 12:37:22 +00002416 (void) FunctionImage(image,function,number_parameters,parameters,
anthony805a2d42011-09-25 08:25:12 +00002417 exception);
2418 parameters=(double *) RelinquishMagickMemory(parameters);
2419 break;
2420 }
2421 break;
2422 }
2423 case 'g':
2424 {
anthonyafa3dfc2012-03-03 11:31:30 +00002425 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002426 {
anthonyafa3dfc2012-03-03 11:31:30 +00002427 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00002428 (void) GammaImage(image,StringToDouble(arg1,(char **) NULL),
anthonyfd706f92012-01-19 04:22:02 +00002429 exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002430 else
2431 image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002432 break;
2433 }
anthonyafa3dfc2012-03-03 11:31:30 +00002434 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2435 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002436 {
anthonyfd706f92012-01-19 04:22:02 +00002437 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002438 if ((flags & SigmaValue) == 0)
2439 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002440 new_image=GaussianBlurImage(image,geometry_info.rho,
cristyd89705a2012-01-20 02:52:24 +00002441 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00002442 break;
2443 }
anthonyafa3dfc2012-03-03 11:31:30 +00002444 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002445 {
anthonyfd706f92012-01-19 04:22:02 +00002446 /*
anthony31f1bf72012-01-30 12:37:22 +00002447 Record Image offset for composition. (A Setting)
2448 Resize last image. (ListOperator)
2449 FUTURE: Why if no 'offset' does this resize ALL images?
2450 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002451 */
anthonyafa3dfc2012-03-03 11:31:30 +00002452 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002453 { /* remove the previous composition geometry offset! */
anthony31f1bf72012-01-30 12:37:22 +00002454 if (image->geometry != (char *) NULL)
2455 image->geometry=DestroyString(image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002456 break;
2457 }
anthony31f1bf72012-01-30 12:37:22 +00002458 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002459 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony31f1bf72012-01-30 12:37:22 +00002460 (void) CloneString(&image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002461 else
anthony31f1bf72012-01-30 12:37:22 +00002462 new_image=ResizeImage(image,geometry.width,geometry.height,
2463 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002464 break;
2465 }
anthony805a2d42011-09-25 08:25:12 +00002466 break;
2467 }
2468 case 'h':
2469 {
anthonyafa3dfc2012-03-03 11:31:30 +00002470 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002471 {
anthonyafa3dfc2012-03-03 11:31:30 +00002472 (void) SetImageArtifact(image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002473 break;
2474 }
2475 break;
2476 }
2477 case 'i':
2478 {
anthonyafa3dfc2012-03-03 11:31:30 +00002479 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002480 {
anthony31f1bf72012-01-30 12:37:22 +00002481 const char
2482 *format,
anthony805a2d42011-09-25 08:25:12 +00002483 *text;
2484
anthony31f1bf72012-01-30 12:37:22 +00002485 format=GetImageOption(image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002486 if (format == (char *) NULL)
2487 {
anthony31f1bf72012-01-30 12:37:22 +00002488 (void) IdentifyImage(image,stdout,image_info->verbose,
anthony805a2d42011-09-25 08:25:12 +00002489 exception);
2490 break;
2491 }
anthony31f1bf72012-01-30 12:37:22 +00002492 text=InterpretImageProperties(image_info,image,format,exception);
anthony805a2d42011-09-25 08:25:12 +00002493 if (text == (char *) NULL)
2494 break;
2495 (void) fputs(text,stdout);
2496 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002497 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002498 break;
2499 }
anthonyafa3dfc2012-03-03 11:31:30 +00002500 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002501 {
anthonyfd706f92012-01-19 04:22:02 +00002502 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002503 new_image=ImplodeImage(image,geometry_info.rho,
2504 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002505 break;
2506 }
anthonyafa3dfc2012-03-03 11:31:30 +00002507 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002508 {
anthony31f1bf72012-01-30 12:37:22 +00002509 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2510 new_image=InterpolativeResizeImage(image,geometry.width,
2511 geometry.height,image->interpolate,exception);
cristy947cb4c2011-10-20 18:41:46 +00002512 break;
2513 }
anthony805a2d42011-09-25 08:25:12 +00002514 break;
2515 }
2516 case 'l':
2517 {
anthonyafa3dfc2012-03-03 11:31:30 +00002518 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002519 {
anthonyfd706f92012-01-19 04:22:02 +00002520 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002521 if ((flags & PercentValue) != 0)
2522 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002523 new_image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
2524 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2525 exception);
anthony805a2d42011-09-25 08:25:12 +00002526 break;
2527 }
anthonyafa3dfc2012-03-03 11:31:30 +00002528 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002529 {
2530 MagickRealType
2531 black_point,
2532 gamma,
2533 white_point;
2534
2535 MagickStatusType
2536 flags;
2537
anthonyfd706f92012-01-19 04:22:02 +00002538 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002539 black_point=geometry_info.rho;
2540 white_point=(MagickRealType) QuantumRange;
2541 if ((flags & SigmaValue) != 0)
2542 white_point=geometry_info.sigma;
2543 gamma=1.0;
2544 if ((flags & XiValue) != 0)
2545 gamma=geometry_info.xi;
2546 if ((flags & PercentValue) != 0)
2547 {
2548 black_point*=(MagickRealType) (QuantumRange/100.0);
2549 white_point*=(MagickRealType) (QuantumRange/100.0);
2550 }
2551 if ((flags & SigmaValue) == 0)
2552 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002553 if (IfPlusOp || ((flags & AspectValue) != 0))
2554 (void) LevelizeImage(image,black_point,white_point,gamma,exception);
anthony805a2d42011-09-25 08:25:12 +00002555 else
anthonyafa3dfc2012-03-03 11:31:30 +00002556 (void) LevelImage(image,black_point,white_point,gamma,exception);
anthony805a2d42011-09-25 08:25:12 +00002557 break;
2558 }
anthonyafa3dfc2012-03-03 11:31:30 +00002559 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002560 {
2561 char
2562 token[MaxTextExtent];
2563
2564 const char
2565 *p;
2566
2567 PixelInfo
2568 black_point,
2569 white_point;
2570
anthonyfd706f92012-01-19 04:22:02 +00002571 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002572 GetMagickToken(p,&p,token); /* get black point color */
2573 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002574 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002575 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002576 else
cristy269c9412011-10-13 23:41:15 +00002577 (void) QueryColorCompliance("#000000",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002578 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002579 if (isalpha((int) token[0]) || (token[0] == '#'))
2580 GetMagickToken(p,&p,token);
2581 if (*token == '\0')
2582 white_point=black_point; /* set everything to that color */
2583 else
2584 {
2585 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2586 GetMagickToken(p,&p,token); /* Get white point color. */
2587 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002588 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002589 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002590 else
cristy269c9412011-10-13 23:41:15 +00002591 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002592 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002593 }
anthony31f1bf72012-01-30 12:37:22 +00002594 (void) LevelImageColors(image,&black_point,&white_point,
2595 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002596 break;
2597 }
anthonyafa3dfc2012-03-03 11:31:30 +00002598 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002599 {
2600 double
2601 black_point,
2602 white_point;
2603
2604 MagickStatusType
2605 flags;
2606
anthonyfd706f92012-01-19 04:22:02 +00002607 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002608 black_point=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002609 white_point=(MagickRealType) image->columns*image->rows;
anthony805a2d42011-09-25 08:25:12 +00002610 if ((flags & SigmaValue) != 0)
2611 white_point=geometry_info.sigma;
2612 if ((flags & PercentValue) != 0)
2613 {
anthony31f1bf72012-01-30 12:37:22 +00002614 black_point*=(double) image->columns*image->rows/100.0;
2615 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002616 }
2617 if ((flags & SigmaValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00002618 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00002619 black_point;
anthony31f1bf72012-01-30 12:37:22 +00002620 (void) LinearStretchImage(image,black_point,white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002621 break;
2622 }
anthonyafa3dfc2012-03-03 11:31:30 +00002623 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002624 {
anthony31f1bf72012-01-30 12:37:22 +00002625 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002626 if ((flags & XValue) == 0)
2627 geometry.x=1;
2628 if ((flags & YValue) == 0)
2629 geometry.y=0;
anthony31f1bf72012-01-30 12:37:22 +00002630 new_image=LiquidRescaleImage(image,geometry.width,
anthony805a2d42011-09-25 08:25:12 +00002631 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2632 break;
2633 }
anthonyafa3dfc2012-03-03 11:31:30 +00002634 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002635 {
anthonyafa3dfc2012-03-03 11:31:30 +00002636 (void) SetImageArtifact(image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002637 break;
2638 }
2639 break;
2640 }
2641 case 'm':
2642 {
anthonyafa3dfc2012-03-03 11:31:30 +00002643 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002644 {
2645 Image
2646 *remap_image;
2647
anthony31f1bf72012-01-30 12:37:22 +00002648 /* DEPRECIATED use -remap */
anthonyfd706f92012-01-19 04:22:02 +00002649 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002650 if (remap_image == (Image *) NULL)
2651 break;
anthony31f1bf72012-01-30 12:37:22 +00002652 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002653 remap_image=DestroyImage(remap_image);
2654 break;
2655 }
anthonyafa3dfc2012-03-03 11:31:30 +00002656 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002657 {
2658 Image
2659 *mask;
2660
anthonyafa3dfc2012-03-03 11:31:30 +00002661 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002662 { /* Remove a mask. */
2663 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00002664 break;
2665 }
anthony31f1bf72012-01-30 12:37:22 +00002666 /* Set the image mask. */
anthonyfd706f92012-01-19 04:22:02 +00002667 mask=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002668 if (mask == (Image *) NULL)
2669 break;
anthony31f1bf72012-01-30 12:37:22 +00002670 (void) SetImageMask(image,mask,exception);
anthony805a2d42011-09-25 08:25:12 +00002671 mask=DestroyImage(mask);
2672 break;
2673 }
anthonyafa3dfc2012-03-03 11:31:30 +00002674 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002675 {
anthony31f1bf72012-01-30 12:37:22 +00002676 /* DEPRECIATED */
anthonyafa3dfc2012-03-03 11:31:30 +00002677 (void) SetImageAlphaChannel(image,IfNormalOp ? SetAlphaChannel :
2678 DeactivateAlphaChannel, exception);
anthony805a2d42011-09-25 08:25:12 +00002679 break;
2680 }
anthonyafa3dfc2012-03-03 11:31:30 +00002681 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002682 {
anthonyfd706f92012-01-19 04:22:02 +00002683 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002684 if ((flags & SigmaValue) == 0)
2685 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002686 new_image=StatisticImage(image,ModeStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002687 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2688 break;
2689 }
anthonyafa3dfc2012-03-03 11:31:30 +00002690 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002691 {
anthony31f1bf72012-01-30 12:37:22 +00002692 (void) ModulateImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002693 break;
2694 }
anthonyafa3dfc2012-03-03 11:31:30 +00002695 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002696 {
anthonyafa3dfc2012-03-03 11:31:30 +00002697 (void) SetImageProgressMonitor(image, IfNormalOp ? MonitorProgress :
2698 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002699 break;
2700 }
anthonyafa3dfc2012-03-03 11:31:30 +00002701 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002702 {
anthony31f1bf72012-01-30 12:37:22 +00002703 (void) SetImageType(image,BilevelType,exception);
anthony805a2d42011-09-25 08:25:12 +00002704 break;
2705 }
anthonyafa3dfc2012-03-03 11:31:30 +00002706 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002707 {
2708 char
2709 token[MaxTextExtent];
2710
2711 const char
2712 *p;
2713
2714 KernelInfo
2715 *kernel;
2716
2717 MorphologyMethod
2718 method;
2719
2720 ssize_t
2721 iterations;
2722
anthonyfd706f92012-01-19 04:22:02 +00002723 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002724 GetMagickToken(p,&p,token);
2725 method=(MorphologyMethod) ParseCommandOption(
2726 MagickMorphologyOptions,MagickFalse,token);
2727 iterations=1L;
2728 GetMagickToken(p,&p,token);
2729 if ((*p == ':') || (*p == ','))
2730 GetMagickToken(p,&p,token);
2731 if ((*p != '\0'))
2732 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002733 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002734 if (kernel == (KernelInfo *) NULL)
2735 {
2736 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00002737 OptionError,"UnabletoParseKernel","morphology");
anthony805a2d42011-09-25 08:25:12 +00002738 break;
2739 }
anthony31f1bf72012-01-30 12:37:22 +00002740 new_image=MorphologyImage(image,method,iterations,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00002741 kernel=DestroyKernelInfo(kernel);
2742 break;
2743 }
anthonyafa3dfc2012-03-03 11:31:30 +00002744 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002745 {
anthonyfd706f92012-01-19 04:22:02 +00002746 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002747 if ((flags & SigmaValue) == 0)
2748 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002749 new_image=MotionBlurImage(image,geometry_info.rho,
2750 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2751 exception);
anthony805a2d42011-09-25 08:25:12 +00002752 break;
2753 }
2754 break;
2755 }
2756 case 'n':
2757 {
anthonyafa3dfc2012-03-03 11:31:30 +00002758 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002759 {
anthony31f1bf72012-01-30 12:37:22 +00002760 (void) NegateImage(image, plus_alt_op, exception);
anthony805a2d42011-09-25 08:25:12 +00002761 break;
2762 }
anthonyafa3dfc2012-03-03 11:31:30 +00002763 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002764 {
anthonyafa3dfc2012-03-03 11:31:30 +00002765 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002766 {
anthonyfd706f92012-01-19 04:22:02 +00002767 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002768 if ((flags & SigmaValue) == 0)
2769 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002770 new_image=StatisticImage(image,NonpeakStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002771 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2772 }
2773 else
2774 {
2775 NoiseType
2776 noise;
2777
anthony31f1bf72012-01-30 12:37:22 +00002778 double
2779 attenuate;
2780
2781 const char*
2782 value;
2783
anthony805a2d42011-09-25 08:25:12 +00002784 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
anthony31f1bf72012-01-30 12:37:22 +00002785 MagickFalse,arg1),
2786
2787 value=GetImageOption(image_info,"attenuate");
2788 if (value != (const char *) NULL)
2789 attenuate=StringToDouble(value,(char **) NULL);
2790 else
2791 attenuate=1.0;
2792
2793 new_image=AddNoiseImage(image,noise,attenuate,exception);
anthony805a2d42011-09-25 08:25:12 +00002794 }
2795 break;
2796 }
anthonyafa3dfc2012-03-03 11:31:30 +00002797 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002798 {
anthony31f1bf72012-01-30 12:37:22 +00002799 (void) NormalizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002800 break;
2801 }
2802 break;
2803 }
2804 case 'o':
2805 {
anthonyafa3dfc2012-03-03 11:31:30 +00002806 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002807 {
2808 PixelInfo
2809 target;
2810
anthony31f1bf72012-01-30 12:37:22 +00002811 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
2812 (void) OpaquePaintImage(image,&target,&draw_info->fill,plus_alt_op,
2813 exception);
anthony805a2d42011-09-25 08:25:12 +00002814 break;
2815 }
anthonyafa3dfc2012-03-03 11:31:30 +00002816 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002817 {
anthony31f1bf72012-01-30 12:37:22 +00002818 (void) OrderedPosterizeImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002819 break;
2820 }
2821 break;
2822 }
2823 case 'p':
2824 {
anthonyafa3dfc2012-03-03 11:31:30 +00002825 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002826 {
anthonyfd706f92012-01-19 04:22:02 +00002827 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002828 new_image=OilPaintImage(image,geometry_info.rho,geometry_info.sigma,
2829 exception);
anthony805a2d42011-09-25 08:25:12 +00002830 break;
2831 }
anthonyafa3dfc2012-03-03 11:31:30 +00002832 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002833 {
cristye9e3d382011-12-14 01:50:13 +00002834 const char
2835 *caption;
2836
anthony805a2d42011-09-25 08:25:12 +00002837 double
2838 angle;
2839
anthonyafa3dfc2012-03-03 11:31:30 +00002840 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002841 {
2842 RandomInfo
2843 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002844
anthony31f1bf72012-01-30 12:37:22 +00002845 random_info=AcquireRandomInfo();
2846 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2847 random_info=DestroyRandomInfo(random_info);
2848 }
2849 else
anthony805a2d42011-09-25 08:25:12 +00002850 {
2851 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00002852 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002853 angle=geometry_info.rho;
2854 }
anthony31f1bf72012-01-30 12:37:22 +00002855 caption=GetImageProperty(image,"caption",exception);
2856 new_image=PolaroidImage(image,draw_info,caption,angle,
2857 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002858 break;
2859 }
anthonyafa3dfc2012-03-03 11:31:30 +00002860 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002861 {
anthony31f1bf72012-01-30 12:37:22 +00002862 (void) ParseGeometry(arg1,&geometry_info);
2863 (void) PosterizeImage(image,(size_t) geometry_info.rho,
2864 quantize_info->dither,exception);
anthony805a2d42011-09-25 08:25:12 +00002865 break;
2866 }
anthonyafa3dfc2012-03-03 11:31:30 +00002867 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002868 {
2869 PreviewType
cristy947cb4c2011-10-20 18:41:46 +00002870 preview_type;
anthony170fce92011-10-20 11:50:23 +00002871
anthony31f1bf72012-01-30 12:37:22 +00002872 /* FUTURE: should be a 'Genesis' option?
2873 Option however is also in WandSettingOptionInfo()
cristy947cb4c2011-10-20 18:41:46 +00002874 */
anthony31f1bf72012-01-30 12:37:22 +00002875 preview_type=UndefinedPreview;
anthonyafa3dfc2012-03-03 11:31:30 +00002876 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00002877 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2878 MagickFalse,arg1);
2879 new_image=PreviewImage(image,preview_type,exception);
anthony805a2d42011-09-25 08:25:12 +00002880 break;
2881 }
anthonyafa3dfc2012-03-03 11:31:30 +00002882 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002883 {
2884 const char
2885 *name;
2886
2887 const StringInfo
2888 *profile;
2889
2890 Image
2891 *profile_image;
2892
2893 ImageInfo
2894 *profile_info;
2895
anthonyafa3dfc2012-03-03 11:31:30 +00002896 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002897 { /* Remove a profile from the image. */
2898 (void) ProfileImage(image,arg1,(const unsigned char *)
cristy092d71c2011-10-14 18:01:29 +00002899 NULL,0,exception);
anthony805a2d42011-09-25 08:25:12 +00002900 break;
2901 }
anthony31f1bf72012-01-30 12:37:22 +00002902 /* Associate a profile with the image. */
anthony805a2d42011-09-25 08:25:12 +00002903 profile_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00002904 profile=GetImageProfile(image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002905 if (profile != (StringInfo *) NULL)
2906 profile_info->profile=(void *) CloneStringInfo(profile);
anthonyfd706f92012-01-19 04:22:02 +00002907 profile_image=GetImageCache(profile_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002908 profile_info=DestroyImageInfo(profile_info);
2909 if (profile_image == (Image *) NULL)
2910 {
2911 StringInfo
2912 *profile;
2913
2914 profile_info=CloneImageInfo(image_info);
anthonyfd706f92012-01-19 04:22:02 +00002915 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002916 MaxTextExtent);
2917 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
2918 if (profile != (StringInfo *) NULL)
2919 {
anthony31f1bf72012-01-30 12:37:22 +00002920 (void) ProfileImage(image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002921 GetStringInfoDatum(profile),(size_t)
cristy092d71c2011-10-14 18:01:29 +00002922 GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002923 profile=DestroyStringInfo(profile);
2924 }
2925 profile_info=DestroyImageInfo(profile_info);
2926 break;
2927 }
2928 ResetImageProfileIterator(profile_image);
2929 name=GetNextImageProfile(profile_image);
2930 while (name != (const char *) NULL)
2931 {
2932 profile=GetImageProfile(profile_image,name);
2933 if (profile != (StringInfo *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002934 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
cristy092d71c2011-10-14 18:01:29 +00002935 (size_t) GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002936 name=GetNextImageProfile(profile_image);
2937 }
2938 profile_image=DestroyImage(profile_image);
2939 break;
2940 }
2941 break;
2942 }
anthony805a2d42011-09-25 08:25:12 +00002943 case 'r':
2944 {
anthonyafa3dfc2012-03-03 11:31:30 +00002945 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002946 {
anthonyfd706f92012-01-19 04:22:02 +00002947 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002948 new_image=RadialBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002949 geometry_info.sigma,exception);
2950 break;
2951 }
anthonyafa3dfc2012-03-03 11:31:30 +00002952 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002953 {
anthony31f1bf72012-01-30 12:37:22 +00002954 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002955 if ((flags & SigmaValue) == 0)
2956 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00002957 (void) RaiseImage(image,&geometry,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002958 break;
2959 }
anthonyafa3dfc2012-03-03 11:31:30 +00002960 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002961 {
anthony31f1bf72012-01-30 12:37:22 +00002962 (void) RandomThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002963 break;
2964 }
anthonyafa3dfc2012-03-03 11:31:30 +00002965 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002966 {
2967 Image
2968 *remap_image;
2969
anthonyfd706f92012-01-19 04:22:02 +00002970 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002971 if (remap_image == (Image *) NULL)
2972 break;
anthony31f1bf72012-01-30 12:37:22 +00002973 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002974 remap_image=DestroyImage(remap_image);
2975 break;
2976 }
anthonyafa3dfc2012-03-03 11:31:30 +00002977 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002978 {
anthonyafa3dfc2012-03-03 11:31:30 +00002979 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00002980 (void) ResetImagePage(image,arg1);
2981 else
2982 (void) ParseAbsoluteGeometry("0x0+0+0",&image->page);
anthony805a2d42011-09-25 08:25:12 +00002983 break;
2984 }
anthonyafa3dfc2012-03-03 11:31:30 +00002985 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002986 {
anthony31f1bf72012-01-30 12:37:22 +00002987 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00002988 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002989 if ((flags & SigmaValue) == 0)
2990 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002991 new_image=ResampleImage(image,geometry_info.rho,
2992 geometry_info.sigma,image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002993 break;
2994 }
anthonyafa3dfc2012-03-03 11:31:30 +00002995 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002996 {
anthonyafbaed72011-10-26 12:05:04 +00002997 /* FUTURE: remove blur argument - no longer used */
anthony31f1bf72012-01-30 12:37:22 +00002998 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2999 new_image=ResizeImage(image,geometry.width,geometry.height,
3000 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00003001 break;
3002 }
anthonyafa3dfc2012-03-03 11:31:30 +00003003 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003004 {
anthony31f1bf72012-01-30 12:37:22 +00003005 (void) ParsePageGeometry(image,arg1,&geometry,exception);
3006 new_image=RollImage(image,geometry.x,geometry.y,exception);
anthony805a2d42011-09-25 08:25:12 +00003007 break;
3008 }
anthonyafa3dfc2012-03-03 11:31:30 +00003009 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003010 {
anthonyfd706f92012-01-19 04:22:02 +00003011 if (strchr(arg1,'>') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003012 if (image->columns <= image->rows)
anthony805a2d42011-09-25 08:25:12 +00003013 break;
anthonyfd706f92012-01-19 04:22:02 +00003014 if (strchr(arg1,'<') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003015 if (image->columns >= image->rows)
anthony805a2d42011-09-25 08:25:12 +00003016 break;
anthonyafbaed72011-10-26 12:05:04 +00003017
anthonyfd706f92012-01-19 04:22:02 +00003018 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003019 new_image=RotateImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00003020 break;
3021 }
3022 break;
3023 }
3024 case 's':
3025 {
anthonyafa3dfc2012-03-03 11:31:30 +00003026 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003027 {
anthony31f1bf72012-01-30 12:37:22 +00003028 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3029 new_image=SampleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00003030 exception);
3031 break;
3032 }
anthonyafa3dfc2012-03-03 11:31:30 +00003033 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003034 {
anthony31f1bf72012-01-30 12:37:22 +00003035 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3036 new_image=ScaleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00003037 exception);
3038 break;
3039 }
anthonyafa3dfc2012-03-03 11:31:30 +00003040 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003041 {
anthonyfd706f92012-01-19 04:22:02 +00003042 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003043 if ((flags & PercentValue) != 0)
3044 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00003045 new_image=SelectiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003046 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3047 break;
3048 }
anthonyafa3dfc2012-03-03 11:31:30 +00003049 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003050 {
anthony31f1bf72012-01-30 12:37:22 +00003051 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003052 /* FUTURE - this may be replaced by a "-channel" method */
anthony31f1bf72012-01-30 12:37:22 +00003053 new_image=SeparateImages(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003054 break;
3055 }
anthonyafa3dfc2012-03-03 11:31:30 +00003056 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003057 {
3058 double
3059 threshold;
3060
anthonyfd706f92012-01-19 04:22:02 +00003061 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00003062 new_image=SepiaToneImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00003063 break;
3064 }
anthonyafa3dfc2012-03-03 11:31:30 +00003065 if (LocaleCompare("segment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003066 {
anthonyfd706f92012-01-19 04:22:02 +00003067 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003068 if ((flags & SigmaValue) == 0)
3069 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003070 (void) SegmentImage(image,image->colorspace,
anthony805a2d42011-09-25 08:25:12 +00003071 image_info->verbose,geometry_info.rho,geometry_info.sigma,
3072 exception);
3073 break;
3074 }
anthonyafa3dfc2012-03-03 11:31:30 +00003075 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003076 {
3077 char
3078 *value;
3079
anthonyafa3dfc2012-03-03 11:31:30 +00003080 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00003081 {
anthonyfd706f92012-01-19 04:22:02 +00003082 if (LocaleNCompare(arg1,"registry:",9) == 0)
3083 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003084 else
anthony31f1bf72012-01-30 12:37:22 +00003085 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003086 {
anthonyfd706f92012-01-19 04:22:02 +00003087 (void) DeleteImageOption(image_info,arg1+7);
anthony31f1bf72012-01-30 12:37:22 +00003088 (void) DeleteImageArtifact(image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003089 }
3090 else
anthony31f1bf72012-01-30 12:37:22 +00003091 (void) DeleteImageProperty(image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003092 break;
3093 }
anthony31f1bf72012-01-30 12:37:22 +00003094 value=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00003095 exception);
3096 if (value == (char *) NULL)
3097 break;
anthonyfd706f92012-01-19 04:22:02 +00003098 if (LocaleNCompare(arg1,"registry:",9) == 0)
3099 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony805a2d42011-09-25 08:25:12 +00003100 exception);
3101 else
anthonyfd706f92012-01-19 04:22:02 +00003102 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003103 {
anthonyfd706f92012-01-19 04:22:02 +00003104 (void) SetImageOption(image_info,arg1+7,value);
anthony31f1bf72012-01-30 12:37:22 +00003105 (void) SetImageArtifact(image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003106 }
3107 else
anthony31f1bf72012-01-30 12:37:22 +00003108 (void) SetImageProperty(image,arg1,value,exception);
anthony805a2d42011-09-25 08:25:12 +00003109 value=DestroyString(value);
3110 break;
3111 }
anthonyafa3dfc2012-03-03 11:31:30 +00003112 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003113 {
anthonyfd706f92012-01-19 04:22:02 +00003114 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003115 if ((flags & SigmaValue) == 0)
3116 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003117 new_image=ShadeImage(image,normal_op,geometry_info.rho,
3118 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00003119 break;
3120 }
anthonyafa3dfc2012-03-03 11:31:30 +00003121 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003122 {
anthonyfd706f92012-01-19 04:22:02 +00003123 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003124 if ((flags & SigmaValue) == 0)
3125 geometry_info.sigma=1.0;
3126 if ((flags & XiValue) == 0)
3127 geometry_info.xi=4.0;
3128 if ((flags & PsiValue) == 0)
3129 geometry_info.psi=4.0;
anthony31f1bf72012-01-30 12:37:22 +00003130 new_image=ShadowImage(image,geometry_info.rho,
3131 geometry_info.sigma,image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003132 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
3133 exception);
anthony805a2d42011-09-25 08:25:12 +00003134 break;
3135 }
anthonyafa3dfc2012-03-03 11:31:30 +00003136 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003137 {
anthonyfd706f92012-01-19 04:22:02 +00003138 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003139 if ((flags & SigmaValue) == 0)
3140 geometry_info.sigma=1.0;
3141 if ((flags & XiValue) == 0)
3142 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00003143 new_image=SharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003144 geometry_info.sigma,geometry_info.xi,exception);
3145 break;
3146 }
anthonyafa3dfc2012-03-03 11:31:30 +00003147 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003148 {
anthony31f1bf72012-01-30 12:37:22 +00003149 flags=ParsePageGeometry(image,arg1,&geometry,exception);
3150 new_image=ShaveImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003151 break;
3152 }
anthonyafa3dfc2012-03-03 11:31:30 +00003153 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003154 {
anthonyfd706f92012-01-19 04:22:02 +00003155 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003156 if ((flags & SigmaValue) == 0)
3157 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00003158 new_image=ShearImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003159 geometry_info.sigma,exception);
3160 break;
3161 }
anthonyafa3dfc2012-03-03 11:31:30 +00003162 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003163 {
anthonyfd706f92012-01-19 04:22:02 +00003164 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003165 if ((flags & SigmaValue) == 0)
3166 geometry_info.sigma=(double) QuantumRange/2.0;
3167 if ((flags & PercentValue) != 0)
3168 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3169 100.0;
anthony31f1bf72012-01-30 12:37:22 +00003170 (void) SigmoidalContrastImage(image,normal_op,geometry_info.rho,
3171 geometry_info.sigma,
anthony805a2d42011-09-25 08:25:12 +00003172 exception);
3173 break;
3174 }
anthonyafa3dfc2012-03-03 11:31:30 +00003175 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003176 {
anthonyfd706f92012-01-19 04:22:02 +00003177 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003178 if ((flags & SigmaValue) == 0)
3179 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003180 new_image=SketchImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003181 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3182 break;
3183 }
anthonyafa3dfc2012-03-03 11:31:30 +00003184 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003185 {
anthony31f1bf72012-01-30 12:37:22 +00003186 (void) SolarizeImage(image,StringToDoubleInterval(arg1,(double)
3187 QuantumRange+1.0),exception);
anthony805a2d42011-09-25 08:25:12 +00003188 break;
3189 }
anthonyafa3dfc2012-03-03 11:31:30 +00003190 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003191 {
3192 SparseColorMethod
3193 method;
3194
3195 char
3196 *arguments;
3197
anthony805a2d42011-09-25 08:25:12 +00003198 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003199 MagickSparseColorOptions,MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003200 arguments=InterpretImageProperties(image_info,image,arg2,exception);
anthony805a2d42011-09-25 08:25:12 +00003201 if (arguments == (char *) NULL)
3202 break;
anthony31f1bf72012-01-30 12:37:22 +00003203 new_image=SparseColorOption(image,method,arguments,exception);
anthony805a2d42011-09-25 08:25:12 +00003204 arguments=DestroyString(arguments);
3205 break;
3206 }
anthonyafa3dfc2012-03-03 11:31:30 +00003207 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003208 {
anthony31f1bf72012-01-30 12:37:22 +00003209 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
3210 new_image=SpliceImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003211 break;
3212 }
anthonyafa3dfc2012-03-03 11:31:30 +00003213 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003214 {
anthonyfd706f92012-01-19 04:22:02 +00003215 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003216 new_image=SpreadImage(image,geometry_info.rho,image->interpolate,
3217 exception);
anthony805a2d42011-09-25 08:25:12 +00003218 break;
3219 }
anthonyafa3dfc2012-03-03 11:31:30 +00003220 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003221 {
3222 StatisticType
3223 type;
3224
anthony805a2d42011-09-25 08:25:12 +00003225 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
anthonyfd706f92012-01-19 04:22:02 +00003226 MagickFalse,arg1);
3227 (void) ParseGeometry(arg2,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003228 new_image=StatisticImage(image,type,(size_t) geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003229 (size_t) geometry_info.sigma,exception);
3230 break;
3231 }
anthonyafa3dfc2012-03-03 11:31:30 +00003232 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003233 {
anthony31f1bf72012-01-30 12:37:22 +00003234 (void) StripImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003235 break;
3236 }
anthonyafa3dfc2012-03-03 11:31:30 +00003237 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003238 {
anthonyfd706f92012-01-19 04:22:02 +00003239 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003240 new_image=SwirlImage(image,geometry_info.rho,
3241 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003242 break;
3243 }
3244 break;
3245 }
3246 case 't':
3247 {
anthonyafa3dfc2012-03-03 11:31:30 +00003248 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003249 {
3250 double
3251 threshold;
3252
anthonyafa3dfc2012-03-03 11:31:30 +00003253 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003254 threshold=(double) QuantumRange/2;
3255 else
anthonyfd706f92012-01-19 04:22:02 +00003256 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00003257 (void) BilevelImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00003258 break;
3259 }
anthonyafa3dfc2012-03-03 11:31:30 +00003260 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003261 {
anthony31f1bf72012-01-30 12:37:22 +00003262 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3263 new_image=ThumbnailImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00003264 exception);
3265 break;
3266 }
anthonyafa3dfc2012-03-03 11:31:30 +00003267 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003268 {
anthony31f1bf72012-01-30 12:37:22 +00003269 new_image=TintImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00003270 break;
3271 }
anthonyafa3dfc2012-03-03 11:31:30 +00003272 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003273 {
anthonyfd706f92012-01-19 04:22:02 +00003274 /* DEPRECIATED */
anthony31f1bf72012-01-30 12:37:22 +00003275 new_image=AffineTransformImage(image,&draw_info->affine,
anthony805a2d42011-09-25 08:25:12 +00003276 exception);
3277 break;
3278 }
anthonyafa3dfc2012-03-03 11:31:30 +00003279 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003280 {
3281 PixelInfo
3282 target;
3283
anthony31f1bf72012-01-30 12:37:22 +00003284 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
3285 (void) TransparentPaintImage(image,&target,(Quantum)
3286 TransparentAlpha,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003287 break;
3288 }
anthonyafa3dfc2012-03-03 11:31:30 +00003289 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003290 {
anthony31f1bf72012-01-30 12:37:22 +00003291 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003292 break;
3293 }
anthonyafa3dfc2012-03-03 11:31:30 +00003294 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003295 {
anthony31f1bf72012-01-30 12:37:22 +00003296 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003297 break;
3298 }
anthonyafa3dfc2012-03-03 11:31:30 +00003299 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003300 {
anthony31f1bf72012-01-30 12:37:22 +00003301 new_image=TrimImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003302 break;
3303 }
anthonyafa3dfc2012-03-03 11:31:30 +00003304 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003305 {
anthonyab3a50c2011-10-27 11:48:57 +00003306 /* Note that "type" setting should have already been defined */
anthony31f1bf72012-01-30 12:37:22 +00003307 (void) SetImageType(image,image_info->type,exception);
anthony805a2d42011-09-25 08:25:12 +00003308 break;
3309 }
3310 break;
3311 }
3312 case 'u':
3313 {
anthonyafa3dfc2012-03-03 11:31:30 +00003314 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003315 {
anthony31f1bf72012-01-30 12:37:22 +00003316 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00003317 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003318 {
anthony31f1bf72012-01-30 12:37:22 +00003319 (void) DeleteImageArtifact(image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003320 break;
3321 }
anthony31f1bf72012-01-30 12:37:22 +00003322 (void) SetImageArtifact(image,"identify:unique-colors","true");
3323 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003324 break;
3325 }
anthonyafa3dfc2012-03-03 11:31:30 +00003326 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003327 {
anthony31f1bf72012-01-30 12:37:22 +00003328 new_image=UniqueImageColors(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003329 break;
3330 }
anthonyafa3dfc2012-03-03 11:31:30 +00003331 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003332 {
anthonyfd706f92012-01-19 04:22:02 +00003333 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003334 if ((flags & SigmaValue) == 0)
3335 geometry_info.sigma=1.0;
3336 if ((flags & XiValue) == 0)
3337 geometry_info.xi=1.0;
3338 if ((flags & PsiValue) == 0)
3339 geometry_info.psi=0.05;
anthony31f1bf72012-01-30 12:37:22 +00003340 new_image=UnsharpMaskImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003341 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3342 break;
3343 }
3344 break;
3345 }
3346 case 'v':
3347 {
anthonyafa3dfc2012-03-03 11:31:30 +00003348 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003349 {
anthonyafa3dfc2012-03-03 11:31:30 +00003350 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony31f1bf72012-01-30 12:37:22 +00003351 three places! ImageArtifact ImageOption image_info->verbose
anthonyafa3dfc2012-03-03 11:31:30 +00003352 Some how new images also get this artifact presumably here
anthony31f1bf72012-01-30 12:37:22 +00003353 */
anthonyafa3dfc2012-03-03 11:31:30 +00003354 (void) SetImageArtifact(image,option+1,
3355 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003356 break;
3357 }
anthonyafa3dfc2012-03-03 11:31:30 +00003358 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003359 {
anthonyfd706f92012-01-19 04:22:02 +00003360 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003361 if ((flags & SigmaValue) == 0)
3362 geometry_info.sigma=1.0;
3363 if ((flags & XiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003364 geometry_info.xi=0.1*image->columns;
anthony805a2d42011-09-25 08:25:12 +00003365 if ((flags & PsiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003366 geometry_info.psi=0.1*image->rows;
3367 new_image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
3368 image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3369 (ssize_t) ceil(geometry_info.psi-0.5),exception);
anthony805a2d42011-09-25 08:25:12 +00003370 break;
3371 }
anthony805a2d42011-09-25 08:25:12 +00003372 break;
3373 }
3374 case 'w':
3375 {
anthonyafa3dfc2012-03-03 11:31:30 +00003376 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003377 {
anthonyfd706f92012-01-19 04:22:02 +00003378 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003379 if ((flags & SigmaValue) == 0)
3380 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003381 new_image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
3382 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003383 break;
3384 }
anthonyafa3dfc2012-03-03 11:31:30 +00003385 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003386 {
anthony31f1bf72012-01-30 12:37:22 +00003387 (void) WhiteThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003388 break;
3389 }
3390 break;
3391 }
3392 default:
3393 break;
3394 }
3395 /*
3396 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003397 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003398 */
3399 if (new_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003400 ReplaceImageInListReturnLast(&image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003401
anthony31f1bf72012-01-30 12:37:22 +00003402 return;
anthonyfd706f92012-01-19 04:22:02 +00003403#undef image_info
3404#undef draw_info
3405#undef quantize_info
anthony31f1bf72012-01-30 12:37:22 +00003406#undef image
anthonyfd706f92012-01-19 04:22:02 +00003407#undef exception
anthonyafa3dfc2012-03-03 11:31:30 +00003408#undef IfNormalOp
3409#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003410#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003411#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003412}
anthonyfd706f92012-01-19 04:22:02 +00003413
anthony43f425d2012-02-26 12:58:58 +00003414WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003415 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003416{
3417 size_t
anthony43f425d2012-02-26 12:58:58 +00003418 n,
anthony31f1bf72012-01-30 12:37:22 +00003419 i;
3420
anthony43f425d2012-02-26 12:58:58 +00003421 assert(cli_wand != (MagickCLI *) NULL);
3422 assert(cli_wand->signature == WandSignature);
3423 assert(cli_wand->wand.signature == WandSignature);
3424 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3425 if (cli_wand->wand.debug != MagickFalse)
3426 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003427
anthonyafa3dfc2012-03-03 11:31:30 +00003428#if !USE_WAND_METHODS
3429 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003430 i=0;
anthony43f425d2012-02-26 12:58:58 +00003431 n=GetImageListLength(cli_wand->wand.images);
3432 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003433 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003434 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003435 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003436 if ( cli_wand->wand.images->next == (Image *) NULL )
3437 break;
3438 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003439 }
anthony43f425d2012-02-26 12:58:58 +00003440 assert( i == n );
3441 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003442#else
3443 MagickResetIterator(&cli_wand->wand);
3444 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3445 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3446 MagickResetIterator(&cli_wand->wand);
3447#endif
anthony31f1bf72012-01-30 12:37:22 +00003448 return;
anthony805a2d42011-09-25 08:25:12 +00003449}
3450
3451/*
3452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3453% %
3454% %
3455% %
anthony43f425d2012-02-26 12:58:58 +00003456+ 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 +00003457% %
3458% %
3459% %
3460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3461%
anthony43f425d2012-02-26 12:58:58 +00003462% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003463% entire image list as a whole. The result is often a complete replacment
3464% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003465%
3466% The format of the MogrifyImage method is:
3467%
anthony43f425d2012-02-26 12:58:58 +00003468% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003469% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003470%
3471% A description of each parameter follows:
3472%
anthony43f425d2012-02-26 12:58:58 +00003473% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003474%
anthony36a8c2c2012-02-10 00:08:44 +00003475% o option: The option string for the operation
3476%
anthony31f1bf72012-01-30 12:37:22 +00003477% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003478%
anthony8b10b462012-02-08 12:32:44 +00003479% NOTE: only "limit" currently uses two arguments.
3480%
3481% Example usage...
3482%
anthonyafa3dfc2012-03-03 11:31:30 +00003483% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3484% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003485%
3486% Or for handling command line arguments EG: +/-option ["arg"]
3487%
anthony43f425d2012-02-26 12:58:58 +00003488% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003489% argc,argv
3490% i=index in argv
3491%
anthony2052d272012-02-28 12:48:29 +00003492% option_info = GetCommandOptionInfo(argv[i]);
3493% count=option_info->type;
3494% option_type=option_info->flags;
3495%
3496% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003497% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003498% count>=1 ? argv[i+1] : (char *)NULL,
3499% count>=2 ? argv[i+2] : (char *)NULL );
3500% i += count+1;
3501%
anthony805a2d42011-09-25 08:25:12 +00003502*/
anthony43f425d2012-02-26 12:58:58 +00003503WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003504 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003505{
anthony31f1bf72012-01-30 12:37:22 +00003506 Image
3507 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003508
anthony43f425d2012-02-26 12:58:58 +00003509#define image_info (cli_wand->wand.image_info)
3510#define images (cli_wand->wand.images)
3511#define exception (cli_wand->wand.exception)
3512#define draw_info (cli_wand->draw_info)
3513#define quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003514#define IfNormalOp (*option=='-')
3515#define IfPlusOp (*option!='-')
3516#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003517
anthony43f425d2012-02-26 12:58:58 +00003518 assert(cli_wand != (MagickCLI *) NULL);
3519 assert(cli_wand->signature == WandSignature);
3520 assert(cli_wand->wand.signature == WandSignature);
3521 assert(images != (Image *) NULL); /* images must be present */
3522 if (cli_wand->wand.debug != MagickFalse)
3523 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003524
3525 (void) SyncImagesSettings(image_info,images,exception);
3526
3527 new_images=NewImageList();
3528
anthonyafa3dfc2012-03-03 11:31:30 +00003529 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003530 {
3531 case 'a':
3532 {
anthonyafa3dfc2012-03-03 11:31:30 +00003533 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003534 {
anthony31f1bf72012-01-30 12:37:22 +00003535 new_images=AppendImages(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003536 break;
3537 }
anthonyafa3dfc2012-03-03 11:31:30 +00003538 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003539 {
anthony31f1bf72012-01-30 12:37:22 +00003540 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003541 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003542 break;
3543 }
3544 break;
3545 }
3546 case 'c':
3547 {
anthonyafa3dfc2012-03-03 11:31:30 +00003548 if (LocaleCompare("channel-inject",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003549 {
3550 puts("stand by...");
3551 break;
3552 }
anthonyafa3dfc2012-03-03 11:31:30 +00003553 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003554 {
anthony805a2d42011-09-25 08:25:12 +00003555 Image
anthony31f1bf72012-01-30 12:37:22 +00003556 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003557
anthonyafa3dfc2012-03-03 11:31:30 +00003558 /* FUTURE - make this a compose option, and thus can be used
3559 with layers compose or even compose last image over all other
3560 images.
cristy87c02f42012-02-24 00:19:10 +00003561 */
anthony31f1bf72012-01-30 12:37:22 +00003562 new_images=RemoveFirstImageFromList(&images);
3563 clut_image=RemoveLastImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003564 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003565 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003566 break;
anthony31f1bf72012-01-30 12:37:22 +00003567 (void) ClutImage(new_images,clut_image,images->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003568 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003569 break;
3570 }
anthonyafa3dfc2012-03-03 11:31:30 +00003571 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003572 {
anthony31f1bf72012-01-30 12:37:22 +00003573 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003574 break;
3575 }
anthonyafa3dfc2012-03-03 11:31:30 +00003576 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003577 {
anthony43f425d2012-02-26 12:58:58 +00003578 /* FUTURE - this may be replaced by a 'channel' method */
anthony31f1bf72012-01-30 12:37:22 +00003579 new_images=CombineImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003580 break;
3581 }
anthonyafa3dfc2012-03-03 11:31:30 +00003582 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003583 {
3584 Image
3585 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003586 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003587
3588 RectangleInfo
3589 geometry;
3590
anthony31f1bf72012-01-30 12:37:22 +00003591 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003592 compose;
3593
3594 const char*
3595 value;
3596
3597 value=GetImageOption(image_info,"compose");
3598 if (value != (const char *) NULL)
3599 compose=(CompositeOperator) ParseCommandOption(
3600 MagickComposeOptions,MagickFalse,value);
3601 else
anthony31f1bf72012-01-30 12:37:22 +00003602 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003603
anthony31f1bf72012-01-30 12:37:22 +00003604 new_images=RemoveFirstImageFromList(&images);
3605 source_image=RemoveFirstImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003606 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003607 if (source_image == (Image *) NULL)
3608 break;
anthonye8f56492012-02-12 12:39:02 +00003609
anthony31f1bf72012-01-30 12:37:22 +00003610 /* FUTURE - this should not be here! - should be part of -geometry */
3611 (void) TransformImage(&source_image,(char *) NULL,
3612 source_image->geometry,exception);
anthony5f867ae2011-10-09 10:28:34 +00003613
anthony31f1bf72012-01-30 12:37:22 +00003614 SetGeometry(source_image,&geometry);
3615 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3616 GravityAdjustGeometry(new_images->columns,new_images->rows,
3617 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003618
anthony31f1bf72012-01-30 12:37:22 +00003619 mask_image=RemoveFirstImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003620 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003621 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003622 if ((compose == DisplaceCompositeOp) ||
3623 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003624 { /* Merge Y displacement into X displace/distort map. */
3625 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony6613bf32011-10-15 07:24:44 +00003626 mask_image,0,0,exception);
anthony805a2d42011-09-25 08:25:12 +00003627 mask_image=DestroyImage(mask_image);
3628 }
3629 else
3630 {
3631 /*
3632 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003633 */
cristy1539afd2012-01-30 01:32:59 +00003634 (void) NegateImage(mask_image,MagickFalse,exception);
anthony31f1bf72012-01-30 12:37:22 +00003635 (void) SetImageMask(new_images,mask_image,exception);
cristy1539afd2012-01-30 01:32:59 +00003636 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003637 }
3638 }
anthony31f1bf72012-01-30 12:37:22 +00003639 (void) CompositeImage(new_images,compose,source_image,geometry.x,
3640 geometry.y,exception);
3641 (void) SetImageMask(new_images,(Image *) NULL,exception);
3642 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003643 break;
3644 }
3645 break;
3646 }
3647 case 'd':
3648 {
anthonyafa3dfc2012-03-03 11:31:30 +00003649 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003650 {
anthony31f1bf72012-01-30 12:37:22 +00003651 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003652 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003653 break;
3654 }
anthonyafa3dfc2012-03-03 11:31:30 +00003655 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003656 {
anthonyafa3dfc2012-03-03 11:31:30 +00003657 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003658 DeleteImages(&images,arg1,exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003659 else
3660 DeleteImages(&images,"-1",exception);
anthony805a2d42011-09-25 08:25:12 +00003661 break;
3662 }
anthonyafa3dfc2012-03-03 11:31:30 +00003663 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003664 {
anthonyafa3dfc2012-03-03 11:31:30 +00003665 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003666 {
3667 const char
3668 *p;
3669
3670 size_t
3671 number_duplicates;
3672
anthony31f1bf72012-01-30 12:37:22 +00003673 number_duplicates=(size_t) StringToLong(arg1);
3674 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003675 if (p == (const char *) NULL)
anthony36a8c2c2012-02-10 00:08:44 +00003676 new_images=DuplicateImages(images,number_duplicates,
anthony805a2d42011-09-25 08:25:12 +00003677 "-1",exception);
3678 else
anthony36a8c2c2012-02-10 00:08:44 +00003679 new_images=DuplicateImages(images,number_duplicates,p,
anthony805a2d42011-09-25 08:25:12 +00003680 exception);
3681 }
anthonyafa3dfc2012-03-03 11:31:30 +00003682 else
3683 new_images=DuplicateImages(images,1,"-1",exception);
anthony36a8c2c2012-02-10 00:08:44 +00003684 AppendImageToList(&images, new_images);
3685 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003686 break;
3687 }
3688 break;
3689 }
3690 case 'e':
3691 {
anthonyafa3dfc2012-03-03 11:31:30 +00003692 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003693 {
anthony805a2d42011-09-25 08:25:12 +00003694 MagickEvaluateOperator
anthony31f1bf72012-01-30 12:37:22 +00003695 method;
anthony805a2d42011-09-25 08:25:12 +00003696
anthony31f1bf72012-01-30 12:37:22 +00003697 method=(MagickEvaluateOperator) ParseCommandOption(
3698 MagickEvaluateOptions,MagickFalse,arg1);
3699 new_images=EvaluateImages(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003700 break;
3701 }
3702 break;
3703 }
3704 case 'f':
3705 {
anthonyafa3dfc2012-03-03 11:31:30 +00003706 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003707 {
anthony31f1bf72012-01-30 12:37:22 +00003708 new_images=ForwardFourierTransformImage(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003709 break;
3710 }
anthonyafa3dfc2012-03-03 11:31:30 +00003711 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003712 {
anthony31f1bf72012-01-30 12:37:22 +00003713 /* DEPRECIATED use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003714 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003715 break;
3716 }
anthonyafa3dfc2012-03-03 11:31:30 +00003717 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003718 {
anthony31f1bf72012-01-30 12:37:22 +00003719 new_images=FxImage(images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003720 break;
3721 }
3722 break;
3723 }
3724 case 'h':
3725 {
anthonyafa3dfc2012-03-03 11:31:30 +00003726 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003727 {
anthony31f1bf72012-01-30 12:37:22 +00003728 /* FUTURE - make this a compose option (and thus layers compose )
3729 or perhaps compose last image over all other images.
3730 */
anthony805a2d42011-09-25 08:25:12 +00003731 Image
anthony31f1bf72012-01-30 12:37:22 +00003732 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003733
anthony31f1bf72012-01-30 12:37:22 +00003734 new_images=RemoveFirstImageFromList(&images);
3735 hald_image=RemoveLastImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003736 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003737 break;
3738 (void) HaldClutImage(new_images,hald_image,exception);
anthony805a2d42011-09-25 08:25:12 +00003739 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003740 break;
3741 }
3742 break;
3743 }
3744 case 'i':
3745 {
anthonyafa3dfc2012-03-03 11:31:30 +00003746 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003747 {
3748 Image
anthony805a2d42011-09-25 08:25:12 +00003749 *magnitude_image,
3750 *phase_image;
3751
anthony31f1bf72012-01-30 12:37:22 +00003752 magnitude_image=RemoveFirstImageFromList(&images);
3753 phase_image=RemoveFirstImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003754 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003755 if (phase_image == (Image *) NULL)
3756 break;
3757 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
3758 normal_op,exception);
3759 magnitude_image=DestroyImage(magnitude_image);
3760 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003761 break;
3762 }
anthonyafa3dfc2012-03-03 11:31:30 +00003763 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003764 {
3765 Image
anthony31f1bf72012-01-30 12:37:22 +00003766 *insert_image,
3767 *index_image;
3768
3769 ssize_t
3770 index;
anthony805a2d42011-09-25 08:25:12 +00003771
3772 index=0;
anthony31f1bf72012-01-30 12:37:22 +00003773 insert_image=RemoveLastImageFromList(&images);
anthonyafa3dfc2012-03-03 11:31:30 +00003774 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003775 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003776 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003777 if (index == 0)
anthony31f1bf72012-01-30 12:37:22 +00003778 PrependImageToList(&images,insert_image);
anthony43f425d2012-02-26 12:58:58 +00003779 else if (index == (ssize_t) GetImageListLength(images))
3780 AppendImageToList(&images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003781 else
anthony43f425d2012-02-26 12:58:58 +00003782 {
3783 index_image=GetImageFromList(images,index-1);
3784 if (index_image == (Image *) NULL)
3785 {
3786 (void) ThrowMagickException(exception,GetMagickModule(),
3787 OptionError,"NoSuchImage","'%s'",arg1);
3788 break;
3789 }
3790 InsertImageInList(&index_image,insert_image);
3791 }
anthony31f1bf72012-01-30 12:37:22 +00003792 images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003793 break;
3794 }
anthony805a2d42011-09-25 08:25:12 +00003795 break;
3796 }
3797 case 'l':
3798 {
anthonyafa3dfc2012-03-03 11:31:30 +00003799 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003800 {
anthony805a2d42011-09-25 08:25:12 +00003801 ImageLayerMethod
3802 method;
3803
anthony805a2d42011-09-25 08:25:12 +00003804 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
anthony31f1bf72012-01-30 12:37:22 +00003805 MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00003806 switch (method)
3807 {
3808 case CoalesceLayer:
3809 {
anthony31f1bf72012-01-30 12:37:22 +00003810 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003811 break;
3812 }
3813 case CompareAnyLayer:
3814 case CompareClearLayer:
3815 case CompareOverlayLayer:
3816 default:
3817 {
anthony31f1bf72012-01-30 12:37:22 +00003818 new_images=CompareImagesLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003819 break;
3820 }
3821 case MergeLayer:
3822 case FlattenLayer:
3823 case MosaicLayer:
3824 case TrimBoundsLayer:
3825 {
anthony31f1bf72012-01-30 12:37:22 +00003826 new_images=MergeImageLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003827 break;
3828 }
3829 case DisposeLayer:
3830 {
anthony31f1bf72012-01-30 12:37:22 +00003831 new_images=DisposeImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003832 break;
3833 }
3834 case OptimizeImageLayer:
3835 {
anthony31f1bf72012-01-30 12:37:22 +00003836 new_images=OptimizeImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003837 break;
3838 }
3839 case OptimizePlusLayer:
3840 {
anthony31f1bf72012-01-30 12:37:22 +00003841 new_images=OptimizePlusImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003842 break;
3843 }
3844 case OptimizeTransLayer:
3845 {
anthony31f1bf72012-01-30 12:37:22 +00003846 OptimizeImageTransparency(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003847 break;
3848 }
3849 case RemoveDupsLayer:
3850 {
anthony31f1bf72012-01-30 12:37:22 +00003851 RemoveDuplicateLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003852 break;
3853 }
3854 case RemoveZeroLayer:
3855 {
anthony31f1bf72012-01-30 12:37:22 +00003856 RemoveZeroDelayLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003857 break;
3858 }
3859 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003860 { /* General Purpose, GIF Animation Optimizer. */
3861 new_images=CoalesceImages(images,exception);
3862 if (new_images == (Image *) NULL)
3863 break;
3864 images=DestroyImageList(images);
3865 images=OptimizeImageLayers(new_images,exception);
3866 if (images == (Image *) NULL)
3867 break;
3868 new_images=DestroyImageList(new_images);
3869 OptimizeImageTransparency(images,exception);
3870 (void) RemapImages(quantize_info,images,(Image *) NULL,
anthony805a2d42011-09-25 08:25:12 +00003871 exception);
3872 break;
3873 }
3874 case CompositeLayer:
3875 {
anthony805a2d42011-09-25 08:25:12 +00003876 Image
3877 *source;
3878
3879 RectangleInfo
3880 geometry;
3881
anthony31f1bf72012-01-30 12:37:22 +00003882 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003883 compose;
3884
3885 const char*
3886 value;
3887
3888 value=GetImageOption(image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003889 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003890 if (value != (const char *) NULL)
3891 compose=(CompositeOperator) ParseCommandOption(
3892 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003893
anthony31f1bf72012-01-30 12:37:22 +00003894 /* Split image sequence at the first 'NULL:' image. */
3895 source=images;
anthony805a2d42011-09-25 08:25:12 +00003896 while (source != (Image *) NULL)
3897 {
3898 source=GetNextImageInList(source);
3899 if ((source != (Image *) NULL) &&
3900 (LocaleCompare(source->magick,"NULL") == 0))
3901 break;
3902 }
3903 if (source != (Image *) NULL)
3904 {
3905 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3906 (GetNextImageInList(source) == (Image *) NULL))
3907 source=(Image *) NULL;
3908 else
anthony31f1bf72012-01-30 12:37:22 +00003909 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003910 source=SplitImageList(source->previous);
3911 DeleteImageFromList(&source);
3912 }
3913 }
3914 if (source == (Image *) NULL)
3915 {
3916 (void) ThrowMagickException(exception,GetMagickModule(),
3917 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003918 break;
3919 }
anthony31f1bf72012-01-30 12:37:22 +00003920 /* Adjust offset with gravity and virtual canvas. */
3921 SetGeometry(images,&geometry);
3922 (void) ParseAbsoluteGeometry(images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003923 geometry.width=source->page.width != 0 ?
3924 source->page.width : source->columns;
3925 geometry.height=source->page.height != 0 ?
3926 source->page.height : source->rows;
anthony31f1bf72012-01-30 12:37:22 +00003927 GravityAdjustGeometry(images->page.width != 0 ?
3928 images->page.width : images->columns,
3929 images->page.height != 0 ? images->page.height :
3930 images->rows,images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003931
anthony31f1bf72012-01-30 12:37:22 +00003932 /* Compose the two image sequences together */
3933 CompositeLayers(images,compose,source,geometry.x,geometry.y,
anthony805a2d42011-09-25 08:25:12 +00003934 exception);
3935 source=DestroyImageList(source);
3936 break;
3937 }
3938 }
anthony805a2d42011-09-25 08:25:12 +00003939 break;
3940 }
anthonyafa3dfc2012-03-03 11:31:30 +00003941 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00003942 {
3943 MagickSizeType
3944 limit;
3945
3946 ResourceType
3947 type;
3948
anthony72feaa62012-01-17 06:46:23 +00003949 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
anthony31f1bf72012-01-30 12:37:22 +00003950 MagickFalse,arg1);
anthony72feaa62012-01-17 06:46:23 +00003951 limit=MagickResourceInfinity;
anthony31f1bf72012-01-30 12:37:22 +00003952 if (LocaleCompare("unlimited",arg2) != 0)
3953 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthony72feaa62012-01-17 06:46:23 +00003954 (void) SetMagickResourceLimit(type,limit);
3955 break;
3956 }
anthony805a2d42011-09-25 08:25:12 +00003957 break;
3958 }
3959 case 'm':
3960 {
anthonyafa3dfc2012-03-03 11:31:30 +00003961 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003962 {
anthony31f1bf72012-01-30 12:37:22 +00003963 /* DEPRECIATED use +remap */
3964 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00003965 break;
3966 }
anthonyafa3dfc2012-03-03 11:31:30 +00003967 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003968 {
3969 Image
3970 *morph_image;
3971
anthony31f1bf72012-01-30 12:37:22 +00003972 morph_image=MorphImages(images,StringToUnsignedLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00003973 exception);
3974 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003975 break;
3976 images=DestroyImageList(images);
3977 images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00003978 break;
3979 }
anthonyafa3dfc2012-03-03 11:31:30 +00003980 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003981 {
anthony31f1bf72012-01-30 12:37:22 +00003982 /* DEPRECIATED use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003983 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003984 break;
3985 }
3986 break;
3987 }
3988 case 'p':
3989 {
anthonyafa3dfc2012-03-03 11:31:30 +00003990 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003991 {
3992 char
3993 *string;
3994
anthony31f1bf72012-01-30 12:37:22 +00003995 string=InterpretImageProperties(image_info,images,arg1,
anthony805a2d42011-09-25 08:25:12 +00003996 exception);
3997 if (string == (char *) NULL)
3998 break;
3999 (void) FormatLocaleFile(stdout,"%s",string);
4000 string=DestroyString(string);
4001 }
anthonyafa3dfc2012-03-03 11:31:30 +00004002 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004003 {
4004 char
4005 **arguments;
4006
4007 int
4008 j,
4009 number_arguments;
4010
anthony31f1bf72012-01-30 12:37:22 +00004011 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004012 if (arguments == (char **) NULL)
4013 break;
anthony31f1bf72012-01-30 12:37:22 +00004014 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004015 {
4016 char
4017 breaker,
4018 quote,
4019 *token;
4020
4021 const char
4022 *arguments;
4023
4024 int
4025 next,
4026 status;
4027
4028 size_t
4029 length;
4030
4031 TokenInfo
4032 *token_info;
4033
4034 /*
4035 Support old style syntax, filter="-option arg".
4036 */
anthony31f1bf72012-01-30 12:37:22 +00004037 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004038 token=(char *) NULL;
4039 if (~length >= (MaxTextExtent-1))
4040 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4041 sizeof(*token));
4042 if (token == (char *) NULL)
4043 break;
4044 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004045 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004046 token_info=AcquireTokenInfo();
4047 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4048 "\"",'\0',&breaker,&next,&quote);
4049 token_info=DestroyTokenInfo(token_info);
4050 if (status == 0)
4051 {
4052 const char
4053 *argv;
4054
4055 argv=(&(arguments[next]));
anthony31f1bf72012-01-30 12:37:22 +00004056 (void) InvokeDynamicImageFilter(token,&images,1,&argv,
anthony805a2d42011-09-25 08:25:12 +00004057 exception);
4058 }
4059 token=DestroyString(token);
4060 break;
4061 }
4062 (void) SubstituteString(&arguments[1],"-","");
anthony31f1bf72012-01-30 12:37:22 +00004063 (void) InvokeDynamicImageFilter(arguments[1],&images,
anthony805a2d42011-09-25 08:25:12 +00004064 number_arguments-2,(const char **) arguments+2,exception);
4065 for (j=0; j < number_arguments; j++)
4066 arguments[j]=DestroyString(arguments[j]);
4067 arguments=(char **) RelinquishMagickMemory(arguments);
4068 break;
4069 }
4070 break;
4071 }
4072 case 'r':
4073 {
anthonyafa3dfc2012-03-03 11:31:30 +00004074 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004075 {
anthony31f1bf72012-01-30 12:37:22 +00004076 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
4077 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
4078 break;
4079 }
anthonyafa3dfc2012-03-03 11:31:30 +00004080 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004081 {
4082 ReverseImageList(&images);
anthony805a2d42011-09-25 08:25:12 +00004083 break;
4084 }
4085 break;
4086 }
4087 case 's':
4088 {
anthonyafa3dfc2012-03-03 11:31:30 +00004089 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004090 {
4091 Image
4092 *smush_image;
4093
4094 ssize_t
4095 offset;
4096
anthony31f1bf72012-01-30 12:37:22 +00004097 offset=(ssize_t) StringToLong(arg1);
4098 smush_image=SmushImages(images,normal_op,offset,exception);
anthony805a2d42011-09-25 08:25:12 +00004099 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004100 break;
4101 images=DestroyImageList(images);
4102 images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004103 break;
4104 }
anthonyafa3dfc2012-03-03 11:31:30 +00004105 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004106 {
4107 Image
4108 *p,
4109 *q,
4110 *swap;
4111
4112 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004113 index,
anthony805a2d42011-09-25 08:25:12 +00004114 swap_index;
4115
anthony31f1bf72012-01-30 12:37:22 +00004116 index=-1;
4117 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004118 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004119 {
4120 GeometryInfo
4121 geometry_info;
4122
4123 MagickStatusType
4124 flags;
4125
4126 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004127 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004128 index=(ssize_t) geometry_info.rho;
4129 if ((flags & SigmaValue) != 0)
4130 swap_index=(ssize_t) geometry_info.sigma;
4131 }
anthony31f1bf72012-01-30 12:37:22 +00004132 p=GetImageFromList(images,index);
4133 q=GetImageFromList(images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004134 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4135 {
4136 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +00004137 OptionError,"NoSuchImage","'%s'",images->filename);
anthony805a2d42011-09-25 08:25:12 +00004138 break;
4139 }
4140 if (p == q)
4141 break;
4142 swap=CloneImage(p,0,0,MagickTrue,exception);
4143 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4144 ReplaceImageInList(&q,swap);
anthony31f1bf72012-01-30 12:37:22 +00004145 images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004146 break;
4147 }
4148 break;
4149 }
4150 case 'w':
4151 {
anthonyafa3dfc2012-03-03 11:31:30 +00004152 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004153 {
4154 char
4155 key[MaxTextExtent];
4156
4157 Image
4158 *write_images;
4159
4160 ImageInfo
4161 *write_info;
4162
anthony31f1bf72012-01-30 12:37:22 +00004163 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004164 (void) DeleteImageRegistry(key);
anthony31f1bf72012-01-30 12:37:22 +00004165 write_images=images;
anthonyafa3dfc2012-03-03 11:31:30 +00004166 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00004167 write_images=CloneImageList(images,exception);
anthony805a2d42011-09-25 08:25:12 +00004168 write_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00004169 (void) WriteImages(write_info,write_images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00004170 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004171 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004172 write_images=DestroyImageList(write_images);
4173 break;
4174 }
4175 break;
4176 }
4177 default:
4178 break;
4179 }
anthony31f1bf72012-01-30 12:37:22 +00004180 if (new_images == (Image *) NULL)
4181 return;
anthony805a2d42011-09-25 08:25:12 +00004182
anthony31f1bf72012-01-30 12:37:22 +00004183 if (images != (Image *) NULL)
4184 images=DestroyImageList(images);
anthony43f425d2012-02-26 12:58:58 +00004185 images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004186 return;
4187
4188#undef image_info
anthony31f1bf72012-01-30 12:37:22 +00004189#undef images
4190#undef exception
anthony43f425d2012-02-26 12:58:58 +00004191#undef draw_info
4192#undef quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004193#undef IfNormalOp
4194#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004195#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004196}
anthony43f425d2012-02-26 12:58:58 +00004197
4198/*
4199%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4200% %
4201% %
4202% %
4203+ C L I S p e c i a l O p e r a t i o n s %
4204% %
4205% %
4206% %
4207%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4208%
4209% CLISpecialOption() Applies operations that may involve empty image lists
4210% and or stacks of image lists or image_info settings.
4211%
anthonyafa3dfc2012-03-03 11:31:30 +00004212% The classic operators of this type is -read, and image stack operators,
4213% which can be applied to empty image lists.
4214%
4215% Note: unlike other Operators, these may involve other special 'option'
4216% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004217%
4218% The format of the CLISpecialOption method is:
4219%
4220% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
4221% const char *arg)
4222%
4223% A description of each parameter follows:
4224%
4225% o cli_wand: the main CLI Wand to use.
4226%
4227% o option: The special option (with any switch char) to process
4228%
4229% o arg: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004230%
anthony2052d272012-02-28 12:48:29 +00004231% Example Usage...
4232%
4233% CLISpecialOperator(cli_wand,"-read", "rose:");
anthony2052d272012-02-28 12:48:29 +00004234%
4235% Or for handling command line arguments EG: +/-option ["arg"]
4236%
4237% cli_wand
4238% argc,argv
4239% i=index in argv
4240%
4241% option_info = GetCommandOptionInfo(argv[i]);
4242% count=option_info->type;
4243% option_type=option_info->flags;
4244%
4245% if ( (option_type & SpecialOptionFlag) != 0 )
4246% CLISpecialOperator(cli_wand,argv[i],
4247% count>=1 ? argv[i+1] : (char *)NULL);
4248% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004249%
4250*/
4251
anthony43f425d2012-02-26 12:58:58 +00004252WandExport void CLISpecialOperator(MagickCLI *cli_wand,
4253 const char *option, const char *arg)
4254{
4255#define exception (cli_wand->wand.exception)
4256
4257 assert(cli_wand != (MagickCLI *) NULL);
4258 assert(cli_wand->signature == WandSignature);
4259 assert(cli_wand->wand.signature == WandSignature);
4260 if (cli_wand->wand.debug != MagickFalse)
4261 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4262
anthonyafa3dfc2012-03-03 11:31:30 +00004263 if (LocaleCompare("(",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004264 {
4265 /* stack 'push' images */
4266 Stack
4267 *node;
4268
4269 size_t
4270 size;
4271
4272 const char*
4273 value;
4274
4275 size=0;
4276 node=cli_wand->image_list_stack;
4277 for ( ; node != (Stack *)NULL; node=node->next)
4278 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004279 if ( size >= MAX_STACK_DEPTH )
anthony43f425d2012-02-26 12:58:58 +00004280 {
4281 ThrowMagickException(exception,GetMagickModule(),
4282 OptionError,"ParenthesisNestedTooDeeply", option);
4283 return;
4284 }
4285 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4286 if (node == (Stack *) NULL)
4287 {
4288 ThrowMagickException(exception,GetMagickModule(),
4289 ResourceLimitFatalError,"MemoryAllocationFailed", "PushImages");
4290 return;
4291 }
4292 node->data = (void *)cli_wand->wand.images;
4293 cli_wand->wand.images = NewImageList();
4294 node->next = cli_wand->image_list_stack;
4295 cli_wand->image_list_stack = node;
4296
4297 /* handle respect-parenthesis */
4298 value=GetImageOption(cli_wand->wand.image_info,"respect-parenthesis");
4299 if (value != (const char *) NULL)
4300 option="{";
4301 else
4302 return;
4303 }
anthonyafa3dfc2012-03-03 11:31:30 +00004304 if (LocaleCompare("{",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004305 {
4306 /* stack 'push' of image_info settings */
4307 Stack
4308 *node;
4309
4310 size_t
4311 size;
4312
4313 size=0;
4314 node=cli_wand->image_info_stack;
4315 for ( ; node != (Stack *)NULL; node=node->next)
4316 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004317 if ( size >= MAX_STACK_DEPTH ) {
4318 ThrowMagickException(exception,GetMagickModule(),
4319 OptionError,"ParenthesisNestedTooDeeply", option);
4320 return;
4321 }
anthony43f425d2012-02-26 12:58:58 +00004322 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthonyafa3dfc2012-03-03 11:31:30 +00004323 if (node == (Stack *) NULL) {
4324 ThrowMagickException(exception,GetMagickModule(),
4325 ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
4326 return;
4327 }
anthony43f425d2012-02-26 12:58:58 +00004328
4329 node->data = (void *)cli_wand->wand.image_info;
4330 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004331 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
4332 ThrowMagickException(exception,GetMagickModule(),
4333 ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
4334 cli_wand->wand.image_info = (ImageInfo *)node->data;
4335 node = (Stack *)RelinquishMagickMemory(node);
4336 return;
4337 }
anthony43f425d2012-02-26 12:58:58 +00004338
4339 node->next = cli_wand->image_info_stack;
4340 cli_wand->image_info_stack = node;
4341
4342 return;
4343 }
anthonyafa3dfc2012-03-03 11:31:30 +00004344 if (LocaleCompare(")",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004345 {
4346 /* pop images from stack */
4347 Stack
4348 *node;
4349
4350 const char*
4351 value;
4352
4353 node = (void *)cli_wand->image_list_stack;
4354 if ( node == (Stack *)NULL)
4355 {
4356 ThrowMagickException(exception,GetMagickModule(),
4357 OptionError,"UnbalancedParenthesis", option);
4358 return;
4359 }
4360 cli_wand->image_list_stack = node->next;
4361
4362 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4363 cli_wand->wand.images= (Image *)node->data;
4364 node = (Stack *)RelinquishMagickMemory(node);
4365
4366 /* handle respect-parenthesis - of the previous 'push' settings */
4367 node = cli_wand->image_info_stack;
4368 if ( node != (Stack *)NULL)
4369 {
4370 value=GetImageOption((ImageInfo *)node->data,"respect-parenthesis");
4371 if (value != (const char *) NULL)
4372 option="}";
4373 else
4374 return;
4375 }
4376 else
4377 return;
4378 }
anthonyafa3dfc2012-03-03 11:31:30 +00004379 if (LocaleCompare("}",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004380 {
4381 /* pop image_info settings from stack */
4382 Stack
4383 *node;
4384
4385 node = (void *)cli_wand->image_info_stack;
4386 if ( node == (Stack *)NULL)
4387 {
4388 ThrowMagickException(exception,GetMagickModule(),
4389 OptionError,"UnbalancedParenthesis", option);
4390 return;
4391 }
4392 cli_wand->image_info_stack = node->next;
4393
4394 (void) DestroyImageInfo(cli_wand->wand.image_info);
4395 cli_wand->wand.image_info = (ImageInfo *)node->data;
4396 node = (Stack *)RelinquishMagickMemory(node);
4397
4398 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4399 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4400 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4401
4402 return;
4403 }
anthonyafa3dfc2012-03-03 11:31:30 +00004404 if (LocaleCompare("clone",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004405 {
4406 Image
4407 *new_images;
4408
4409 if (*option == '+')
4410 arg="-1";
4411 if (IsSceneGeometry(arg,MagickFalse) == MagickFalse)
4412 {
4413 ThrowMagickException(exception,GetMagickModule(),
4414 OptionError,"InvalidArgument", "'%s': %s", option, arg);
4415 return;
4416 }
4417 if ( cli_wand->image_list_stack == (Stack *)NULL)
4418 {
4419 ThrowMagickException(exception,GetMagickModule(),
4420 OptionError,"UnableToCloneImage", option);
4421 return;
4422 }
4423 new_images = (Image *)cli_wand->image_list_stack->data;
4424 if (new_images == (Image *) NULL)
4425 {
4426 ThrowMagickException(exception,GetMagickModule(),
4427 OptionError,"UnableToCloneImage", option);
4428 return;
4429 }
4430 new_images=CloneImages(new_images,arg,exception);
4431 if (new_images == (Image *) NULL)
4432 {
4433 ThrowMagickException(exception,GetMagickModule(),
4434 OptionError,"NoSuchImage",option);
4435 return;
4436 }
4437 AppendImageToList(&cli_wand->wand.images,new_images);
4438 return;
4439 }
anthonyafa3dfc2012-03-03 11:31:30 +00004440 if ( LocaleCompare("read",option+1) == 0 )
anthony43f425d2012-02-26 12:58:58 +00004441 {
anthonyafa3dfc2012-03-03 11:31:30 +00004442#if !USE_WAND_METHODS
anthony43f425d2012-02-26 12:58:58 +00004443 Image *
4444 new_images;
4445
anthony43f425d2012-02-26 12:58:58 +00004446 if (cli_wand->wand.image_info->ping != MagickFalse)
anthonyafa3dfc2012-03-03 11:31:30 +00004447 new_images=PingImages(cli_wand->wand.image_info,arg,exception);
anthony43f425d2012-02-26 12:58:58 +00004448 else
anthonyafa3dfc2012-03-03 11:31:30 +00004449 new_images=ReadImages(cli_wand->wand.image_info,arg,exception);
anthony43f425d2012-02-26 12:58:58 +00004450 AppendImageToList(&cli_wand->wand.images, new_images);
4451#else
4452 /* read images using MagickWand method - no ping */
4453 /* This is not working! - it locks up in a CPU loop! */
4454 MagickSetLastIterator(&cli_wand->wand);
4455 MagickReadImage(&cli_wand->wand,arg);
4456 MagickSetFirstIterator(&cli_wand->wand);
4457#endif
4458 return;
4459 }
anthonyafa3dfc2012-03-03 11:31:30 +00004460 /* No-op options */
4461 if (LocaleCompare("noop",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004462 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004463 if (LocaleCompare("sans",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004464 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004465 if (LocaleCompare("sans0",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004466 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004467 if (LocaleCompare("sans2",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004468 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004469 if (LocaleCompare("list",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004470 {
4471 /* FUTURE: This should really be built into the MagickCore
4472 It does not actually require any wand or images at all!
4473 */
4474 ssize_t
4475 list;
4476
4477 list=ParseCommandOption(MagickListOptions,MagickFalse, arg);
4478 switch (list)
4479 {
4480 case MagickCoderOptions:
4481 {
4482 (void) ListCoderInfo((FILE *) NULL,exception);
4483 break;
4484 }
4485 case MagickColorOptions:
4486 {
4487 (void) ListColorInfo((FILE *) NULL,exception);
4488 break;
4489 }
4490 case MagickConfigureOptions:
4491 {
4492 (void) ListConfigureInfo((FILE *) NULL,exception);
4493 break;
4494 }
4495 case MagickDelegateOptions:
4496 {
4497 (void) ListDelegateInfo((FILE *) NULL,exception);
4498 break;
4499 }
4500 case MagickFontOptions:
4501 {
4502 (void) ListTypeInfo((FILE *) NULL,exception);
4503 break;
4504 }
4505 case MagickFormatOptions:
4506 (void) ListMagickInfo((FILE *) NULL,exception);
4507 break;
4508 case MagickLocaleOptions:
4509 (void) ListLocaleInfo((FILE *) NULL,exception);
4510 break;
4511 case MagickLogOptions:
4512 (void) ListLogInfo((FILE *) NULL,exception);
4513 break;
4514 case MagickMagicOptions:
4515 (void) ListMagicInfo((FILE *) NULL,exception);
4516 break;
4517 case MagickMimeOptions:
4518 (void) ListMimeInfo((FILE *) NULL,exception);
4519 break;
4520 case MagickModuleOptions:
4521 (void) ListModuleInfo((FILE *) NULL,exception);
4522 break;
4523 case MagickPolicyOptions:
4524 (void) ListPolicyInfo((FILE *) NULL,exception);
4525 break;
4526 case MagickResourceOptions:
4527 (void) ListMagickResourceInfo((FILE *) NULL,exception);
4528 break;
4529 case MagickThresholdOptions:
4530 (void) ListThresholdMaps((FILE *) NULL,exception);
4531 break;
4532 default:
4533 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4534 exception);
4535 break;
4536 }
4537 return;
4538 }
4539
4540#if 0
4541 // adjust stack handling
4542 // Other 'special' options this should handle
4543 // "region" "list" "version"
4544 // It does not do "exit" however as due to its side-effect requirements
4545#endif
4546#if 0
4547 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
4548 MagickExceptionReturn(OptionError,"InvalidUseOfOption",option);
4549#endif
4550
4551#undef image_info
4552#undef images
4553#undef exception
4554}