blob: c07ec7a3ccb18f5a58646af89642ce7fbf8c9417 [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;
anthony92c93bd2012-03-19 14:02:47 +0000426 cli_wand->location="'%s' at unknown";
427 cli_wand->location2="'%s' '%s' at unknown";
anthony319dac62012-03-06 04:12:44 +0000428 cli_wand->filename=cli_wand->wand.name;
anthony1cdc5b72012-03-03 02:31:18 +0000429 cli_wand->line=0;
430 cli_wand->column=0;
anthony43f425d2012-02-26 12:58:58 +0000431 cli_wand->signature=WandSignature;
432
433 if (cli_wand->wand.debug != MagickFalse)
434 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
435 return(cli_wand);
436}
437
438/*
439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440% %
441% %
442% %
443+ D e s t r o y W a n d C L I %
444% %
445% %
446% %
447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448%
449% DestroyMagickCLI() destorys everything in a CLI wand, including image_info
450% and any exceptions, if still present in the wand.
451%
452% The format of the NewMagickWand method is:
anthonyafa3dfc2012-03-03 11:31:30 +0000453%
anthony43f425d2012-02-26 12:58:58 +0000454% MagickWand *DestroyMagickCLI()
455% Exception *exception)
456%
457*/
458WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
459{
460 Stack
461 *node;
462
463 assert(cli_wand != (MagickCLI *) NULL);
464 assert(cli_wand->signature == WandSignature);
465 assert(cli_wand->wand.signature == WandSignature);
466 if (cli_wand->wand.debug != MagickFalse)
467 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
468
469 /* Destroy CLI part of MagickCLI */
470 if (cli_wand->draw_info != (DrawInfo *) NULL )
471 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
472 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
473 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
474 while(cli_wand->image_list_stack != (Stack *)NULL)
475 {
476 node=cli_wand->image_list_stack;
477 cli_wand->image_list_stack=node->next;
478 (void) DestroyImageList((Image *)node->data);
479 (void) RelinquishMagickMemory(node);
480 }
481 while(cli_wand->image_info_stack != (Stack *)NULL)
482 {
483 node=cli_wand->image_info_stack;
484 cli_wand->image_info_stack=node->next;
485 (void) DestroyImageInfo((ImageInfo *)node->data);
486 (void) RelinquishMagickMemory(node);
487 }
488 cli_wand->signature=(~WandSignature);
489
490 /* Destroy Wand part MagickCLI */
491 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
492 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
493 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
494 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
495 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
496 RelinquishWandId(cli_wand->wand.id);
497 cli_wand->wand.signature=(~WandSignature);
498
499 return((MagickCLI *)NULL);
500}
501
502/*
503%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504% %
505% %
506% %
anthony2052d272012-02-28 12:48:29 +0000507+ C L I C a t c h E x c e p t i o n %
508% %
509% %
510% %
511%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512%
513% CLICatchException() will report exceptions, either just non-fatal warnings
514% only, or all errors, according to 'all_execeptions' boolean argument.
515%
516% The function returns true is errors are fatal, in which case the caller
517% should abort and re-call with an 'all_exceptions' argument of true before
518% quitting.
519%
520% The cut-off level between fatal and non-fatal may be controlled by options
521% (FUTURE), but defaults to 'Error' exceptions.
522%
523% The format of the CLICatchException method is:
524%
525% MagickBooleanType CLICatchException(MagickCLI *cli_wand,
526% const MagickBooleanType all_exceptions );
527%
528*/
529WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
530 const MagickBooleanType all_exceptions )
531{
532 MagickBooleanType
533 status;
534 assert(cli_wand != (MagickCLI *) NULL);
535 assert(cli_wand->signature == WandSignature);
536 assert(cli_wand->wand.signature == WandSignature);
537 if (cli_wand->wand.debug != MagickFalse)
538 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
539
540 // FUTURE: '-regard_warning' should make this more sensitive.
541 // Note pipelined options may like more control over this level
542
543 status = MagickFalse;
544 if (cli_wand->wand.exception->severity > ErrorException)
545 status = MagickTrue;
546
547 if ( status == MagickFalse || all_exceptions != MagickFalse )
548 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
549
550 return(status);
551}
552
553/*
554%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
555% %
556% %
557% %
anthony43f425d2012-02-26 12:58:58 +0000558+ C L I S e t t i n g O p t i o n I n f o %
559% %
560% %
561% %
562%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
563%
564% CLISettingOptionInfo() applies a single settings option into a CLI wand
565% holding the image_info, draw_info, quantize_info structures that will be
566% used when processing the images.
567%
568% These options do no require images to be present in the CLI wand for them
569% to be able to be set, in which case they will generally be applied to image
570% that are read in later
anthony80c37752012-01-16 01:03:11 +0000571%
572% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000573% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000574%
anthony2052d272012-02-28 12:48:29 +0000575% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000576%
anthonyafa3dfc2012-03-03 11:31:30 +0000577% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +0000578% const char *option, const char *arg1)
anthony805a2d42011-09-25 08:25:12 +0000579%
580% A description of each parameter follows:
581%
anthony43f425d2012-02-26 12:58:58 +0000582% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000583%
anthonydcf510d2011-10-30 13:51:40 +0000584% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000585%
anthony24aa8822012-03-11 00:56:06 +0000586% o arg1: The single argument used to set this option.
anthonydcf510d2011-10-30 13:51:40 +0000587%
anthony72feaa62012-01-17 06:46:23 +0000588% Example usage...
589%
anthonyafa3dfc2012-03-03 11:31:30 +0000590% CLISettingOptionInfo(cli_wand, "-background", "Red"); // set value
591% CLISettingOptionInfo(cli_wand, "-adjoin", NULL); // set boolean
592% CLISettingOptionInfo(cli_wand, "+adjoin", NULL); // unset
anthony72feaa62012-01-17 06:46:23 +0000593%
anthony24aa8822012-03-11 00:56:06 +0000594% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +0000595%
596% argc,argv
597% i=index in argv
598%
anthony2052d272012-02-28 12:48:29 +0000599% option_info = GetCommandOptionInfo(argv[i]);
600% count=option_info->type;
601% option_type=option_info->flags;
602%
603% if ( (option_type & SettingOperatorOptionFlags) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +0000604% CLISettingOptionInfo(cli_wand, argv[i],
605% (count>0) ? argv[i+1] : (char *)NULL);
anthonydcf510d2011-10-30 13:51:40 +0000606% i += count+1;
607%
anthony805a2d42011-09-25 08:25:12 +0000608*/
anthonyafa3dfc2012-03-03 11:31:30 +0000609WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +0000610 const char *option,const char *arg1)
anthony805a2d42011-09-25 08:25:12 +0000611{
anthony43f425d2012-02-26 12:58:58 +0000612 assert(cli_wand != (MagickCLI *) NULL);
613 assert(cli_wand->signature == WandSignature);
614 assert(cli_wand->wand.signature == WandSignature);
615 if (cli_wand->wand.debug != MagickFalse)
616 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony1afdc7a2011-10-05 11:54:28 +0000617
anthony92c93bd2012-03-19 14:02:47 +0000618#define _image_info (cli_wand->wand.image_info)
619#define _exception (cli_wand->wand.exception)
620#define _draw_info (cli_wand->draw_info)
621#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000622#define IfSetOption (*option=='-')
623#define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
624#define ArgBooleanNot (IfSetOption?MagickFalse:MagickTrue)
625#define ArgBooleanString (IfSetOption?"true":"false")
626#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000627
anthonyafa3dfc2012-03-03 11:31:30 +0000628 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000629 {
630 case 'a':
631 {
anthonyafa3dfc2012-03-03 11:31:30 +0000632 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000633 {
anthony92c93bd2012-03-19 14:02:47 +0000634 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000635 break;
636 }
anthonyafa3dfc2012-03-03 11:31:30 +0000637 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000638 {
anthony92c93bd2012-03-19 14:02:47 +0000639 /* DEPRECIATED: _draw_info setting only: for -draw and -transform */
anthony74b1cfc2011-10-06 12:44:16 +0000640 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000641 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000642 else
anthony92c93bd2012-03-19 14:02:47 +0000643 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000644 break;
645 }
anthonyafa3dfc2012-03-03 11:31:30 +0000646 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000647 {
anthony92c93bd2012-03-19 14:02:47 +0000648 _image_info->antialias =
649 _draw_info->stroke_antialias =
650 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000651 break;
652 }
anthony31f1bf72012-01-30 12:37:22 +0000653 if (LocaleCompare("attenuate",option+1) == 0)
654 {
anthony92c93bd2012-03-19 14:02:47 +0000655 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
656 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
657 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000658 break;
659 }
anthonyafa3dfc2012-03-03 11:31:30 +0000660 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000661 {
anthony92c93bd2012-03-19 14:02:47 +0000662 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000663 break;
664 }
665 break;
666 }
667 case 'b':
668 {
anthonyafa3dfc2012-03-03 11:31:30 +0000669 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000670 {
anthony92c93bd2012-03-19 14:02:47 +0000671 /* FUTURE: both _image_info attribute & ImageOption in use!
672 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000673 SyncImageSettings() used to set per-image attribute.
674
anthony92c93bd2012-03-19 14:02:47 +0000675 FUTURE: if _image_info->background_color is not set then
anthony72feaa62012-01-17 06:46:23 +0000676 we should fall back to image
677 Note that +background, means fall-back to image background
678 and only if not set fall back to BackgroundColor const.
anthony74b1cfc2011-10-06 12:44:16 +0000679 */
anthony92c93bd2012-03-19 14:02:47 +0000680 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000681 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000682 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000683 break;
684 }
anthonyafa3dfc2012-03-03 11:31:30 +0000685 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000686 {
anthony74b1cfc2011-10-06 12:44:16 +0000687 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000688 as it is actually rarely used except in direct convolve operations
689 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000690
691 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000692 */
anthony92c93bd2012-03-19 14:02:47 +0000693 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000694 break;
695 }
anthonyafa3dfc2012-03-03 11:31:30 +0000696 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000697 {
anthony72feaa62012-01-17 06:46:23 +0000698 /* Used as a image chromaticity setting
699 SyncImageSettings() used to set per-image attribute.
700 */
anthony92c93bd2012-03-19 14:02:47 +0000701 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000702 break;
703 }
anthonyafa3dfc2012-03-03 11:31:30 +0000704 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000705 {
anthonyafbaed72011-10-26 12:05:04 +0000706 /* Image chromaticity X,Y NB: Y=X if Y not defined
707 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000708 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000709 */
anthony92c93bd2012-03-19 14:02:47 +0000710 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000711 break;
712 }
anthonyafa3dfc2012-03-03 11:31:30 +0000713 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000714 {
anthony92c93bd2012-03-19 14:02:47 +0000715 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000716 SyncImageSettings() used to set per-image attribute.
717 */
anthony74b1cfc2011-10-06 12:44:16 +0000718 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000719 {
anthony92c93bd2012-03-19 14:02:47 +0000720 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000721 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000722 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000723 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000724 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000725 break;
726 }
anthony92c93bd2012-03-19 14:02:47 +0000727 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000728 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000729 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000730 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000731 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000732 break;
733 }
anthonyafa3dfc2012-03-03 11:31:30 +0000734 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000735 {
anthonyfd706f92012-01-19 04:22:02 +0000736 /* DEPRECIATED - now "undercolor" */
anthony24aa8822012-03-11 00:56:06 +0000737 CLISettingOptionInfo(cli_wand,"undercolor",arg1);
anthonyfd706f92012-01-19 04:22:02 +0000738 break;
anthony805a2d42011-09-25 08:25:12 +0000739 }
740 break;
741 }
742 case 'c':
743 {
anthonyafa3dfc2012-03-03 11:31:30 +0000744 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000745 {
746 MagickSizeType
747 limit;
748
749 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000750 if (LocaleCompare("unlimited",arg1) != 0)
751 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000752 (void) SetMagickResourceLimit(MemoryResource,limit);
753 (void) SetMagickResourceLimit(MapResource,2*limit);
754 break;
755 }
anthonyafa3dfc2012-03-03 11:31:30 +0000756 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000757 {
anthony92c93bd2012-03-19 14:02:47 +0000758 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000759 break;
760 }
anthonyafa3dfc2012-03-03 11:31:30 +0000761 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000762 {
anthony43f425d2012-02-26 12:58:58 +0000763 /* FUTURE: -channel mask {vaules}
anthony24aa8822012-03-11 00:56:06 +0000764 This is also applied to images in SimpleImageOperator!!!
anthony43f425d2012-02-26 12:58:58 +0000765 Move it to SyncImageSettings() - or alternative
anthony31f1bf72012-01-30 12:37:22 +0000766 */
anthony92c93bd2012-03-19 14:02:47 +0000767 _image_info->channel=(ChannelType) (
anthony24aa8822012-03-11 00:56:06 +0000768 IfSetOption ? ParseChannelOption(arg1) : DefaultChannels );
anthony805a2d42011-09-25 08:25:12 +0000769 break;
770 }
anthonyafa3dfc2012-03-03 11:31:30 +0000771 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000772 {
anthonyafbaed72011-10-26 12:05:04 +0000773 /* Setting used for new images via AquireImage()
774 But also used as a SimpleImageOperator
775 Undefined colorspace means don't modify images on
776 read or as a operation */
anthony92c93bd2012-03-19 14:02:47 +0000777 _image_info->colorspace=(ColorspaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000778 MagickColorspaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000779 break;
780 }
anthonyafa3dfc2012-03-03 11:31:30 +0000781 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000782 {
anthony92c93bd2012-03-19 14:02:47 +0000783 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000784 break;
785 }
anthonyafa3dfc2012-03-03 11:31:30 +0000786 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000787 {
anthony92c93bd2012-03-19 14:02:47 +0000788 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000789 SyncImageSettings() used to set per-image attribute. - REMOVE
790
anthonyafbaed72011-10-26 12:05:04 +0000791 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000792 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000793 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000794 */
anthony92c93bd2012-03-19 14:02:47 +0000795 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
796 _image_info->compose=(CompositeOperator) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000797 MagickComposeOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000798 break;
799 }
anthonyafa3dfc2012-03-03 11:31:30 +0000800 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000801 {
anthony92c93bd2012-03-19 14:02:47 +0000802 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000803 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000804 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000805
anthony92c93bd2012-03-19 14:02:47 +0000806 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000807 however the image attribute (for save) is set from the
808 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000809
810 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000811 */
anthony92c93bd2012-03-19 14:02:47 +0000812 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
813 _image_info->compression=(CompressionType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000814 MagickCompressOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000815 break;
816 }
817 break;
818 }
819 case 'd':
820 {
anthonyafa3dfc2012-03-03 11:31:30 +0000821 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000822 {
anthony72feaa62012-01-17 06:46:23 +0000823 /* SyncImageSettings() used to set per-image attribute. */
824 (void) SetLogEventMask(ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000825 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000826 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000827 break;
828 }
anthonyafa3dfc2012-03-03 11:31:30 +0000829 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000830 {
anthony24aa8822012-03-11 00:56:06 +0000831 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000832 {
anthony5f867ae2011-10-09 10:28:34 +0000833 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000834 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000835 else
anthony24aa8822012-03-11 00:56:06 +0000836 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000837 break;
838 }
anthony24aa8822012-03-11 00:56:06 +0000839 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000840 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000841 (void) DefineImageOption(_image_info,arg1);
anthony5f867ae2011-10-09 10:28:34 +0000842 else
anthony92c93bd2012-03-19 14:02:47 +0000843 (void) DeleteImageOption(_image_info,arg1);
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 */
anthony92c93bd2012-03-19 14:02:47 +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 {
anthony92c93bd2012-03-19 14:02:47 +0000856 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000857 Basically as density can be in a XxY form!
858
859 SyncImageSettings() used to set per-image attribute.
860 */
anthony92c93bd2012-03-19 14:02:47 +0000861 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
862 (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 */
anthony92c93bd2012-03-19 14:02:47 +0000871 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
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 {
anthony92c93bd2012-03-19 14:02:47 +0000877 /* Image Option is only used to set _draw_info */
878 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
879 _draw_info->direction=(DirectionType) ParseCommandOption(
anthony5f867ae2011-10-09 10:28:34 +0000880 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 {
anthony92c93bd2012-03-19 14:02:47 +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 */
anthony92c93bd2012-03-19 14:02:47 +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 {
anthony92c93bd2012-03-19 14:02:47 +0000898 /* _image_info attr (on/off), _quantize_info attr (on/off)
899 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000900 FUTURE: merge the duality of the dithering options
901 */
anthony92c93bd2012-03-19 14:02:47 +0000902 _image_info->dither = _quantize_info->dither = ArgBoolean;
903 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
904 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000905 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000906 if (_quantize_info->dither_method == NoDitherMethod)
907 _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 {
anthony92c93bd2012-03-19 14:02:47 +0000916 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
917 (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 {
anthony92c93bd2012-03-19 14:02:47 +0000922 /* Both _image_info attr and ImageInfo */
923 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
924 _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 {
anthony92c93bd2012-03-19 14:02:47 +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 {
anthony92c93bd2012-03-19 14:02:47 +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 {
anthony92c93bd2012-03-19 14:02:47 +0000944 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000945 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");
anthony92c93bd2012-03-19 14:02:47 +0000962 (void) SetImageOption(_image_info,option+1,value);
963 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)
anthony92c93bd2012-03-19 14:02:47 +0000972 _draw_info->fill_pattern=GetImageCache(_image_info,value,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000973 else
anthony92c93bd2012-03-19 14:02:47 +0000974 _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. */
anthony92c93bd2012-03-19 14:02:47 +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 {
anthony92c93bd2012-03-19 14:02:47 +0000985 (void) CloneString(&_draw_info->font,ArgOption(NULL));
986 (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
anthony24aa8822012-03-11 00:56:06 +0000996 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000997 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +0000998 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000999 */
anthony92c93bd2012-03-19 14:02:47 +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
anthony92c93bd2012-03-19 14:02:47 +00001009 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 {
anthony92c93bd2012-03-19 14:02:47 +00001013 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +00001014 QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00001015 (void) SetImageOption(_image_info,option+1,arg1);
cristy947cb4c2011-10-20 18:41:46 +00001016 break;
1017 }
anthony92c93bd2012-03-19 14:02:47 +00001018 _image_info->fuzz=0.0;
1019 (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. */
anthony92c93bd2012-03-19 14:02:47 +00001029 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
1030 _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 */
anthony92c93bd2012-03-19 14:02:47 +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 */
anthony92c93bd2012-03-19 14:02:47 +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 {
anthony92c93bd2012-03-19 14:02:47 +00001058 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +00001059 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001060 */
anthony92c93bd2012-03-19 14:02:47 +00001061 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
1062 _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 {
anthony92c93bd2012-03-19 14:02:47 +00001068 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1069 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +00001070 (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. */
anthony92c93bd2012-03-19 14:02:47 +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 {
anthony92c93bd2012-03-19 14:02:47 +00001081 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1082 _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 {
anthony92c93bd2012-03-19 14:02:47 +00001091 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1092 _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() */
anthony92c93bd2012-03-19 14:02:47 +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)
anthony24aa8822012-03-11 00:56:06 +00001108 (void) SetLogFormat(arg1);
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. */
anthony92c93bd2012-03-19 14:02:47 +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. */
anthony92c93bd2012-03-19 14:02:47 +00001124 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001125 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001126 &_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 {
anthony92c93bd2012-03-19 14:02:47 +00001131 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001132 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 {
anthony24aa8822012-03-11 00:56:06 +00001137 /* Setting (used by some input coders!) -- why?
1138 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001139 */
anthony92c93bd2012-03-19 14:02:47 +00001140 _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 */
anthony92c93bd2012-03-19 14:02:47 +00001154 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1155 _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 {
anthony92c93bd2012-03-19 14:02:47 +00001183 (void) DeleteImageOption(_image_info,option+1);
1184 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001185 break;
1186 }
1187 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001188 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001189 if (image_option != (const char *) NULL)
1190 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001191 canonical_page=GetPageGeometry(arg1);
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);
anthony92c93bd2012-03-19 14:02:47 +00001200 (void) SetImageOption(_image_info,option+1,page);
1201 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001202 break;
1203 }
anthonyafa3dfc2012-03-03 11:31:30 +00001204 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001205 {
anthony92c93bd2012-03-19 14:02:47 +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 {
anthony92c93bd2012-03-19 14:02:47 +00001211 _image_info->pointsize=_draw_info->pointsize=
anthony72feaa62012-01-17 06:46:23 +00001212 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
anthonya3ef4ed2012-03-17 06:52:53 +00001221 * 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 {
anthony92c93bd2012-03-19 14:02:47 +00001224 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001225 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001226 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001227 MagickPreviewOptions,MagickFalse,arg1);
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 {
anthony92c93bd2012-03-19 14:02:47 +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)
anthony92c93bd2012-03-19 14:02:47 +00001240 _image_info->quality=StringToUnsignedLong(arg1);
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 {
anthony92c93bd2012-03-19 14:02:47 +00001245 /* Just a set direct in _quantize_info */
1246 _quantize_info->colorspace=UndefinedColorspace;
anthonyafbaed72011-10-26 12:05:04 +00001247 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001248 _quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001249 MagickColorspaceOptions,MagickFalse,arg1);
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 */
anthony92c93bd2012-03-19 14:02:47 +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 {
anthony92c93bd2012-03-19 14:02:47 +00001282 /* _draw_info only setting */
1283 _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 {
anthony92c93bd2012-03-19 14:02:47 +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 */
anthony92c93bd2012-03-19 14:02:47 +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 */
anthony92c93bd2012-03-19 14:02:47 +00001306 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1307 _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(
anthony24aa8822012-03-11 00:56:06 +00001313 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
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 {
anthony92c93bd2012-03-19 14:02:47 +00001319 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001320 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001321 */
anthony92c93bd2012-03-19 14:02:47 +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 {
anthony92c93bd2012-03-19 14:02:47 +00001327 _draw_info->stretch=(StretchType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001328 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");
anthony92c93bd2012-03-19 14:02:47 +00001350 (void) SetImageOption(_image_info,option+1,value);
1351 if (_draw_info->stroke_pattern != (Image *) NULL)
1352 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001353
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)
anthony92c93bd2012-03-19 14:02:47 +00001360 _draw_info->stroke_pattern=GetImageCache(_image_info,value,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001361 else
anthony92c93bd2012-03-19 14:02:47 +00001362 _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 {
anthony92c93bd2012-03-19 14:02:47 +00001367 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1368 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001369 (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 {
anthony92c93bd2012-03-19 14:02:47 +00001374 _draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
anthony72feaa62012-01-17 06:46:23 +00001375 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 {
anthony92c93bd2012-03-19 14:02:47 +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. */
anthony92c93bd2012-03-19 14:02:47 +00001390 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001391 break;
1392 }
anthonyafa3dfc2012-03-03 11:31:30 +00001393 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001394 {
anthony92c93bd2012-03-19 14:02:47 +00001395 /* FUTURE: move _image_info string to option splay-tree */
1396 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001397 break;
1398 }
anthonyafa3dfc2012-03-03 11:31:30 +00001399 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001400 {
anthony92c93bd2012-03-19 14:02:47 +00001401 _draw_info->fill_pattern=IfSetOption
1402 ?GetImageCache(_image_info,arg1,_exception)
1403 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001404 break;
1405 }
anthonyafa3dfc2012-03-03 11:31:30 +00001406 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001407 {
anthony72feaa62012-01-17 06:46:23 +00001408 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony92c93bd2012-03-19 14:02:47 +00001409 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001410 break;
1411 }
anthonyafa3dfc2012-03-03 11:31:30 +00001412 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001413 {
anthony92c93bd2012-03-19 14:02:47 +00001414 /* FUTURE: both _image_info attribute & ImageOption in use!
1415 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001416 SyncImageSettings() used to set per-image attribute.
1417
anthonyafbaed72011-10-26 12:05:04 +00001418 Note that +transparent-color, means fall-back to image
1419 attribute so ImageOption is deleted, not set to a default.
1420 */
anthony92c93bd2012-03-19 14:02:47 +00001421 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001422 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001423 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001424 break;
1425 }
anthonyafa3dfc2012-03-03 11:31:30 +00001426 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001427 {
anthony92c93bd2012-03-19 14:02:47 +00001428 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1429 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001430 break;
1431 }
anthonyafa3dfc2012-03-03 11:31:30 +00001432 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001433 {
anthony72feaa62012-01-17 06:46:23 +00001434 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001435 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1436 _image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
anthony72feaa62012-01-17 06:46:23 +00001437 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001438 break;
1439 }
1440 break;
1441 }
1442 case 'u':
1443 {
anthonyafa3dfc2012-03-03 11:31:30 +00001444 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001445 {
anthony92c93bd2012-03-19 14:02:47 +00001446 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001447 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001448 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001449 break;
1450 }
anthonyafa3dfc2012-03-03 11:31:30 +00001451 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001452 {
anthony72feaa62012-01-17 06:46:23 +00001453 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001454 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001455 FUTURE: this probably should be part of the density setting
1456 */
anthony92c93bd2012-03-19 14:02:47 +00001457 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1458 _image_info->units=(ResolutionType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001459 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001460 break;
1461 }
1462 break;
1463 }
1464 case 'v':
1465 {
anthonyafa3dfc2012-03-03 11:31:30 +00001466 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001467 {
anthony24aa8822012-03-11 00:56:06 +00001468 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001469 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001470 */
anthony92c93bd2012-03-19 14:02:47 +00001471 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1472 _image_info->verbose= ArgBoolean;
1473 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001474 break;
1475 }
anthonyafa3dfc2012-03-03 11:31:30 +00001476 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001477 {
anthony92c93bd2012-03-19 14:02:47 +00001478 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001479 Only used by coder FPX
1480 */
anthony92c93bd2012-03-19 14:02:47 +00001481 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001482 break;
1483 }
anthonyafa3dfc2012-03-03 11:31:30 +00001484 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001485 {
anthonyfd706f92012-01-19 04:22:02 +00001486 /* SyncImageSettings() used to set per-image attribute.
1487 This is VERY deep in the image caching structure.
1488 */
anthony92c93bd2012-03-19 14:02:47 +00001489 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001490 break;
1491 }
1492 break;
1493 }
1494 case 'w':
1495 {
anthonyafa3dfc2012-03-03 11:31:30 +00001496 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001497 {
anthony72feaa62012-01-17 06:46:23 +00001498 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001499 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001500 */
anthony72feaa62012-01-17 06:46:23 +00001501 if (!IfSetOption)
1502 break;
anthony92c93bd2012-03-19 14:02:47 +00001503 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001504 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001505 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001506 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001507 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001508 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001509 if (_draw_info->weight <= 800)
1510 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001511 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001512 if (_draw_info->weight >= 100)
1513 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001514 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001515 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001516 break;
1517 }
anthonyafa3dfc2012-03-03 11:31:30 +00001518 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001519 {
anthony72feaa62012-01-17 06:46:23 +00001520 /* Used as a image chromaticity setting
1521 SyncImageSettings() used to set per-image attribute.
1522 */
anthony92c93bd2012-03-19 14:02:47 +00001523 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001524 break;
1525 }
1526 break;
1527 }
1528 default:
1529 break;
1530 }
anthony24aa8822012-03-11 00:56:06 +00001531
anthony92c93bd2012-03-19 14:02:47 +00001532#undef _image_info
1533#undef _exception
1534#undef _draw_info
1535#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001536#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001537#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001538#undef ArgBooleanNot
1539#undef ArgBooleanString
1540#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001541
anthony31f1bf72012-01-30 12:37:22 +00001542 return;
anthony805a2d42011-09-25 08:25:12 +00001543}
1544
1545/*
1546%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1547% %
1548% %
1549% %
anthony43f425d2012-02-26 12:58:58 +00001550+ 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 +00001551% %
1552% %
1553% %
1554%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1555%
anthony31f1bf72012-01-30 12:37:22 +00001556% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001557% the images in the CLI wand, with the settings that was previously saved in
1558% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001559%
1560% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001561% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001562%
anthonyd1447672012-01-19 05:33:53 +00001563% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001564%
anthony43f425d2012-02-26 12:58:58 +00001565% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001566% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001567%
1568% A description of each parameter follows:
1569%
anthony43f425d2012-02-26 12:58:58 +00001570% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001571%
anthonyfd706f92012-01-19 04:22:02 +00001572% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001573%
anthonyfd706f92012-01-19 04:22:02 +00001574% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001575%
anthony31f1bf72012-01-30 12:37:22 +00001576% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001577%
anthony31f1bf72012-01-30 12:37:22 +00001578% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001579%
anthonyafa3dfc2012-03-03 11:31:30 +00001580% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1581% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1582% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001583%
anthony24aa8822012-03-11 00:56:06 +00001584% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +00001585%
anthony43f425d2012-02-26 12:58:58 +00001586% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001587% argc,argv
1588% i=index in argv
1589%
anthony2052d272012-02-28 12:48:29 +00001590% option_info = GetCommandOptionInfo(argv[i]);
1591% count=option_info->type;
1592% option_type=option_info->flags;
1593%
1594% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001595% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001596% count>=1 ? argv[i+1] : (char *)NULL,
1597% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001598% i += count+1;
1599%
anthony805a2d42011-09-25 08:25:12 +00001600*/
anthony31f1bf72012-01-30 12:37:22 +00001601
1602/*
1603 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001604 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001605
1606 The image in the list may be modified in three different ways...
1607 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1608 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1609 * one image replace by a list of images (-separate and -crop only!)
1610
anthonyafa3dfc2012-03-03 11:31:30 +00001611 In each case the result replaces the single original image in the list, as
1612 well as the pointer to the modified image (last image added if replaced by a
1613 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001614
1615 As the image pointed to may be replaced, the first image in the list may
1616 also change. GetFirstImageInList() should be used by caller if they wish
1617 return the Image pointer to the first image in list.
1618*/
anthony43f425d2012-02-26 12:58:58 +00001619static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001620 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001621{
1622 Image *
1623 new_image;
1624
anthony805a2d42011-09-25 08:25:12 +00001625 GeometryInfo
1626 geometry_info;
1627
1628 RectangleInfo
1629 geometry;
1630
1631 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001632 flags;
1633
anthony92c93bd2012-03-19 14:02:47 +00001634 ssize_t
1635 type;
1636
1637#define _image_info (cli_wand->wand.image_info)
1638#define _image (cli_wand->wand.images)
1639#define _exception (cli_wand->wand.exception)
1640#define _draw_info (cli_wand->draw_info)
1641#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001642#define IfNormalOp (*option=='-')
1643#define IfPlusOp (*option!='-')
1644#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
1645#define plus_alt_op (IfNormalOp?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001646
anthony43f425d2012-02-26 12:58:58 +00001647 assert(cli_wand != (MagickCLI *) NULL);
1648 assert(cli_wand->signature == WandSignature);
1649 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00001650 assert(_image != (Image *) NULL); /* an _image must be present */
anthony43f425d2012-02-26 12:58:58 +00001651 if (cli_wand->wand.debug != MagickFalse)
1652 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001653
anthony92c93bd2012-03-19 14:02:47 +00001654 (void) SyncImageSettings(_image_info,_image,_exception);
anthony24aa8822012-03-11 00:56:06 +00001655
anthony805a2d42011-09-25 08:25:12 +00001656 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001657
anthony92c93bd2012-03-19 14:02:47 +00001658 new_image = (Image *)NULL; /* the replacement _image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001659
anthonyfd706f92012-01-19 04:22:02 +00001660 /* FUTURE: We may need somthing a little more optimized than this!
1661 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1662 */
anthonyafa3dfc2012-03-03 11:31:30 +00001663 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001664 {
1665 case 'a':
1666 {
anthonyafa3dfc2012-03-03 11:31:30 +00001667 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001668 {
anthony92c93bd2012-03-19 14:02:47 +00001669 if (IsGeometry(arg1) == MagickFalse)
1670 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001671 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001672 if ((flags & SigmaValue) == 0)
1673 geometry_info.sigma=1.0;
1674 if ((flags & XiValue) == 0)
1675 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001676 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1677 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001678 break;
1679 }
anthonyafa3dfc2012-03-03 11:31:30 +00001680 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001681 {
anthony92c93bd2012-03-19 14:02:47 +00001682 if (IsGeometry(arg1) == MagickFalse)
1683 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1684 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1685 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1686 _exception);
anthony805a2d42011-09-25 08:25:12 +00001687 break;
1688 }
anthonyafa3dfc2012-03-03 11:31:30 +00001689 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001690 {
anthony92c93bd2012-03-19 14:02:47 +00001691 if (IsGeometry(arg1) == MagickFalse)
1692 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001693 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001694 if ((flags & SigmaValue) == 0)
1695 geometry_info.sigma=1.0;
1696 if ((flags & XiValue) == 0)
1697 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001698 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1699 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001700 break;
1701 }
anthonyafa3dfc2012-03-03 11:31:30 +00001702 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001703 {
anthony92c93bd2012-03-19 14:02:47 +00001704 type=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1705 if (type < 0)
1706 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1707 option,arg1);
1708 (void) SetImageAlphaChannel(_image,(AlphaChannelType)type,_exception);
anthony805a2d42011-09-25 08:25:12 +00001709 break;
1710 }
anthonyafa3dfc2012-03-03 11:31:30 +00001711 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001712 {
1713 char
1714 *text,
1715 geometry[MaxTextExtent];
1716
anthony92c93bd2012-03-19 14:02:47 +00001717 if (IsGeometry(arg1) == MagickFalse)
1718 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001719 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001720 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001721 if ((flags & SigmaValue) == 0)
1722 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001723 text=InterpretImageProperties(_image_info,_image,arg2,
1724 _exception);
anthony805a2d42011-09-25 08:25:12 +00001725 if (text == (char *) NULL)
1726 break;
anthony92c93bd2012-03-19 14:02:47 +00001727 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001728 text=DestroyString(text);
1729 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1730 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001731 (void) CloneString(&_draw_info->geometry,geometry);
1732 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001733 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001734 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001735 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001736 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001737 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001738 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001739 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001740 (void) AnnotateImage(_image,_draw_info,_exception);
1741 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001742 break;
1743 }
anthonyafa3dfc2012-03-03 11:31:30 +00001744 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001745 {
anthony92c93bd2012-03-19 14:02:47 +00001746 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001747 break;
1748 }
anthonyafa3dfc2012-03-03 11:31:30 +00001749 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001750 {
anthony92c93bd2012-03-19 14:02:47 +00001751 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001752 break;
1753 }
anthonyafa3dfc2012-03-03 11:31:30 +00001754 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001755 {
anthonyafa3dfc2012-03-03 11:31:30 +00001756 /* This should probbaly be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001757 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001758 {
1759 case TopRightOrientation:
1760 {
anthony92c93bd2012-03-19 14:02:47 +00001761 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001762 break;
1763 }
1764 case BottomRightOrientation:
1765 {
anthony92c93bd2012-03-19 14:02:47 +00001766 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001767 break;
1768 }
1769 case BottomLeftOrientation:
1770 {
anthony92c93bd2012-03-19 14:02:47 +00001771 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001772 break;
1773 }
1774 case LeftTopOrientation:
1775 {
anthony92c93bd2012-03-19 14:02:47 +00001776 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001777 break;
1778 }
1779 case RightTopOrientation:
1780 {
anthony92c93bd2012-03-19 14:02:47 +00001781 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001782 break;
1783 }
1784 case RightBottomOrientation:
1785 {
anthony92c93bd2012-03-19 14:02:47 +00001786 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001787 break;
1788 }
1789 case LeftBottomOrientation:
1790 {
anthony92c93bd2012-03-19 14:02:47 +00001791 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001792 break;
1793 }
1794 default:
1795 break;
1796 }
1797 if (new_image != (Image *) NULL)
1798 new_image->orientation=TopLeftOrientation;
1799 break;
1800 }
1801 break;
1802 }
1803 case 'b':
1804 {
anthonyafa3dfc2012-03-03 11:31:30 +00001805 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001806 {
anthony92c93bd2012-03-19 14:02:47 +00001807 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001808 break;
1809 }
anthonyafa3dfc2012-03-03 11:31:30 +00001810 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001811 {
anthony805a2d42011-09-25 08:25:12 +00001812 geometry_info.rho=1.5;
anthonyafa3dfc2012-03-03 11:31:30 +00001813 if (IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00001814 flags=ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00001815 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001816 break;
1817 }
anthonyafa3dfc2012-03-03 11:31:30 +00001818 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001819 {
anthony74b1cfc2011-10-06 12:44:16 +00001820 /* FUTURE: use of "bias" in a blur is non-sensible */
anthonyfd706f92012-01-19 04:22:02 +00001821 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001822 if ((flags & SigmaValue) == 0)
1823 geometry_info.sigma=1.0;
1824 if ((flags & XiValue) == 0)
1825 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001826 new_image=BlurImage(_image,geometry_info.rho,
1827 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001828 break;
1829 }
anthonyafa3dfc2012-03-03 11:31:30 +00001830 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001831 {
anthony31f1bf72012-01-30 12:37:22 +00001832 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001833 compose;
1834
1835 const char*
anthony5f867ae2011-10-09 10:28:34 +00001836 value;
1837
anthony92c93bd2012-03-19 14:02:47 +00001838 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001839 if (value != (const char *) NULL)
1840 compose=(CompositeOperator) ParseCommandOption(
1841 MagickComposeOptions,MagickFalse,value);
1842 else
anthony92c93bd2012-03-19 14:02:47 +00001843 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001844
anthony92c93bd2012-03-19 14:02:47 +00001845 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001846 if ((flags & SigmaValue) == 0)
1847 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00001848 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001849 break;
1850 }
anthonyafa3dfc2012-03-03 11:31:30 +00001851 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001852 {
1853 double
1854 brightness,
1855 contrast;
1856
1857 GeometryInfo
1858 geometry_info;
1859
1860 MagickStatusType
1861 flags;
1862
anthonyfd706f92012-01-19 04:22:02 +00001863 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001864 brightness=geometry_info.rho;
1865 contrast=0.0;
1866 if ((flags & SigmaValue) != 0)
1867 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001868 (void) BrightnessContrastImage(_image,brightness,contrast,
1869 _exception);
anthony805a2d42011-09-25 08:25:12 +00001870 break;
1871 }
1872 break;
1873 }
1874 case 'c':
1875 {
anthonyafa3dfc2012-03-03 11:31:30 +00001876 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001877 {
1878 char
1879 *color_correction_collection;
1880
1881 /*
1882 Color correct with a color decision list.
1883 */
anthony92c93bd2012-03-19 14:02:47 +00001884 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001885 if (color_correction_collection == (char *) NULL)
1886 break;
anthony92c93bd2012-03-19 14:02:47 +00001887 (void) ColorDecisionListImage(_image,color_correction_collection,
1888 _exception);
anthony805a2d42011-09-25 08:25:12 +00001889 break;
1890 }
anthonyafa3dfc2012-03-03 11:31:30 +00001891 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001892 {
anthonyfd706f92012-01-19 04:22:02 +00001893 /* The "channel" setting has already been set
anthony24aa8822012-03-11 00:56:06 +00001894 FUTURE: This probably should be part of SyncImageSettings().
anthonyfd706f92012-01-19 04:22:02 +00001895 */
anthony92c93bd2012-03-19 14:02:47 +00001896 SetPixelChannelMapMask(_image,_image_info->channel);
anthony805a2d42011-09-25 08:25:12 +00001897 break;
1898 }
anthonyafa3dfc2012-03-03 11:31:30 +00001899 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001900 {
anthonyfd706f92012-01-19 04:22:02 +00001901 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001902 if ((flags & SigmaValue) == 0)
1903 geometry_info.sigma=1.0;
1904 if ((flags & XiValue) == 0)
1905 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001906 new_image=CharcoalImage(_image,geometry_info.rho,
1907 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001908 break;
1909 }
anthonyafa3dfc2012-03-03 11:31:30 +00001910 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001911 {
anthony92c93bd2012-03-19 14:02:47 +00001912 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1913 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001914 break;
1915 }
anthonyafa3dfc2012-03-03 11:31:30 +00001916 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001917 {
anthony92c93bd2012-03-19 14:02:47 +00001918 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001919 break;
1920 }
anthonyafa3dfc2012-03-03 11:31:30 +00001921 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001922 {
anthonyafa3dfc2012-03-03 11:31:30 +00001923 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001924 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001925 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001926 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001927 break;
1928 }
anthonyafa3dfc2012-03-03 11:31:30 +00001929 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001930 {
1931 CacheView
1932 *mask_view;
1933
1934 Image
1935 *mask_image;
1936
1937 register Quantum
1938 *restrict q;
1939
1940 register ssize_t
1941 x;
1942
1943 ssize_t
1944 y;
1945
anthonyafa3dfc2012-03-03 11:31:30 +00001946 if (IfPlusOp) {
1947 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001948 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00001949 break;
1950 }
anthony92c93bd2012-03-19 14:02:47 +00001951 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001952 if (mask_image == (Image *) NULL)
1953 break;
anthony92c93bd2012-03-19 14:02:47 +00001954 if (SetImageStorageClass(mask_image,DirectClass,_exception)
anthonyfd706f92012-01-19 04:22:02 +00001955 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001956 break;
anthony92c93bd2012-03-19 14:02:47 +00001957 /* Create a write mask from cli_wandp-mask _image */
anthonyfd706f92012-01-19 04:22:02 +00001958 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00001959 mask_view=AcquireCacheView(mask_image);
1960 for (y=0; y < (ssize_t) mask_image->rows; y++)
1961 {
1962 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00001963 _exception);
anthony805a2d42011-09-25 08:25:12 +00001964 if (q == (Quantum *) NULL)
1965 break;
1966 for (x=0; x < (ssize_t) mask_image->columns; x++)
1967 {
1968 if (mask_image->matte == MagickFalse)
1969 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1970 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1971 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1972 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1973 q+=GetPixelChannels(mask_image);
1974 }
anthony92c93bd2012-03-19 14:02:47 +00001975 if (SyncCacheViewAuthenticPixels(mask_view,_exception) == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00001976 break;
1977 }
anthonyfd706f92012-01-19 04:22:02 +00001978 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001979 mask_view=DestroyCacheView(mask_view);
1980 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00001981 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001982 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00001983 break;
1984 }
anthonyafa3dfc2012-03-03 11:31:30 +00001985 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001986 {
anthony92c93bd2012-03-19 14:02:47 +00001987 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00001988 break;
1989 }
anthonyafa3dfc2012-03-03 11:31:30 +00001990 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001991 {
anthony92c93bd2012-03-19 14:02:47 +00001992 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00001993 break;
1994 }
anthonyafa3dfc2012-03-03 11:31:30 +00001995 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001996 {
1997 KernelInfo
1998 *kernel;
1999
anthonyfd706f92012-01-19 04:22:02 +00002000 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002001 if (kernel == (KernelInfo *) NULL)
2002 break;
anthony92c93bd2012-03-19 14:02:47 +00002003 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002004 kernel=DestroyKernelInfo(kernel);
2005 break;
2006 }
anthonyafa3dfc2012-03-03 11:31:30 +00002007 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002008 {
anthony92c93bd2012-03-19 14:02:47 +00002009 /* Reduce the number of colors in the _image.
2010 FUTURE: also provide 'plus version with _image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002011 */
anthony92c93bd2012-03-19 14:02:47 +00002012 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2013 if (_quantize_info->number_colors == 0)
anthony805a2d42011-09-25 08:25:12 +00002014 break;
anthony92c93bd2012-03-19 14:02:47 +00002015 if ((_image->storage_class == DirectClass) ||
2016 _image->colors > _quantize_info->number_colors)
2017 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002018 else
anthony92c93bd2012-03-19 14:02:47 +00002019 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002020 break;
2021 }
anthonyafa3dfc2012-03-03 11:31:30 +00002022 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002023 {
anthony92c93bd2012-03-19 14:02:47 +00002024 /* WARNING: this is both a _image_info setting (already done)
2025 and a operator to change _image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002026
2027 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002028 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002029
anthonyd2cdc862011-10-07 14:07:17 +00002030 Note that +colorspace sets "undefined" or no effect on
2031 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002032 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002033 */
anthony92c93bd2012-03-19 14:02:47 +00002034 (void) TransformImageColorspace(_image,
2035 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2036 _exception);
anthony805a2d42011-09-25 08:25:12 +00002037 break;
2038 }
anthonyafa3dfc2012-03-03 11:31:30 +00002039 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002040 {
anthony92c93bd2012-03-19 14:02:47 +00002041 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002042 break;
2043 }
anthonyafa3dfc2012-03-03 11:31:30 +00002044 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002045 {
2046 double
2047 black_point,
2048 white_point;
2049
2050 MagickStatusType
2051 flags;
2052
anthonyfd706f92012-01-19 04:22:02 +00002053 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002054 black_point=geometry_info.rho;
2055 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2056 black_point;
2057 if ((flags & PercentValue) != 0)
2058 {
anthony92c93bd2012-03-19 14:02:47 +00002059 black_point*=(double) _image->columns*_image->rows/100.0;
2060 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002061 }
anthony92c93bd2012-03-19 14:02:47 +00002062 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002063 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002064 (void) ContrastStretchImage(_image,black_point,white_point,
2065 _exception);
anthony805a2d42011-09-25 08:25:12 +00002066 break;
2067 }
anthonyafa3dfc2012-03-03 11:31:30 +00002068 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002069 {
2070 KernelInfo
2071 *kernel_info;
2072
anthonyfd706f92012-01-19 04:22:02 +00002073 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002074 if (kernel_info == (KernelInfo *) NULL)
2075 break;
anthony92c93bd2012-03-19 14:02:47 +00002076 kernel_info->bias=_image->bias;
2077 new_image=ConvolveImage(_image,kernel_info,_exception);
anthony805a2d42011-09-25 08:25:12 +00002078 kernel_info=DestroyKernelInfo(kernel_info);
2079 break;
2080 }
anthonyafa3dfc2012-03-03 11:31:30 +00002081 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002082 {
anthony31f1bf72012-01-30 12:37:22 +00002083 /* WARNING: This can generate multiple images! */
anthony92c93bd2012-03-19 14:02:47 +00002084 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002085 break;
2086 }
anthonyafa3dfc2012-03-03 11:31:30 +00002087 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002088 {
anthony92c93bd2012-03-19 14:02:47 +00002089 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2090 _exception);
anthony805a2d42011-09-25 08:25:12 +00002091 break;
2092 }
2093 break;
2094 }
2095 case 'd':
2096 {
anthonyafa3dfc2012-03-03 11:31:30 +00002097 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002098 {
2099 StringInfo
2100 *passkey;
2101
anthony92c93bd2012-03-19 14:02:47 +00002102 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002103 if (passkey != (StringInfo *) NULL)
2104 {
anthony92c93bd2012-03-19 14:02:47 +00002105 (void) PasskeyDecipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002106 passkey=DestroyStringInfo(passkey);
2107 }
2108 break;
2109 }
anthonyafa3dfc2012-03-03 11:31:30 +00002110 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002111 {
anthony92c93bd2012-03-19 14:02:47 +00002112 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002113 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002114
anthonydcf510d2011-10-30 13:51:40 +00002115 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2116 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002117
anthonyfd706f92012-01-19 04:22:02 +00002118 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002119 */
anthony92c93bd2012-03-19 14:02:47 +00002120 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002121 break;
2122 }
anthonyafa3dfc2012-03-03 11:31:30 +00002123 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002124 {
2125 double
2126 threshold;
2127
anthonyafa3dfc2012-03-03 11:31:30 +00002128 if (IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00002129 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyafa3dfc2012-03-03 11:31:30 +00002130 else
2131 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002132 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002133 break;
2134 }
anthonyafa3dfc2012-03-03 11:31:30 +00002135 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002136 {
anthony92c93bd2012-03-19 14:02:47 +00002137 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002138 break;
2139 }
anthonyafa3dfc2012-03-03 11:31:30 +00002140 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002141 {
2142 char
2143 *args,
2144 token[MaxTextExtent];
2145
2146 const char
2147 *p;
2148
2149 DistortImageMethod
2150 method;
2151
2152 double
2153 *arguments;
2154
2155 register ssize_t
2156 x;
2157
2158 size_t
2159 number_arguments;
2160
anthony805a2d42011-09-25 08:25:12 +00002161 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
anthonyfd706f92012-01-19 04:22:02 +00002162 MagickFalse,arg1);
anthony80c37752012-01-16 01:03:11 +00002163 if (method == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002164 {
anthony80c37752012-01-16 01:03:11 +00002165 double
2166 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002167 /* Special Case - Argument is actually a resize geometry!
2168 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002169 ** FUTURE: make a separate special resize operator
anthony805a2d42011-09-25 08:25:12 +00002170 */
anthony92c93bd2012-03-19 14:02:47 +00002171 (void) ParseRegionGeometry(_image,arg2,&geometry,
2172 _exception);
anthony80c37752012-01-16 01:03:11 +00002173 resize_args[0]=(double) geometry.width;
2174 resize_args[1]=(double) geometry.height;
anthony92c93bd2012-03-19 14:02:47 +00002175 new_image=DistortImage(_image,method,(size_t)2,
2176 resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002177 break;
2178 }
anthonyfd706f92012-01-19 04:22:02 +00002179 /* handle percent arguments */
anthony92c93bd2012-03-19 14:02:47 +00002180 args=InterpretImageProperties(_image_info,_image,arg2,
2181 _exception);
anthony805a2d42011-09-25 08:25:12 +00002182 if (args == (char *) NULL)
2183 break;
anthonyfd706f92012-01-19 04:22:02 +00002184 /* convert arguments into an array of doubles
2185 FUTURE: make this a separate function.
2186 Also make use of new 'sentinal' feature to avoid need for
2187 tokenization.
2188 */
anthony805a2d42011-09-25 08:25:12 +00002189 p=(char *) args;
2190 for (x=0; *p != '\0'; x++)
2191 {
2192 GetMagickToken(p,&p,token);
2193 if (*token == ',')
2194 GetMagickToken(p,&p,token);
2195 }
2196 number_arguments=(size_t) x;
2197 arguments=(double *) AcquireQuantumMemory(number_arguments,
2198 sizeof(*arguments));
2199 if (arguments == (double *) NULL)
2200 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002201 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002202 (void) ResetMagickMemory(arguments,0,number_arguments*
2203 sizeof(*arguments));
2204 p=(char *) args;
2205 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2206 {
2207 GetMagickToken(p,&p,token);
2208 if (*token == ',')
2209 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002210 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002211 }
2212 args=DestroyString(args);
anthony92c93bd2012-03-19 14:02:47 +00002213 new_image=DistortImage(_image,method,number_arguments,arguments,
2214 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002215 arguments=(double *) RelinquishMagickMemory(arguments);
2216 break;
2217 }
anthonyafa3dfc2012-03-03 11:31:30 +00002218 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002219 {
anthony92c93bd2012-03-19 14:02:47 +00002220 (void) CloneString(&_draw_info->primitive,arg1);
2221 (void) DrawImage(_image,_draw_info,_exception);
2222 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002223 break;
2224 }
2225 break;
2226 }
2227 case 'e':
2228 {
anthonyafa3dfc2012-03-03 11:31:30 +00002229 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002230 {
anthonyfd706f92012-01-19 04:22:02 +00002231 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002232 if ((flags & SigmaValue) == 0)
2233 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002234 new_image=EdgeImage(_image,geometry_info.rho,
2235 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002236 break;
2237 }
anthonyafa3dfc2012-03-03 11:31:30 +00002238 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002239 {
anthonyfd706f92012-01-19 04:22:02 +00002240 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002241 if ((flags & SigmaValue) == 0)
2242 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002243 new_image=EmbossImage(_image,geometry_info.rho,
2244 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002245 break;
2246 }
anthonyafa3dfc2012-03-03 11:31:30 +00002247 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002248 {
2249 StringInfo
2250 *passkey;
2251
anthony92c93bd2012-03-19 14:02:47 +00002252 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002253 if (passkey != (StringInfo *) NULL)
2254 {
anthony92c93bd2012-03-19 14:02:47 +00002255 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002256 passkey=DestroyStringInfo(passkey);
2257 }
2258 break;
2259 }
anthonyafa3dfc2012-03-03 11:31:30 +00002260 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002261 {
anthony92c93bd2012-03-19 14:02:47 +00002262 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002263 break;
2264 }
anthonyafa3dfc2012-03-03 11:31:30 +00002265 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002266 {
anthony92c93bd2012-03-19 14:02:47 +00002267 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002268 break;
2269 }
anthonyafa3dfc2012-03-03 11:31:30 +00002270 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002271 {
2272 double
2273 constant;
2274
2275 MagickEvaluateOperator
2276 op;
2277
anthony805a2d42011-09-25 08:25:12 +00002278 op=(MagickEvaluateOperator) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00002279 MagickEvaluateOptions,MagickFalse,arg1);
2280 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00002281 (void) EvaluateImage(_image,op,constant,_exception);
anthony805a2d42011-09-25 08:25:12 +00002282 break;
2283 }
anthonyafa3dfc2012-03-03 11:31:30 +00002284 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002285 {
anthony92c93bd2012-03-19 14:02:47 +00002286 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002287 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002288 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002289 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002290 geometry.height=_image->rows;
2291 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002292 break;
2293 }
2294 break;
2295 }
2296 case 'f':
2297 {
anthonyafa3dfc2012-03-03 11:31:30 +00002298 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002299 {
anthony31f1bf72012-01-30 12:37:22 +00002300 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002301 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002302 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002303 break;
2304 }
anthony92c93bd2012-03-19 14:02:47 +00002305 (void) SetImageArtifact(_image,"identify:features","true");
2306 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002307 break;
2308 }
anthonyafa3dfc2012-03-03 11:31:30 +00002309 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002310 {
anthony92c93bd2012-03-19 14:02:47 +00002311 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002312 break;
2313 }
anthonyafa3dfc2012-03-03 11:31:30 +00002314 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002315 {
anthony92c93bd2012-03-19 14:02:47 +00002316 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002317 break;
2318 }
anthonyafa3dfc2012-03-03 11:31:30 +00002319 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002320 {
2321 PixelInfo
2322 target;
2323
anthony92c93bd2012-03-19 14:02:47 +00002324 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2325 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2326 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2327 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002328 break;
2329 }
anthonyafa3dfc2012-03-03 11:31:30 +00002330 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002331 {
2332 FrameInfo
2333 frame_info;
2334
anthony31f1bf72012-01-30 12:37:22 +00002335 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002336 compose;
2337
2338 const char*
2339 value;
2340
anthony92c93bd2012-03-19 14:02:47 +00002341 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002342 if (value != (const char *) NULL)
2343 compose=(CompositeOperator) ParseCommandOption(
2344 MagickComposeOptions,MagickFalse,value);
2345 else
anthony92c93bd2012-03-19 14:02:47 +00002346 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002347
anthony92c93bd2012-03-19 14:02:47 +00002348 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002349 frame_info.width=geometry.width;
2350 frame_info.height=geometry.height;
2351 if ((flags & HeightValue) == 0)
2352 frame_info.height=geometry.width;
2353 frame_info.outer_bevel=geometry.x;
2354 frame_info.inner_bevel=geometry.y;
2355 frame_info.x=(ssize_t) frame_info.width;
2356 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002357 frame_info.width=_image->columns+2*frame_info.width;
2358 frame_info.height=_image->rows+2*frame_info.height;
2359 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002360 break;
2361 }
anthonyafa3dfc2012-03-03 11:31:30 +00002362 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002363 {
2364 char
2365 *arguments,
2366 token[MaxTextExtent];
2367
2368 const char
2369 *p;
2370
2371 double
2372 *parameters;
2373
2374 MagickFunction
2375 function;
2376
2377 register ssize_t
2378 x;
2379
2380 size_t
2381 number_parameters;
2382
cristy947cb4c2011-10-20 18:41:46 +00002383 /*
2384 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002385 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002386 */
anthony805a2d42011-09-25 08:25:12 +00002387 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
anthonyfd706f92012-01-19 04:22:02 +00002388 MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002389 arguments=InterpretImageProperties(_image_info,_image,arg2,
2390 _exception);
anthony805a2d42011-09-25 08:25:12 +00002391 if (arguments == (char *) NULL)
2392 break;
2393 p=(char *) arguments;
2394 for (x=0; *p != '\0'; x++)
2395 {
2396 GetMagickToken(p,&p,token);
2397 if (*token == ',')
2398 GetMagickToken(p,&p,token);
2399 }
2400 number_parameters=(size_t) x;
2401 parameters=(double *) AcquireQuantumMemory(number_parameters,
2402 sizeof(*parameters));
2403 if (parameters == (double *) NULL)
2404 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002405 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002406 (void) ResetMagickMemory(parameters,0,number_parameters*
2407 sizeof(*parameters));
2408 p=(char *) arguments;
2409 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2410 {
2411 GetMagickToken(p,&p,token);
2412 if (*token == ',')
2413 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002414 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002415 }
2416 arguments=DestroyString(arguments);
anthony92c93bd2012-03-19 14:02:47 +00002417 (void) FunctionImage(_image,function,number_parameters,parameters,
2418 _exception);
anthony805a2d42011-09-25 08:25:12 +00002419 parameters=(double *) RelinquishMagickMemory(parameters);
2420 break;
2421 }
2422 break;
2423 }
2424 case 'g':
2425 {
anthonyafa3dfc2012-03-03 11:31:30 +00002426 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002427 {
anthonyafa3dfc2012-03-03 11:31:30 +00002428 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002429 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2430 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002431 else
anthony92c93bd2012-03-19 14:02:47 +00002432 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002433 break;
2434 }
anthonyafa3dfc2012-03-03 11:31:30 +00002435 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2436 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002437 {
anthonyfd706f92012-01-19 04:22:02 +00002438 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002439 if ((flags & SigmaValue) == 0)
2440 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002441 new_image=GaussianBlurImage(_image,geometry_info.rho,
2442 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002443 break;
2444 }
anthonyafa3dfc2012-03-03 11:31:30 +00002445 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002446 {
anthonyfd706f92012-01-19 04:22:02 +00002447 /*
anthony31f1bf72012-01-30 12:37:22 +00002448 Record Image offset for composition. (A Setting)
anthony92c93bd2012-03-19 14:02:47 +00002449 Resize last _image. (ListOperator)
anthony31f1bf72012-01-30 12:37:22 +00002450 FUTURE: Why if no 'offset' does this resize ALL images?
2451 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002452 */
anthonyafa3dfc2012-03-03 11:31:30 +00002453 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002454 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002455 if (_image->geometry != (char *) NULL)
2456 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002457 break;
2458 }
anthony92c93bd2012-03-19 14:02:47 +00002459 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002460 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002461 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002462 else
anthony92c93bd2012-03-19 14:02:47 +00002463 new_image=ResizeImage(_image,geometry.width,geometry.height,
2464 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00002465 break;
2466 }
anthony805a2d42011-09-25 08:25:12 +00002467 break;
2468 }
2469 case 'h':
2470 {
anthonyafa3dfc2012-03-03 11:31:30 +00002471 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002472 {
anthony92c93bd2012-03-19 14:02:47 +00002473 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002474 break;
2475 }
2476 break;
2477 }
2478 case 'i':
2479 {
anthonyafa3dfc2012-03-03 11:31:30 +00002480 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002481 {
anthony31f1bf72012-01-30 12:37:22 +00002482 const char
2483 *format,
anthony805a2d42011-09-25 08:25:12 +00002484 *text;
2485
anthony92c93bd2012-03-19 14:02:47 +00002486 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002487 if (format == (char *) NULL)
2488 {
anthony92c93bd2012-03-19 14:02:47 +00002489 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2490 _exception);
anthony805a2d42011-09-25 08:25:12 +00002491 break;
2492 }
anthony92c93bd2012-03-19 14:02:47 +00002493 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002494 if (text == (char *) NULL)
2495 break;
2496 (void) fputs(text,stdout);
2497 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002498 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002499 break;
2500 }
anthonyafa3dfc2012-03-03 11:31:30 +00002501 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002502 {
anthonyfd706f92012-01-19 04:22:02 +00002503 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002504 new_image=ImplodeImage(_image,geometry_info.rho,
2505 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002506 break;
2507 }
anthonyafa3dfc2012-03-03 11:31:30 +00002508 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002509 {
anthony92c93bd2012-03-19 14:02:47 +00002510 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2511 new_image=InterpolativeResizeImage(_image,geometry.width,
2512 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002513 break;
2514 }
anthony805a2d42011-09-25 08:25:12 +00002515 break;
2516 }
2517 case 'l':
2518 {
anthonyafa3dfc2012-03-03 11:31:30 +00002519 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002520 {
anthonyfd706f92012-01-19 04:22:02 +00002521 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002522 if ((flags & PercentValue) != 0)
2523 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002524 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002525 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002526 _exception);
anthony805a2d42011-09-25 08:25:12 +00002527 break;
2528 }
anthonyafa3dfc2012-03-03 11:31:30 +00002529 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002530 {
2531 MagickRealType
2532 black_point,
2533 gamma,
2534 white_point;
2535
2536 MagickStatusType
2537 flags;
2538
anthonyfd706f92012-01-19 04:22:02 +00002539 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002540 black_point=geometry_info.rho;
2541 white_point=(MagickRealType) QuantumRange;
2542 if ((flags & SigmaValue) != 0)
2543 white_point=geometry_info.sigma;
2544 gamma=1.0;
2545 if ((flags & XiValue) != 0)
2546 gamma=geometry_info.xi;
2547 if ((flags & PercentValue) != 0)
2548 {
2549 black_point*=(MagickRealType) (QuantumRange/100.0);
2550 white_point*=(MagickRealType) (QuantumRange/100.0);
2551 }
2552 if ((flags & SigmaValue) == 0)
2553 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002554 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002555 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002556 else
anthony92c93bd2012-03-19 14:02:47 +00002557 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002558 break;
2559 }
anthonyafa3dfc2012-03-03 11:31:30 +00002560 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002561 {
2562 char
2563 token[MaxTextExtent];
2564
2565 const char
2566 *p;
2567
2568 PixelInfo
2569 black_point,
2570 white_point;
2571
anthonyfd706f92012-01-19 04:22:02 +00002572 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002573 GetMagickToken(p,&p,token); /* get black point color */
2574 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002575 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002576 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002577 else
cristy269c9412011-10-13 23:41:15 +00002578 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002579 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002580 if (isalpha((int) token[0]) || (token[0] == '#'))
2581 GetMagickToken(p,&p,token);
2582 if (*token == '\0')
2583 white_point=black_point; /* set everything to that color */
2584 else
2585 {
2586 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2587 GetMagickToken(p,&p,token); /* Get white point color. */
2588 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002589 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002590 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002591 else
cristy269c9412011-10-13 23:41:15 +00002592 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002593 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002594 }
anthony92c93bd2012-03-19 14:02:47 +00002595 (void) LevelImageColors(_image,&black_point,&white_point,
2596 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002597 break;
2598 }
anthonyafa3dfc2012-03-03 11:31:30 +00002599 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002600 {
2601 double
2602 black_point,
2603 white_point;
2604
2605 MagickStatusType
2606 flags;
2607
anthonyfd706f92012-01-19 04:22:02 +00002608 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002609 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002610 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002611 if ((flags & SigmaValue) != 0)
2612 white_point=geometry_info.sigma;
2613 if ((flags & PercentValue) != 0)
2614 {
anthony92c93bd2012-03-19 14:02:47 +00002615 black_point*=(double) _image->columns*_image->rows/100.0;
2616 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002617 }
2618 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002619 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002620 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002621 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002622 break;
2623 }
anthonyafa3dfc2012-03-03 11:31:30 +00002624 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002625 {
anthony92c93bd2012-03-19 14:02:47 +00002626 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002627 if ((flags & XValue) == 0)
2628 geometry.x=1;
2629 if ((flags & YValue) == 0)
2630 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002631 new_image=LiquidRescaleImage(_image,geometry.width,
2632 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002633 break;
2634 }
anthonyafa3dfc2012-03-03 11:31:30 +00002635 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002636 {
anthony92c93bd2012-03-19 14:02:47 +00002637 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002638 break;
2639 }
2640 break;
2641 }
2642 case 'm':
2643 {
anthonyafa3dfc2012-03-03 11:31:30 +00002644 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002645 {
2646 Image
2647 *remap_image;
2648
anthony31f1bf72012-01-30 12:37:22 +00002649 /* DEPRECIATED use -remap */
anthony92c93bd2012-03-19 14:02:47 +00002650 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002651 if (remap_image == (Image *) NULL)
2652 break;
anthony92c93bd2012-03-19 14:02:47 +00002653 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002654 remap_image=DestroyImage(remap_image);
2655 break;
2656 }
anthonyafa3dfc2012-03-03 11:31:30 +00002657 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002658 {
2659 Image
2660 *mask;
2661
anthonyafa3dfc2012-03-03 11:31:30 +00002662 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002663 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002664 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002665 break;
2666 }
anthony92c93bd2012-03-19 14:02:47 +00002667 /* Set the _image mask. */
2668 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002669 if (mask == (Image *) NULL)
2670 break;
anthony92c93bd2012-03-19 14:02:47 +00002671 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002672 mask=DestroyImage(mask);
2673 break;
2674 }
anthonyafa3dfc2012-03-03 11:31:30 +00002675 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002676 {
anthony31f1bf72012-01-30 12:37:22 +00002677 /* DEPRECIATED */
anthony92c93bd2012-03-19 14:02:47 +00002678 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2679 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002680 break;
2681 }
anthonya3ef4ed2012-03-17 06:52:53 +00002682 if (LocaleCompare("median",option+1) == 0)
2683 {
2684 /* DEPRECIATED - use -statistic Median */
2685 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2686 break;
2687 }
anthonyafa3dfc2012-03-03 11:31:30 +00002688 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002689 {
anthonyfd706f92012-01-19 04:22:02 +00002690 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002691 if ((flags & SigmaValue) == 0)
2692 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002693 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2694 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002695 break;
2696 }
anthonyafa3dfc2012-03-03 11:31:30 +00002697 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002698 {
anthony92c93bd2012-03-19 14:02:47 +00002699 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002700 break;
2701 }
anthonyafa3dfc2012-03-03 11:31:30 +00002702 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002703 {
anthony92c93bd2012-03-19 14:02:47 +00002704 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002705 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002706 break;
2707 }
anthonyafa3dfc2012-03-03 11:31:30 +00002708 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002709 {
anthony92c93bd2012-03-19 14:02:47 +00002710 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002711 break;
2712 }
anthonyafa3dfc2012-03-03 11:31:30 +00002713 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002714 {
2715 char
2716 token[MaxTextExtent];
2717
2718 const char
2719 *p;
2720
2721 KernelInfo
2722 *kernel;
2723
2724 MorphologyMethod
2725 method;
2726
2727 ssize_t
2728 iterations;
2729
anthonyfd706f92012-01-19 04:22:02 +00002730 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002731 GetMagickToken(p,&p,token);
2732 method=(MorphologyMethod) ParseCommandOption(
2733 MagickMorphologyOptions,MagickFalse,token);
2734 iterations=1L;
2735 GetMagickToken(p,&p,token);
2736 if ((*p == ':') || (*p == ','))
2737 GetMagickToken(p,&p,token);
2738 if ((*p != '\0'))
2739 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002740 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002741 if (kernel == (KernelInfo *) NULL)
2742 {
anthony92c93bd2012-03-19 14:02:47 +00002743 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00002744 OptionError,"UnabletoParseKernel","morphology");
anthony805a2d42011-09-25 08:25:12 +00002745 break;
2746 }
anthony92c93bd2012-03-19 14:02:47 +00002747 new_image=MorphologyImage(_image,method,iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002748 kernel=DestroyKernelInfo(kernel);
2749 break;
2750 }
anthonyafa3dfc2012-03-03 11:31:30 +00002751 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002752 {
anthonyfd706f92012-01-19 04:22:02 +00002753 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002754 if ((flags & SigmaValue) == 0)
2755 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002756 new_image=MotionBlurImage(_image,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002757 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
anthony92c93bd2012-03-19 14:02:47 +00002758 _exception);
anthony805a2d42011-09-25 08:25:12 +00002759 break;
2760 }
2761 break;
2762 }
2763 case 'n':
2764 {
anthonyafa3dfc2012-03-03 11:31:30 +00002765 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002766 {
anthony92c93bd2012-03-19 14:02:47 +00002767 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002768 break;
2769 }
anthonyafa3dfc2012-03-03 11:31:30 +00002770 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002771 {
anthonyafa3dfc2012-03-03 11:31:30 +00002772 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002773 {
anthonyfd706f92012-01-19 04:22:02 +00002774 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002775 if ((flags & SigmaValue) == 0)
2776 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002777 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2778 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002779 }
2780 else
2781 {
2782 NoiseType
2783 noise;
2784
anthony31f1bf72012-01-30 12:37:22 +00002785 double
2786 attenuate;
2787
2788 const char*
2789 value;
2790
anthony805a2d42011-09-25 08:25:12 +00002791 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
anthony31f1bf72012-01-30 12:37:22 +00002792 MagickFalse,arg1),
2793
anthony92c93bd2012-03-19 14:02:47 +00002794 value=GetImageOption(_image_info,"attenuate");
anthony31f1bf72012-01-30 12:37:22 +00002795 if (value != (const char *) NULL)
2796 attenuate=StringToDouble(value,(char **) NULL);
2797 else
2798 attenuate=1.0;
2799
anthony92c93bd2012-03-19 14:02:47 +00002800 new_image=AddNoiseImage(_image,noise,attenuate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002801 }
2802 break;
2803 }
anthonyafa3dfc2012-03-03 11:31:30 +00002804 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002805 {
anthony92c93bd2012-03-19 14:02:47 +00002806 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002807 break;
2808 }
2809 break;
2810 }
2811 case 'o':
2812 {
anthonyafa3dfc2012-03-03 11:31:30 +00002813 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002814 {
2815 PixelInfo
2816 target;
2817
anthony92c93bd2012-03-19 14:02:47 +00002818 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2819 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2820 _exception);
anthony805a2d42011-09-25 08:25:12 +00002821 break;
2822 }
anthonyafa3dfc2012-03-03 11:31:30 +00002823 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002824 {
anthony92c93bd2012-03-19 14:02:47 +00002825 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002826 break;
2827 }
2828 break;
2829 }
2830 case 'p':
2831 {
anthonyafa3dfc2012-03-03 11:31:30 +00002832 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002833 {
anthonyfd706f92012-01-19 04:22:02 +00002834 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002835 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2836 _exception);
anthony805a2d42011-09-25 08:25:12 +00002837 break;
2838 }
anthonyafa3dfc2012-03-03 11:31:30 +00002839 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002840 {
cristye9e3d382011-12-14 01:50:13 +00002841 const char
2842 *caption;
2843
anthony805a2d42011-09-25 08:25:12 +00002844 double
2845 angle;
2846
anthonyafa3dfc2012-03-03 11:31:30 +00002847 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002848 {
2849 RandomInfo
2850 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002851
anthony31f1bf72012-01-30 12:37:22 +00002852 random_info=AcquireRandomInfo();
2853 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2854 random_info=DestroyRandomInfo(random_info);
2855 }
2856 else
anthony805a2d42011-09-25 08:25:12 +00002857 {
2858 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00002859 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002860 angle=geometry_info.rho;
2861 }
anthony92c93bd2012-03-19 14:02:47 +00002862 caption=GetImageProperty(_image,"caption",_exception);
2863 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2864 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002865 break;
2866 }
anthonyafa3dfc2012-03-03 11:31:30 +00002867 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002868 {
anthony31f1bf72012-01-30 12:37:22 +00002869 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002870 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
2871 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00002872 break;
2873 }
anthonyafa3dfc2012-03-03 11:31:30 +00002874 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002875 {
2876 PreviewType
cristy947cb4c2011-10-20 18:41:46 +00002877 preview_type;
anthony170fce92011-10-20 11:50:23 +00002878
anthony31f1bf72012-01-30 12:37:22 +00002879 /* FUTURE: should be a 'Genesis' option?
2880 Option however is also in WandSettingOptionInfo()
cristy947cb4c2011-10-20 18:41:46 +00002881 */
anthony31f1bf72012-01-30 12:37:22 +00002882 preview_type=UndefinedPreview;
anthonyafa3dfc2012-03-03 11:31:30 +00002883 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00002884 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2885 MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002886 new_image=PreviewImage(_image,preview_type,_exception);
anthony805a2d42011-09-25 08:25:12 +00002887 break;
2888 }
anthonyafa3dfc2012-03-03 11:31:30 +00002889 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002890 {
2891 const char
2892 *name;
2893
2894 const StringInfo
2895 *profile;
2896
2897 Image
2898 *profile_image;
2899
2900 ImageInfo
2901 *profile_info;
2902
anthonyafa3dfc2012-03-03 11:31:30 +00002903 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00002904 { /* Remove a profile from the _image. */
2905 (void) ProfileImage(_image,arg1,(const unsigned char *)
2906 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002907 break;
2908 }
anthony92c93bd2012-03-19 14:02:47 +00002909 /* Associate a profile with the _image. */
2910 profile_info=CloneImageInfo(_image_info);
2911 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002912 if (profile != (StringInfo *) NULL)
2913 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00002914 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002915 profile_info=DestroyImageInfo(profile_info);
2916 if (profile_image == (Image *) NULL)
2917 {
2918 StringInfo
2919 *profile;
2920
anthony92c93bd2012-03-19 14:02:47 +00002921 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00002922 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002923 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00002924 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002925 if (profile != (StringInfo *) NULL)
2926 {
anthony92c93bd2012-03-19 14:02:47 +00002927 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002928 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00002929 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002930 profile=DestroyStringInfo(profile);
2931 }
2932 profile_info=DestroyImageInfo(profile_info);
2933 break;
2934 }
2935 ResetImageProfileIterator(profile_image);
2936 name=GetNextImageProfile(profile_image);
2937 while (name != (const char *) NULL)
2938 {
2939 profile=GetImageProfile(profile_image,name);
2940 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00002941 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2942 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002943 name=GetNextImageProfile(profile_image);
2944 }
2945 profile_image=DestroyImage(profile_image);
2946 break;
2947 }
2948 break;
2949 }
anthony805a2d42011-09-25 08:25:12 +00002950 case 'r':
2951 {
anthonyafa3dfc2012-03-03 11:31:30 +00002952 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002953 {
anthonyfd706f92012-01-19 04:22:02 +00002954 flags=ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002955 new_image=RadialBlurImage(_image,geometry_info.rho,
2956 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002957 break;
2958 }
anthonyafa3dfc2012-03-03 11:31:30 +00002959 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002960 {
anthony92c93bd2012-03-19 14:02:47 +00002961 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002962 if ((flags & SigmaValue) == 0)
2963 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00002964 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002965 break;
2966 }
anthonyafa3dfc2012-03-03 11:31:30 +00002967 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002968 {
anthony92c93bd2012-03-19 14:02:47 +00002969 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002970 break;
2971 }
anthonyafa3dfc2012-03-03 11:31:30 +00002972 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002973 {
2974 Image
2975 *remap_image;
2976
anthony92c93bd2012-03-19 14:02:47 +00002977 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002978 if (remap_image == (Image *) NULL)
2979 break;
anthony92c93bd2012-03-19 14:02:47 +00002980 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002981 remap_image=DestroyImage(remap_image);
2982 break;
2983 }
anthonyafa3dfc2012-03-03 11:31:30 +00002984 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002985 {
anthonyafa3dfc2012-03-03 11:31:30 +00002986 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002987 (void) ResetImagePage(_image,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002988 else
anthony92c93bd2012-03-19 14:02:47 +00002989 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00002990 break;
2991 }
anthonyafa3dfc2012-03-03 11:31:30 +00002992 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002993 {
anthony31f1bf72012-01-30 12:37:22 +00002994 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00002995 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002996 if ((flags & SigmaValue) == 0)
2997 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002998 new_image=ResampleImage(_image,geometry_info.rho,
2999 geometry_info.sigma,_image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003000 break;
3001 }
anthonyafa3dfc2012-03-03 11:31:30 +00003002 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003003 {
anthonyafbaed72011-10-26 12:05:04 +00003004 /* FUTURE: remove blur argument - no longer used */
anthony92c93bd2012-03-19 14:02:47 +00003005 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3006 new_image=ResizeImage(_image,geometry.width,geometry.height,
3007 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003008 break;
3009 }
anthonyafa3dfc2012-03-03 11:31:30 +00003010 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003011 {
anthony92c93bd2012-03-19 14:02:47 +00003012 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3013 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003014 break;
3015 }
anthonyafa3dfc2012-03-03 11:31:30 +00003016 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003017 {
anthonyfd706f92012-01-19 04:22:02 +00003018 if (strchr(arg1,'>') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003019 if (_image->columns <= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003020 break;
anthonyfd706f92012-01-19 04:22:02 +00003021 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003022 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003023 break;
anthonyafbaed72011-10-26 12:05:04 +00003024
anthonyfd706f92012-01-19 04:22:02 +00003025 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003026 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003027 break;
3028 }
3029 break;
3030 }
3031 case 's':
3032 {
anthonyafa3dfc2012-03-03 11:31:30 +00003033 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003034 {
anthony92c93bd2012-03-19 14:02:47 +00003035 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3036 new_image=SampleImage(_image,geometry.width,geometry.height,
3037 _exception);
anthony805a2d42011-09-25 08:25:12 +00003038 break;
3039 }
anthonyafa3dfc2012-03-03 11:31:30 +00003040 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003041 {
anthony92c93bd2012-03-19 14:02:47 +00003042 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3043 new_image=ScaleImage(_image,geometry.width,geometry.height,
3044 _exception);
anthony805a2d42011-09-25 08:25:12 +00003045 break;
3046 }
anthonyafa3dfc2012-03-03 11:31:30 +00003047 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003048 {
anthonyfd706f92012-01-19 04:22:02 +00003049 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003050 if ((flags & PercentValue) != 0)
3051 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003052 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3053 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003054 break;
3055 }
anthonyafa3dfc2012-03-03 11:31:30 +00003056 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003057 {
anthony31f1bf72012-01-30 12:37:22 +00003058 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003059 /* FUTURE - this may be replaced by a "-channel" method */
anthony92c93bd2012-03-19 14:02:47 +00003060 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003061 break;
3062 }
anthonyafa3dfc2012-03-03 11:31:30 +00003063 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003064 {
3065 double
3066 threshold;
3067
anthonyfd706f92012-01-19 04:22:02 +00003068 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003069 new_image=SepiaToneImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003070 break;
3071 }
anthonyafa3dfc2012-03-03 11:31:30 +00003072 if (LocaleCompare("segment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003073 {
anthonyfd706f92012-01-19 04:22:02 +00003074 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003075 if ((flags & SigmaValue) == 0)
3076 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003077 (void) SegmentImage(_image,_image->colorspace,
3078 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3079 _exception);
anthony805a2d42011-09-25 08:25:12 +00003080 break;
3081 }
anthonyafa3dfc2012-03-03 11:31:30 +00003082 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003083 {
3084 char
3085 *value;
3086
anthonyafa3dfc2012-03-03 11:31:30 +00003087 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00003088 {
anthonyfd706f92012-01-19 04:22:02 +00003089 if (LocaleNCompare(arg1,"registry:",9) == 0)
3090 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003091 else
anthony31f1bf72012-01-30 12:37:22 +00003092 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003093 {
anthony92c93bd2012-03-19 14:02:47 +00003094 (void) DeleteImageOption(_image_info,arg1+7);
3095 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003096 }
3097 else
anthony92c93bd2012-03-19 14:02:47 +00003098 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003099 break;
3100 }
anthony92c93bd2012-03-19 14:02:47 +00003101 value=InterpretImageProperties(_image_info,_image,arg2,
3102 _exception);
anthony805a2d42011-09-25 08:25:12 +00003103 if (value == (char *) NULL)
3104 break;
anthonyfd706f92012-01-19 04:22:02 +00003105 if (LocaleNCompare(arg1,"registry:",9) == 0)
3106 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony92c93bd2012-03-19 14:02:47 +00003107 _exception);
anthony805a2d42011-09-25 08:25:12 +00003108 else
anthonyfd706f92012-01-19 04:22:02 +00003109 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003110 {
anthony92c93bd2012-03-19 14:02:47 +00003111 (void) SetImageOption(_image_info,arg1+7,value);
3112 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003113 }
3114 else
anthony92c93bd2012-03-19 14:02:47 +00003115 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003116 value=DestroyString(value);
3117 break;
3118 }
anthonyafa3dfc2012-03-03 11:31:30 +00003119 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003120 {
anthonyfd706f92012-01-19 04:22:02 +00003121 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003122 if ((flags & SigmaValue) == 0)
3123 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003124 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3125 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003126 break;
3127 }
anthonyafa3dfc2012-03-03 11:31:30 +00003128 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003129 {
anthonyfd706f92012-01-19 04:22:02 +00003130 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003131 if ((flags & SigmaValue) == 0)
3132 geometry_info.sigma=1.0;
3133 if ((flags & XiValue) == 0)
3134 geometry_info.xi=4.0;
3135 if ((flags & PsiValue) == 0)
3136 geometry_info.psi=4.0;
anthony92c93bd2012-03-19 14:02:47 +00003137 new_image=ShadowImage(_image,geometry_info.rho,
3138 geometry_info.sigma,_image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003139 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
anthony92c93bd2012-03-19 14:02:47 +00003140 _exception);
anthony805a2d42011-09-25 08:25:12 +00003141 break;
3142 }
anthonyafa3dfc2012-03-03 11:31:30 +00003143 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003144 {
anthonyfd706f92012-01-19 04:22:02 +00003145 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003146 if ((flags & SigmaValue) == 0)
3147 geometry_info.sigma=1.0;
3148 if ((flags & XiValue) == 0)
3149 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00003150 new_image=SharpenImage(_image,geometry_info.rho,
3151 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003152 break;
3153 }
anthonyafa3dfc2012-03-03 11:31:30 +00003154 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003155 {
anthony92c93bd2012-03-19 14:02:47 +00003156 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3157 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003158 break;
3159 }
anthonyafa3dfc2012-03-03 11:31:30 +00003160 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003161 {
anthonyfd706f92012-01-19 04:22:02 +00003162 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003163 if ((flags & SigmaValue) == 0)
3164 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003165 new_image=ShearImage(_image,geometry_info.rho,
3166 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003167 break;
3168 }
anthonyafa3dfc2012-03-03 11:31:30 +00003169 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003170 {
anthonyfd706f92012-01-19 04:22:02 +00003171 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003172 if ((flags & SigmaValue) == 0)
3173 geometry_info.sigma=(double) QuantumRange/2.0;
3174 if ((flags & PercentValue) != 0)
3175 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3176 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003177 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003178 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003179 _exception);
anthony805a2d42011-09-25 08:25:12 +00003180 break;
3181 }
anthonyafa3dfc2012-03-03 11:31:30 +00003182 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003183 {
anthonyfd706f92012-01-19 04:22:02 +00003184 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003185 if ((flags & SigmaValue) == 0)
3186 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003187 new_image=SketchImage(_image,geometry_info.rho,
3188 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003189 break;
3190 }
anthonyafa3dfc2012-03-03 11:31:30 +00003191 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003192 {
anthony92c93bd2012-03-19 14:02:47 +00003193 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3194 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003195 break;
3196 }
anthonyafa3dfc2012-03-03 11:31:30 +00003197 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003198 {
3199 SparseColorMethod
3200 method;
3201
3202 char
3203 *arguments;
3204
anthony805a2d42011-09-25 08:25:12 +00003205 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003206 MagickSparseColorOptions,MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003207 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003208 if (arguments == (char *) NULL)
3209 break;
anthony92c93bd2012-03-19 14:02:47 +00003210 new_image=SparseColorOption(_image,method,arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003211 arguments=DestroyString(arguments);
3212 break;
3213 }
anthonyafa3dfc2012-03-03 11:31:30 +00003214 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003215 {
anthony92c93bd2012-03-19 14:02:47 +00003216 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3217 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003218 break;
3219 }
anthonyafa3dfc2012-03-03 11:31:30 +00003220 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003221 {
anthonyfd706f92012-01-19 04:22:02 +00003222 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003223 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3224 _exception);
anthony805a2d42011-09-25 08:25:12 +00003225 break;
3226 }
anthonyafa3dfc2012-03-03 11:31:30 +00003227 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003228 {
3229 StatisticType
3230 type;
3231
anthony805a2d42011-09-25 08:25:12 +00003232 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
anthonyfd706f92012-01-19 04:22:02 +00003233 MagickFalse,arg1);
3234 (void) ParseGeometry(arg2,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003235 new_image=StatisticImage(_image,type,(size_t) geometry_info.rho,
3236 (size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003237 break;
3238 }
anthonyafa3dfc2012-03-03 11:31:30 +00003239 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003240 {
anthony92c93bd2012-03-19 14:02:47 +00003241 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003242 break;
3243 }
anthonyafa3dfc2012-03-03 11:31:30 +00003244 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003245 {
anthonyfd706f92012-01-19 04:22:02 +00003246 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003247 new_image=SwirlImage(_image,geometry_info.rho,
3248 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003249 break;
3250 }
3251 break;
3252 }
3253 case 't':
3254 {
anthonyafa3dfc2012-03-03 11:31:30 +00003255 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003256 {
3257 double
3258 threshold;
3259
anthonyafa3dfc2012-03-03 11:31:30 +00003260 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003261 threshold=(double) QuantumRange/2;
3262 else
anthonyfd706f92012-01-19 04:22:02 +00003263 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003264 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003265 break;
3266 }
anthonyafa3dfc2012-03-03 11:31:30 +00003267 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003268 {
anthony92c93bd2012-03-19 14:02:47 +00003269 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3270 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3271 _exception);
anthony805a2d42011-09-25 08:25:12 +00003272 break;
3273 }
anthonyafa3dfc2012-03-03 11:31:30 +00003274 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003275 {
anthony92c93bd2012-03-19 14:02:47 +00003276 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003277 break;
3278 }
anthonyafa3dfc2012-03-03 11:31:30 +00003279 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003280 {
anthonya3ef4ed2012-03-17 06:52:53 +00003281 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony92c93bd2012-03-19 14:02:47 +00003282 new_image=AffineTransformImage(_image,&_draw_info->affine,
3283 _exception);
anthony805a2d42011-09-25 08:25:12 +00003284 break;
3285 }
anthonyafa3dfc2012-03-03 11:31:30 +00003286 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003287 {
3288 PixelInfo
3289 target;
3290
anthony92c93bd2012-03-19 14:02:47 +00003291 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3292 (void) TransparentPaintImage(_image,&target,(Quantum)
3293 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003294 break;
3295 }
anthonyafa3dfc2012-03-03 11:31:30 +00003296 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003297 {
anthony92c93bd2012-03-19 14:02:47 +00003298 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003299 break;
3300 }
anthonyafa3dfc2012-03-03 11:31:30 +00003301 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003302 {
anthony92c93bd2012-03-19 14:02:47 +00003303 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003304 break;
3305 }
anthonyafa3dfc2012-03-03 11:31:30 +00003306 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003307 {
anthony92c93bd2012-03-19 14:02:47 +00003308 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003309 break;
3310 }
anthonyafa3dfc2012-03-03 11:31:30 +00003311 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003312 {
anthonyab3a50c2011-10-27 11:48:57 +00003313 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003314 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003315 break;
3316 }
3317 break;
3318 }
3319 case 'u':
3320 {
anthonyafa3dfc2012-03-03 11:31:30 +00003321 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003322 {
anthony31f1bf72012-01-30 12:37:22 +00003323 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthony24aa8822012-03-11 00:56:06 +00003324 /* FUTURE: This option is not documented!!!!! */
anthonyafa3dfc2012-03-03 11:31:30 +00003325 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003326 {
anthony92c93bd2012-03-19 14:02:47 +00003327 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003328 break;
3329 }
anthony92c93bd2012-03-19 14:02:47 +00003330 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3331 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003332 break;
3333 }
anthonyafa3dfc2012-03-03 11:31:30 +00003334 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003335 {
anthony92c93bd2012-03-19 14:02:47 +00003336 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003337 break;
3338 }
anthonyafa3dfc2012-03-03 11:31:30 +00003339 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003340 {
anthonyfd706f92012-01-19 04:22:02 +00003341 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003342 if ((flags & SigmaValue) == 0)
3343 geometry_info.sigma=1.0;
3344 if ((flags & XiValue) == 0)
3345 geometry_info.xi=1.0;
3346 if ((flags & PsiValue) == 0)
3347 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003348 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3349 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003350 break;
3351 }
3352 break;
3353 }
3354 case 'v':
3355 {
anthonyafa3dfc2012-03-03 11:31:30 +00003356 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003357 {
anthonyafa3dfc2012-03-03 11:31:30 +00003358 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003359 three places! ImageArtifact ImageOption _image_info->verbose
anthonyafa3dfc2012-03-03 11:31:30 +00003360 Some how new images also get this artifact presumably here
anthony31f1bf72012-01-30 12:37:22 +00003361 */
anthony92c93bd2012-03-19 14:02:47 +00003362 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003363 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003364 break;
3365 }
anthonyafa3dfc2012-03-03 11:31:30 +00003366 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003367 {
anthonyfd706f92012-01-19 04:22:02 +00003368 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003369 if ((flags & SigmaValue) == 0)
3370 geometry_info.sigma=1.0;
3371 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003372 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003373 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003374 geometry_info.psi=0.1*_image->rows;
3375 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3376 _image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3377 (ssize_t) ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003378 break;
3379 }
anthony805a2d42011-09-25 08:25:12 +00003380 break;
3381 }
3382 case 'w':
3383 {
anthonyafa3dfc2012-03-03 11:31:30 +00003384 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003385 {
anthonyfd706f92012-01-19 04:22:02 +00003386 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003387 if ((flags & SigmaValue) == 0)
3388 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003389 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3390 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003391 break;
3392 }
anthonyafa3dfc2012-03-03 11:31:30 +00003393 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003394 {
anthony92c93bd2012-03-19 14:02:47 +00003395 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003396 break;
3397 }
3398 break;
3399 }
3400 default:
3401 break;
3402 }
3403 /*
3404 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003405 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003406 */
3407 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003408 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003409
anthony31f1bf72012-01-30 12:37:22 +00003410 return;
anthony92c93bd2012-03-19 14:02:47 +00003411#undef _image_info
3412#undef _draw_info
3413#undef _quantize_info
3414#undef _image
3415#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003416#undef IfNormalOp
3417#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003418#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003419#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003420}
anthonyfd706f92012-01-19 04:22:02 +00003421
anthony43f425d2012-02-26 12:58:58 +00003422WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003423 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003424{
3425 size_t
anthony43f425d2012-02-26 12:58:58 +00003426 n,
anthony31f1bf72012-01-30 12:37:22 +00003427 i;
3428
anthony43f425d2012-02-26 12:58:58 +00003429 assert(cli_wand != (MagickCLI *) NULL);
3430 assert(cli_wand->signature == WandSignature);
3431 assert(cli_wand->wand.signature == WandSignature);
3432 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3433 if (cli_wand->wand.debug != MagickFalse)
3434 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003435
anthonyafa3dfc2012-03-03 11:31:30 +00003436#if !USE_WAND_METHODS
3437 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003438 i=0;
anthony43f425d2012-02-26 12:58:58 +00003439 n=GetImageListLength(cli_wand->wand.images);
3440 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003441 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003442 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003443 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003444 if ( cli_wand->wand.images->next == (Image *) NULL )
3445 break;
3446 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003447 }
anthony43f425d2012-02-26 12:58:58 +00003448 assert( i == n );
3449 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003450#else
3451 MagickResetIterator(&cli_wand->wand);
3452 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3453 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3454 MagickResetIterator(&cli_wand->wand);
3455#endif
anthony31f1bf72012-01-30 12:37:22 +00003456 return;
anthony805a2d42011-09-25 08:25:12 +00003457}
3458
3459/*
3460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3461% %
3462% %
3463% %
anthony43f425d2012-02-26 12:58:58 +00003464+ 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 +00003465% %
3466% %
3467% %
3468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3469%
anthony43f425d2012-02-26 12:58:58 +00003470% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003471% entire image list as a whole. The result is often a complete replacment
3472% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003473%
3474% The format of the MogrifyImage method is:
3475%
anthony43f425d2012-02-26 12:58:58 +00003476% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003477% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003478%
3479% A description of each parameter follows:
3480%
anthony43f425d2012-02-26 12:58:58 +00003481% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003482%
anthony36a8c2c2012-02-10 00:08:44 +00003483% o option: The option string for the operation
3484%
anthony31f1bf72012-01-30 12:37:22 +00003485% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003486%
anthony8b10b462012-02-08 12:32:44 +00003487% NOTE: only "limit" currently uses two arguments.
3488%
3489% Example usage...
3490%
anthonyafa3dfc2012-03-03 11:31:30 +00003491% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3492% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003493%
anthony24aa8822012-03-11 00:56:06 +00003494% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003495%
anthony43f425d2012-02-26 12:58:58 +00003496% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003497% argc,argv
3498% i=index in argv
3499%
anthony2052d272012-02-28 12:48:29 +00003500% option_info = GetCommandOptionInfo(argv[i]);
3501% count=option_info->type;
3502% option_type=option_info->flags;
3503%
3504% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003505% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003506% count>=1 ? argv[i+1] : (char *)NULL,
3507% count>=2 ? argv[i+2] : (char *)NULL );
3508% i += count+1;
3509%
anthony805a2d42011-09-25 08:25:12 +00003510*/
anthony43f425d2012-02-26 12:58:58 +00003511WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003512 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003513{
anthony31f1bf72012-01-30 12:37:22 +00003514 Image
3515 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003516
anthony92c93bd2012-03-19 14:02:47 +00003517#define _image_info (cli_wand->wand.image_info)
3518#define _images (cli_wand->wand.images)
3519#define _exception (cli_wand->wand.exception)
3520#define _draw_info (cli_wand->draw_info)
3521#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003522#define IfNormalOp (*option=='-')
3523#define IfPlusOp (*option!='-')
3524#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003525
anthony43f425d2012-02-26 12:58:58 +00003526 assert(cli_wand != (MagickCLI *) NULL);
3527 assert(cli_wand->signature == WandSignature);
3528 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003529 assert(_images != (Image *) NULL); /* _images must be present */
anthony43f425d2012-02-26 12:58:58 +00003530 if (cli_wand->wand.debug != MagickFalse)
3531 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003532
anthony92c93bd2012-03-19 14:02:47 +00003533 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003534
3535 new_images=NewImageList();
3536
anthonyafa3dfc2012-03-03 11:31:30 +00003537 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003538 {
3539 case 'a':
3540 {
anthonyafa3dfc2012-03-03 11:31:30 +00003541 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003542 {
anthony92c93bd2012-03-19 14:02:47 +00003543 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003544 break;
3545 }
anthonyafa3dfc2012-03-03 11:31:30 +00003546 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003547 {
anthony31f1bf72012-01-30 12:37:22 +00003548 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003549 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003550 break;
3551 }
3552 break;
3553 }
3554 case 'c':
3555 {
cristy5f257b22012-03-07 00:27:29 +00003556 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003557 {
anthony92c93bd2012-03-19 14:02:47 +00003558 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003559 break;
3560 }
anthonyafa3dfc2012-03-03 11:31:30 +00003561 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003562 {
anthony805a2d42011-09-25 08:25:12 +00003563 Image
anthony31f1bf72012-01-30 12:37:22 +00003564 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003565
anthonyafa3dfc2012-03-03 11:31:30 +00003566 /* FUTURE - make this a compose option, and thus can be used
3567 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003568 _images.
cristy87c02f42012-02-24 00:19:10 +00003569 */
anthony92c93bd2012-03-19 14:02:47 +00003570 new_images=RemoveFirstImageFromList(&_images);
3571 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003572 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003573 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003574 break;
anthony92c93bd2012-03-19 14:02:47 +00003575 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003576 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003577 break;
3578 }
anthonyafa3dfc2012-03-03 11:31:30 +00003579 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003580 {
anthony92c93bd2012-03-19 14:02:47 +00003581 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003582 break;
3583 }
anthonyafa3dfc2012-03-03 11:31:30 +00003584 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003585 {
anthony43f425d2012-02-26 12:58:58 +00003586 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003587 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003588 break;
3589 }
anthonyafa3dfc2012-03-03 11:31:30 +00003590 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003591 {
3592 Image
3593 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003594 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003595
3596 RectangleInfo
3597 geometry;
3598
anthony31f1bf72012-01-30 12:37:22 +00003599 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003600 compose;
3601
3602 const char*
3603 value;
3604
anthony92c93bd2012-03-19 14:02:47 +00003605 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00003606 if (value != (const char *) NULL)
3607 compose=(CompositeOperator) ParseCommandOption(
3608 MagickComposeOptions,MagickFalse,value);
3609 else
anthony31f1bf72012-01-30 12:37:22 +00003610 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003611
anthony92c93bd2012-03-19 14:02:47 +00003612 new_images=RemoveFirstImageFromList(&_images);
3613 source_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003614 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003615 if (source_image == (Image *) NULL)
3616 break;
anthonye8f56492012-02-12 12:39:02 +00003617
anthony31f1bf72012-01-30 12:37:22 +00003618 /* FUTURE - this should not be here! - should be part of -geometry */
3619 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003620 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003621
anthony31f1bf72012-01-30 12:37:22 +00003622 SetGeometry(source_image,&geometry);
3623 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3624 GravityAdjustGeometry(new_images->columns,new_images->rows,
3625 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003626
anthony92c93bd2012-03-19 14:02:47 +00003627 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003628 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003629 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003630 if ((compose == DisplaceCompositeOp) ||
3631 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003632 { /* Merge Y displacement into X displace/distort map. */
3633 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony92c93bd2012-03-19 14:02:47 +00003634 mask_image,0,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003635 mask_image=DestroyImage(mask_image);
3636 }
3637 else
3638 {
3639 /*
3640 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003641 */
anthony92c93bd2012-03-19 14:02:47 +00003642 (void) NegateImage(mask_image,MagickFalse,_exception);
3643 (void) SetImageMask(new_images,mask_image,_exception);
cristy1539afd2012-01-30 01:32:59 +00003644 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003645 }
3646 }
anthony31f1bf72012-01-30 12:37:22 +00003647 (void) CompositeImage(new_images,compose,source_image,geometry.x,
anthony92c93bd2012-03-19 14:02:47 +00003648 geometry.y,_exception);
3649 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003650 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003651 break;
3652 }
3653 break;
3654 }
3655 case 'd':
3656 {
anthonyafa3dfc2012-03-03 11:31:30 +00003657 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003658 {
anthony31f1bf72012-01-30 12:37:22 +00003659 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003660 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003661 break;
3662 }
anthonyafa3dfc2012-03-03 11:31:30 +00003663 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003664 {
anthonyafa3dfc2012-03-03 11:31:30 +00003665 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003666 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003667 else
anthony92c93bd2012-03-19 14:02:47 +00003668 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003669 break;
3670 }
anthonyafa3dfc2012-03-03 11:31:30 +00003671 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003672 {
anthonyafa3dfc2012-03-03 11:31:30 +00003673 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003674 {
3675 const char
3676 *p;
3677
3678 size_t
3679 number_duplicates;
3680
anthony31f1bf72012-01-30 12:37:22 +00003681 number_duplicates=(size_t) StringToLong(arg1);
3682 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003683 if (p == (const char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003684 new_images=DuplicateImages(_images,number_duplicates,
3685 "-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003686 else
anthony92c93bd2012-03-19 14:02:47 +00003687 new_images=DuplicateImages(_images,number_duplicates,p,
3688 _exception);
anthony805a2d42011-09-25 08:25:12 +00003689 }
anthonyafa3dfc2012-03-03 11:31:30 +00003690 else
anthony92c93bd2012-03-19 14:02:47 +00003691 new_images=DuplicateImages(_images,1,"-1",_exception);
3692 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003693 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003694 break;
3695 }
3696 break;
3697 }
3698 case 'e':
3699 {
anthonyafa3dfc2012-03-03 11:31:30 +00003700 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003701 {
anthony805a2d42011-09-25 08:25:12 +00003702 MagickEvaluateOperator
anthony31f1bf72012-01-30 12:37:22 +00003703 method;
anthony805a2d42011-09-25 08:25:12 +00003704
anthony31f1bf72012-01-30 12:37:22 +00003705 method=(MagickEvaluateOperator) ParseCommandOption(
3706 MagickEvaluateOptions,MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003707 new_images=EvaluateImages(_images,method,_exception);
anthony805a2d42011-09-25 08:25:12 +00003708 break;
3709 }
3710 break;
3711 }
3712 case 'f':
3713 {
anthonyafa3dfc2012-03-03 11:31:30 +00003714 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003715 {
anthony92c93bd2012-03-19 14:02:47 +00003716 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003717 break;
3718 }
anthonyafa3dfc2012-03-03 11:31:30 +00003719 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003720 {
anthony319dac62012-03-06 04:12:44 +00003721 /* REDIRECTED to use -layers flatten instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003722 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003723 break;
3724 }
anthonyafa3dfc2012-03-03 11:31:30 +00003725 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003726 {
anthony92c93bd2012-03-19 14:02:47 +00003727 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003728 break;
3729 }
3730 break;
3731 }
3732 case 'h':
3733 {
anthonyafa3dfc2012-03-03 11:31:30 +00003734 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003735 {
anthony31f1bf72012-01-30 12:37:22 +00003736 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003737 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003738 */
anthony805a2d42011-09-25 08:25:12 +00003739 Image
anthony31f1bf72012-01-30 12:37:22 +00003740 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003741
anthony92c93bd2012-03-19 14:02:47 +00003742 new_images=RemoveFirstImageFromList(&_images);
3743 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003744 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003745 break;
anthony92c93bd2012-03-19 14:02:47 +00003746 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003747 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003748 break;
3749 }
3750 break;
3751 }
3752 case 'i':
3753 {
anthonyafa3dfc2012-03-03 11:31:30 +00003754 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003755 {
3756 Image
anthony805a2d42011-09-25 08:25:12 +00003757 *magnitude_image,
3758 *phase_image;
3759
anthony92c93bd2012-03-19 14:02:47 +00003760 magnitude_image=RemoveFirstImageFromList(&_images);
3761 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003762 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003763 if (phase_image == (Image *) NULL)
3764 break;
3765 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003766 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003767 magnitude_image=DestroyImage(magnitude_image);
3768 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003769 break;
3770 }
anthonyafa3dfc2012-03-03 11:31:30 +00003771 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003772 {
3773 Image
anthony31f1bf72012-01-30 12:37:22 +00003774 *insert_image,
3775 *index_image;
3776
3777 ssize_t
3778 index;
anthony805a2d42011-09-25 08:25:12 +00003779
3780 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003781 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003782 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003783 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003784 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003785 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003786 PrependImageToList(&_images,insert_image);
3787 else if (index == (ssize_t) GetImageListLength(_images))
3788 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003789 else
anthony43f425d2012-02-26 12:58:58 +00003790 {
anthony92c93bd2012-03-19 14:02:47 +00003791 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003792 if (index_image == (Image *) NULL)
3793 {
anthony92c93bd2012-03-19 14:02:47 +00003794 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +00003795 OptionError,"NoSuchImage","'%s'",arg1);
3796 break;
3797 }
3798 InsertImageInList(&index_image,insert_image);
3799 }
anthony92c93bd2012-03-19 14:02:47 +00003800 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003801 break;
3802 }
anthony805a2d42011-09-25 08:25:12 +00003803 break;
3804 }
3805 case 'l':
3806 {
anthonyafa3dfc2012-03-03 11:31:30 +00003807 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003808 {
anthony805a2d42011-09-25 08:25:12 +00003809 ImageLayerMethod
3810 method;
3811
anthony805a2d42011-09-25 08:25:12 +00003812 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
anthony31f1bf72012-01-30 12:37:22 +00003813 MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00003814 switch (method)
3815 {
3816 case CoalesceLayer:
3817 {
anthony92c93bd2012-03-19 14:02:47 +00003818 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003819 break;
3820 }
3821 case CompareAnyLayer:
3822 case CompareClearLayer:
3823 case CompareOverlayLayer:
3824 default:
3825 {
anthony92c93bd2012-03-19 14:02:47 +00003826 new_images=CompareImagesLayers(_images,method,_exception);
anthony805a2d42011-09-25 08:25:12 +00003827 break;
3828 }
3829 case MergeLayer:
3830 case FlattenLayer:
3831 case MosaicLayer:
3832 case TrimBoundsLayer:
3833 {
anthony92c93bd2012-03-19 14:02:47 +00003834 new_images=MergeImageLayers(_images,method,_exception);
anthony805a2d42011-09-25 08:25:12 +00003835 break;
3836 }
3837 case DisposeLayer:
3838 {
anthony92c93bd2012-03-19 14:02:47 +00003839 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003840 break;
3841 }
3842 case OptimizeImageLayer:
3843 {
anthony92c93bd2012-03-19 14:02:47 +00003844 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003845 break;
3846 }
3847 case OptimizePlusLayer:
3848 {
anthony92c93bd2012-03-19 14:02:47 +00003849 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003850 break;
3851 }
3852 case OptimizeTransLayer:
3853 {
anthony92c93bd2012-03-19 14:02:47 +00003854 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003855 break;
3856 }
3857 case RemoveDupsLayer:
3858 {
anthony92c93bd2012-03-19 14:02:47 +00003859 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003860 break;
3861 }
3862 case RemoveZeroLayer:
3863 {
anthony92c93bd2012-03-19 14:02:47 +00003864 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003865 break;
3866 }
3867 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003868 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00003869 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003870 if (new_images == (Image *) NULL)
3871 break;
anthony92c93bd2012-03-19 14:02:47 +00003872 _images=DestroyImageList(_images);
3873 _images=OptimizeImageLayers(new_images,_exception);
3874 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003875 break;
3876 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00003877 OptimizeImageTransparency(_images,_exception);
3878 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3879 _exception);
anthony805a2d42011-09-25 08:25:12 +00003880 break;
3881 }
3882 case CompositeLayer:
3883 {
anthony805a2d42011-09-25 08:25:12 +00003884 Image
3885 *source;
3886
3887 RectangleInfo
3888 geometry;
3889
anthony31f1bf72012-01-30 12:37:22 +00003890 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003891 compose;
3892
3893 const char*
3894 value;
3895
anthony92c93bd2012-03-19 14:02:47 +00003896 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003897 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003898 if (value != (const char *) NULL)
3899 compose=(CompositeOperator) ParseCommandOption(
3900 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003901
anthony31f1bf72012-01-30 12:37:22 +00003902 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00003903 source=_images;
anthony805a2d42011-09-25 08:25:12 +00003904 while (source != (Image *) NULL)
3905 {
3906 source=GetNextImageInList(source);
3907 if ((source != (Image *) NULL) &&
3908 (LocaleCompare(source->magick,"NULL") == 0))
3909 break;
3910 }
3911 if (source != (Image *) NULL)
3912 {
3913 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3914 (GetNextImageInList(source) == (Image *) NULL))
3915 source=(Image *) NULL;
3916 else
anthony31f1bf72012-01-30 12:37:22 +00003917 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003918 source=SplitImageList(source->previous);
3919 DeleteImageFromList(&source);
3920 }
3921 }
3922 if (source == (Image *) NULL)
3923 {
anthony92c93bd2012-03-19 14:02:47 +00003924 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00003925 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003926 break;
3927 }
anthony31f1bf72012-01-30 12:37:22 +00003928 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00003929 SetGeometry(_images,&geometry);
3930 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003931 geometry.width=source->page.width != 0 ?
3932 source->page.width : source->columns;
3933 geometry.height=source->page.height != 0 ?
3934 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00003935 GravityAdjustGeometry(_images->page.width != 0 ?
3936 _images->page.width : _images->columns,
3937 _images->page.height != 0 ? _images->page.height :
3938 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003939
anthony31f1bf72012-01-30 12:37:22 +00003940 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00003941 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
3942 _exception);
anthony805a2d42011-09-25 08:25:12 +00003943 source=DestroyImageList(source);
3944 break;
3945 }
3946 }
anthony805a2d42011-09-25 08:25:12 +00003947 break;
3948 }
anthonyafa3dfc2012-03-03 11:31:30 +00003949 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00003950 {
3951 MagickSizeType
3952 limit;
3953
3954 ResourceType
3955 type;
3956
anthony72feaa62012-01-17 06:46:23 +00003957 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
anthony31f1bf72012-01-30 12:37:22 +00003958 MagickFalse,arg1);
anthony72feaa62012-01-17 06:46:23 +00003959 limit=MagickResourceInfinity;
anthony31f1bf72012-01-30 12:37:22 +00003960 if (LocaleCompare("unlimited",arg2) != 0)
3961 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthony72feaa62012-01-17 06:46:23 +00003962 (void) SetMagickResourceLimit(type,limit);
3963 break;
3964 }
anthony805a2d42011-09-25 08:25:12 +00003965 break;
3966 }
3967 case 'm':
3968 {
anthonyafa3dfc2012-03-03 11:31:30 +00003969 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003970 {
anthony31f1bf72012-01-30 12:37:22 +00003971 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00003972 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00003973 break;
3974 }
anthonyafa3dfc2012-03-03 11:31:30 +00003975 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003976 {
3977 Image
3978 *morph_image;
3979
anthony92c93bd2012-03-19 14:02:47 +00003980 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
3981 _exception);
anthony805a2d42011-09-25 08:25:12 +00003982 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003983 break;
anthony92c93bd2012-03-19 14:02:47 +00003984 _images=DestroyImageList(_images);
3985 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00003986 break;
3987 }
anthonyafa3dfc2012-03-03 11:31:30 +00003988 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003989 {
anthony319dac62012-03-06 04:12:44 +00003990 /* REDIRECTED to use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003991 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003992 break;
3993 }
3994 break;
3995 }
3996 case 'p':
3997 {
anthonyafa3dfc2012-03-03 11:31:30 +00003998 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003999 {
4000 char
4001 *string;
4002
anthony92c93bd2012-03-19 14:02:47 +00004003 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004004 if (string == (char *) NULL)
4005 break;
4006 (void) FormatLocaleFile(stdout,"%s",string);
4007 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004008 break;
anthony805a2d42011-09-25 08:25:12 +00004009 }
anthonyafa3dfc2012-03-03 11:31:30 +00004010 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004011 {
4012 char
4013 **arguments;
4014
4015 int
4016 j,
4017 number_arguments;
4018
anthony31f1bf72012-01-30 12:37:22 +00004019 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004020 if (arguments == (char **) NULL)
4021 break;
anthony31f1bf72012-01-30 12:37:22 +00004022 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004023 {
4024 char
4025 breaker,
4026 quote,
4027 *token;
4028
4029 const char
4030 *arguments;
4031
4032 int
4033 next,
4034 status;
4035
4036 size_t
4037 length;
4038
4039 TokenInfo
4040 *token_info;
4041
4042 /*
anthony24aa8822012-03-11 00:56:06 +00004043 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004044 */
anthony31f1bf72012-01-30 12:37:22 +00004045 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004046 token=(char *) NULL;
4047 if (~length >= (MaxTextExtent-1))
4048 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4049 sizeof(*token));
4050 if (token == (char *) NULL)
4051 break;
4052 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004053 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004054 token_info=AcquireTokenInfo();
4055 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4056 "\"",'\0',&breaker,&next,&quote);
4057 token_info=DestroyTokenInfo(token_info);
4058 if (status == 0)
4059 {
4060 const char
4061 *argv;
4062
4063 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004064 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4065 _exception);
anthony805a2d42011-09-25 08:25:12 +00004066 }
4067 token=DestroyString(token);
4068 break;
4069 }
4070 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004071 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4072 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004073 for (j=0; j < number_arguments; j++)
4074 arguments[j]=DestroyString(arguments[j]);
4075 arguments=(char **) RelinquishMagickMemory(arguments);
4076 break;
4077 }
4078 break;
4079 }
4080 case 'r':
4081 {
anthonyafa3dfc2012-03-03 11:31:30 +00004082 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004083 {
anthony92c93bd2012-03-19 14:02:47 +00004084 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4085 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004086 break;
4087 }
anthonyafa3dfc2012-03-03 11:31:30 +00004088 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004089 {
anthony92c93bd2012-03-19 14:02:47 +00004090 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004091 break;
4092 }
4093 break;
4094 }
4095 case 's':
4096 {
anthonyafa3dfc2012-03-03 11:31:30 +00004097 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004098 {
4099 Image
4100 *smush_image;
4101
4102 ssize_t
4103 offset;
4104
anthony31f1bf72012-01-30 12:37:22 +00004105 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004106 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004107 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004108 break;
anthony92c93bd2012-03-19 14:02:47 +00004109 _images=DestroyImageList(_images);
4110 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004111 break;
4112 }
anthonyafa3dfc2012-03-03 11:31:30 +00004113 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004114 {
4115 Image
4116 *p,
4117 *q,
4118 *swap;
4119
4120 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004121 index,
anthony805a2d42011-09-25 08:25:12 +00004122 swap_index;
4123
anthony31f1bf72012-01-30 12:37:22 +00004124 index=-1;
4125 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004126 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004127 {
4128 GeometryInfo
4129 geometry_info;
4130
4131 MagickStatusType
4132 flags;
4133
4134 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004135 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004136 index=(ssize_t) geometry_info.rho;
4137 if ((flags & SigmaValue) != 0)
4138 swap_index=(ssize_t) geometry_info.sigma;
4139 }
anthony92c93bd2012-03-19 14:02:47 +00004140 p=GetImageFromList(_images,index);
4141 q=GetImageFromList(_images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004142 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4143 {
anthony92c93bd2012-03-19 14:02:47 +00004144 (void) ThrowMagickException(_exception,GetMagickModule(),
4145 OptionError,"NoSuchImage","'%s'",_images->filename);
anthony805a2d42011-09-25 08:25:12 +00004146 break;
4147 }
4148 if (p == q)
4149 break;
anthony92c93bd2012-03-19 14:02:47 +00004150 swap=CloneImage(p,0,0,MagickTrue,_exception);
4151 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
anthony805a2d42011-09-25 08:25:12 +00004152 ReplaceImageInList(&q,swap);
anthony92c93bd2012-03-19 14:02:47 +00004153 _images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004154 break;
4155 }
4156 break;
4157 }
4158 case 'w':
4159 {
anthonyafa3dfc2012-03-03 11:31:30 +00004160 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004161 {
4162 char
4163 key[MaxTextExtent];
4164
4165 Image
4166 *write_images;
4167
4168 ImageInfo
4169 *write_info;
4170
anthony31f1bf72012-01-30 12:37:22 +00004171 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004172 (void) DeleteImageRegistry(key);
anthony92c93bd2012-03-19 14:02:47 +00004173 write_images=_images;
anthonyafa3dfc2012-03-03 11:31:30 +00004174 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00004175 write_images=CloneImageList(_images,_exception);
4176 write_info=CloneImageInfo(_image_info);
4177 (void) WriteImages(write_info,write_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004178 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004179 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004180 write_images=DestroyImageList(write_images);
4181 break;
4182 }
4183 break;
4184 }
4185 default:
4186 break;
4187 }
anthony31f1bf72012-01-30 12:37:22 +00004188 if (new_images == (Image *) NULL)
4189 return;
anthony805a2d42011-09-25 08:25:12 +00004190
anthony92c93bd2012-03-19 14:02:47 +00004191 if (_images != (Image *) NULL)
4192 _images=DestroyImageList(_images);
4193 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004194 return;
4195
anthony92c93bd2012-03-19 14:02:47 +00004196#undef _image_info
4197#undef _images
4198#undef _exception
4199#undef _draw_info
4200#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004201#undef IfNormalOp
4202#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004203#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004204}
anthony43f425d2012-02-26 12:58:58 +00004205
4206/*
4207%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4208% %
4209% %
4210% %
4211+ C L I S p e c i a l O p e r a t i o n s %
4212% %
4213% %
4214% %
4215%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4216%
4217% CLISpecialOption() Applies operations that may involve empty image lists
4218% and or stacks of image lists or image_info settings.
4219%
anthonyafa3dfc2012-03-03 11:31:30 +00004220% The classic operators of this type is -read, and image stack operators,
4221% which can be applied to empty image lists.
4222%
4223% Note: unlike other Operators, these may involve other special 'option'
4224% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004225%
4226% The format of the CLISpecialOption method is:
4227%
4228% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004229% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004230%
4231% A description of each parameter follows:
4232%
4233% o cli_wand: the main CLI Wand to use.
4234%
4235% o option: The special option (with any switch char) to process
4236%
anthony24aa8822012-03-11 00:56:06 +00004237% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004238%
anthony2052d272012-02-28 12:48:29 +00004239% Example Usage...
4240%
4241% CLISpecialOperator(cli_wand,"-read", "rose:");
anthony2052d272012-02-28 12:48:29 +00004242%
anthony24aa8822012-03-11 00:56:06 +00004243% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004244%
4245% cli_wand
4246% argc,argv
4247% i=index in argv
4248%
4249% option_info = GetCommandOptionInfo(argv[i]);
4250% count=option_info->type;
4251% option_type=option_info->flags;
4252%
4253% if ( (option_type & SpecialOptionFlag) != 0 )
4254% CLISpecialOperator(cli_wand,argv[i],
4255% count>=1 ? argv[i+1] : (char *)NULL);
4256% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004257%
4258*/
4259
anthony43f425d2012-02-26 12:58:58 +00004260WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004261 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004262{
anthony92c93bd2012-03-19 14:02:47 +00004263#define _exception (cli_wand->wand.exception)
anthony43f425d2012-02-26 12:58:58 +00004264
4265 assert(cli_wand != (MagickCLI *) NULL);
4266 assert(cli_wand->signature == WandSignature);
4267 assert(cli_wand->wand.signature == WandSignature);
4268 if (cli_wand->wand.debug != MagickFalse)
4269 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4270
anthony24aa8822012-03-11 00:56:06 +00004271 if(cli_wand->wand.images != (Image *)NULL)
4272 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
anthony92c93bd2012-03-19 14:02:47 +00004273 _exception);
anthony24aa8822012-03-11 00:56:06 +00004274
anthonyafa3dfc2012-03-03 11:31:30 +00004275 if (LocaleCompare("(",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004276 {
4277 /* stack 'push' images */
4278 Stack
4279 *node;
4280
4281 size_t
4282 size;
4283
4284 const char*
4285 value;
4286
4287 size=0;
4288 node=cli_wand->image_list_stack;
4289 for ( ; node != (Stack *)NULL; node=node->next)
4290 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004291 if ( size >= MAX_STACK_DEPTH )
anthony92c93bd2012-03-19 14:02:47 +00004292 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004293 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4294 if (node == (Stack *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004295 CLIWandExceptionReturn(ResourceLimitFatalError,
4296 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004297 node->data = (void *)cli_wand->wand.images;
4298 cli_wand->wand.images = NewImageList();
4299 node->next = cli_wand->image_list_stack;
4300 cli_wand->image_list_stack = node;
4301
4302 /* handle respect-parenthesis */
4303 value=GetImageOption(cli_wand->wand.image_info,"respect-parenthesis");
4304 if (value != (const char *) NULL)
4305 option="{";
4306 else
4307 return;
4308 }
anthonyafa3dfc2012-03-03 11:31:30 +00004309 if (LocaleCompare("{",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004310 {
4311 /* stack 'push' of image_info settings */
4312 Stack
4313 *node;
4314
4315 size_t
4316 size;
4317
4318 size=0;
4319 node=cli_wand->image_info_stack;
4320 for ( ; node != (Stack *)NULL; node=node->next)
4321 size++;
anthony92c93bd2012-03-19 14:02:47 +00004322 if ( size >= MAX_STACK_DEPTH )
4323 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004324 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthony92c93bd2012-03-19 14:02:47 +00004325 if (node == (Stack *) NULL)
4326 CLIWandExceptionReturn(ResourceLimitFatalError,
4327 "MemoryAllocationFailed",option);
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) {
anthony92c93bd2012-03-19 14:02:47 +00004332 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4333 option);
anthonyafa3dfc2012-03-03 11:31:30 +00004334 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)
anthony92c93bd2012-03-19 14:02:47 +00004355 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004356 cli_wand->image_list_stack = node->next;
4357
4358 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4359 cli_wand->wand.images= (Image *)node->data;
4360 node = (Stack *)RelinquishMagickMemory(node);
4361
4362 /* handle respect-parenthesis - of the previous 'push' settings */
4363 node = cli_wand->image_info_stack;
4364 if ( node != (Stack *)NULL)
4365 {
4366 value=GetImageOption((ImageInfo *)node->data,"respect-parenthesis");
4367 if (value != (const char *) NULL)
4368 option="}";
4369 else
4370 return;
4371 }
4372 else
4373 return;
4374 }
anthonyafa3dfc2012-03-03 11:31:30 +00004375 if (LocaleCompare("}",option) == 0)
anthony43f425d2012-02-26 12:58:58 +00004376 {
4377 /* pop image_info settings from stack */
4378 Stack
4379 *node;
4380
4381 node = (void *)cli_wand->image_info_stack;
4382 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004383 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004384 cli_wand->image_info_stack = node->next;
4385
4386 (void) DestroyImageInfo(cli_wand->wand.image_info);
4387 cli_wand->wand.image_info = (ImageInfo *)node->data;
4388 node = (Stack *)RelinquishMagickMemory(node);
4389
4390 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4391 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4392 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4393
4394 return;
4395 }
anthonyafa3dfc2012-03-03 11:31:30 +00004396 if (LocaleCompare("clone",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004397 {
4398 Image
4399 *new_images;
4400
4401 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004402 arg1="-1";
4403 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004404 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004405 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004406 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004407 new_images = (Image *)cli_wand->image_list_stack->data;
4408 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004409 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4410 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004411 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004412 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony43f425d2012-02-26 12:58:58 +00004413 AppendImageToList(&cli_wand->wand.images,new_images);
4414 return;
4415 }
anthony319dac62012-03-06 04:12:44 +00004416 if ( ( LocaleCompare("read",option+1) == 0 ) ||
4417 ( LocaleCompare("--",option) == 0 ) )
anthony43f425d2012-02-26 12:58:58 +00004418 {
anthonyafa3dfc2012-03-03 11:31:30 +00004419#if !USE_WAND_METHODS
anthony43f425d2012-02-26 12:58:58 +00004420 Image *
4421 new_images;
4422
anthony43f425d2012-02-26 12:58:58 +00004423 if (cli_wand->wand.image_info->ping != MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004424 new_images=PingImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004425 else
anthony92c93bd2012-03-19 14:02:47 +00004426 new_images=ReadImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004427 AppendImageToList(&cli_wand->wand.images, new_images);
4428#else
4429 /* read images using MagickWand method - no ping */
4430 /* This is not working! - it locks up in a CPU loop! */
4431 MagickSetLastIterator(&cli_wand->wand);
anthony24aa8822012-03-11 00:56:06 +00004432 MagickReadImage(&cli_wand->wand,arg1);
anthony43f425d2012-02-26 12:58:58 +00004433 MagickSetFirstIterator(&cli_wand->wand);
4434#endif
4435 return;
4436 }
anthonyafa3dfc2012-03-03 11:31:30 +00004437 /* No-op options */
4438 if (LocaleCompare("noop",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004439 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004440 if (LocaleCompare("sans",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004441 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004442 if (LocaleCompare("sans0",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004443 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004444 if (LocaleCompare("sans2",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004445 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004446 if (LocaleCompare("list",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004447 {
4448 /* FUTURE: This should really be built into the MagickCore
4449 It does not actually require any wand or images at all!
4450 */
4451 ssize_t
4452 list;
4453
anthony24aa8822012-03-11 00:56:06 +00004454 list=ParseCommandOption(MagickListOptions,MagickFalse, arg1);
anthony43f425d2012-02-26 12:58:58 +00004455 switch (list)
4456 {
4457 case MagickCoderOptions:
4458 {
anthony92c93bd2012-03-19 14:02:47 +00004459 (void) ListCoderInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004460 break;
4461 }
4462 case MagickColorOptions:
4463 {
anthony92c93bd2012-03-19 14:02:47 +00004464 (void) ListColorInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004465 break;
4466 }
4467 case MagickConfigureOptions:
4468 {
anthony92c93bd2012-03-19 14:02:47 +00004469 (void) ListConfigureInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004470 break;
4471 }
4472 case MagickDelegateOptions:
4473 {
anthony92c93bd2012-03-19 14:02:47 +00004474 (void) ListDelegateInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004475 break;
4476 }
4477 case MagickFontOptions:
4478 {
anthony92c93bd2012-03-19 14:02:47 +00004479 (void) ListTypeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004480 break;
4481 }
4482 case MagickFormatOptions:
anthony92c93bd2012-03-19 14:02:47 +00004483 (void) ListMagickInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004484 break;
4485 case MagickLocaleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004486 (void) ListLocaleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004487 break;
4488 case MagickLogOptions:
anthony92c93bd2012-03-19 14:02:47 +00004489 (void) ListLogInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004490 break;
4491 case MagickMagicOptions:
anthony92c93bd2012-03-19 14:02:47 +00004492 (void) ListMagicInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004493 break;
4494 case MagickMimeOptions:
anthony92c93bd2012-03-19 14:02:47 +00004495 (void) ListMimeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004496 break;
4497 case MagickModuleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004498 (void) ListModuleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004499 break;
4500 case MagickPolicyOptions:
anthony92c93bd2012-03-19 14:02:47 +00004501 (void) ListPolicyInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004502 break;
4503 case MagickResourceOptions:
anthony92c93bd2012-03-19 14:02:47 +00004504 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004505 break;
4506 case MagickThresholdOptions:
anthony92c93bd2012-03-19 14:02:47 +00004507 (void) ListThresholdMaps((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004508 break;
4509 default:
4510 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
anthony92c93bd2012-03-19 14:02:47 +00004511 _exception);
anthony43f425d2012-02-26 12:58:58 +00004512 break;
4513 }
4514 return;
4515 }
4516
4517#if 0
4518 // adjust stack handling
4519 // Other 'special' options this should handle
4520 // "region" "list" "version"
4521 // It does not do "exit" however as due to its side-effect requirements
4522#endif
4523#if 0
4524 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
4525 MagickExceptionReturn(OptionError,"InvalidUseOfOption",option);
4526#endif
4527
anthony92c93bd2012-03-19 14:02:47 +00004528#undef _exception
anthony43f425d2012-02-26 12:58:58 +00004529}