blob: 117f85a98b343349e6420375f2d03dab4f035f4d [file] [log] [blame]
anthony805a2d42011-09-25 08:25:12 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
anthony8b10b462012-02-08 12:32:44 +00006% OOO PPPP EEEE RRRR AA TTTTT III OOO N N %
7% O O P P E R R A A T I O O NN N %
8% O O PPPP EEE RRRR AAAA T I O O N N N %
9% O O P E R R A A T I O O N NN %
10% OOO P EEEE R RR A A T III OOO N N %
anthony805a2d42011-09-25 08:25:12 +000011% %
12% %
anthony8b10b462012-02-08 12:32:44 +000013% CLI Magick Option Methods %
anthony805a2d42011-09-25 08:25:12 +000014% %
anthony8b10b462012-02-08 12:32:44 +000015% Dragon Computing %
cristy9e58efd2012-01-30 14:27:34 +000016% Anthony Thyssen %
cristy0a0ca4f2011-09-28 01:15:28 +000017% September 2011 %
anthony805a2d42011-09-25 08:25:12 +000018% %
19% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
anthony805a2d42011-09-25 08:25:12 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36% Apply the given options (settings, and simple, or sequence operations) to
anthony8b10b462012-02-08 12:32:44 +000037% the given image(s) according to the current "image_info", "draw_info", and
38% "quantize_info" settings, stored in a special CLI Image Wand.
anthony805a2d42011-09-25 08:25:12 +000039%
40% The final goal is to allow the execution in a strict one option at a time
41% manner that is needed for 'pipelining and file scripting' of options in
42% IMv7.
43%
anthony8b10b462012-02-08 12:32:44 +000044% Anthony Thyssen, September 2011
anthony805a2d42011-09-25 08:25:12 +000045*/
46
47/*
48 Include declarations.
49*/
50#include "MagickWand/studio.h"
51#include "MagickWand/MagickWand.h"
anthony72feaa62012-01-17 06:46:23 +000052#include "MagickWand/magick-wand-private.h"
anthonyfd706f92012-01-19 04:22:02 +000053#include "MagickWand/operation.h"
anthony2052d272012-02-28 12:48:29 +000054#include "MagickWand/operation-private.h"
anthony43f425d2012-02-26 12:58:58 +000055#include "MagickWand/wand.h"
anthony805a2d42011-09-25 08:25:12 +000056#include "MagickCore/monitor-private.h"
57#include "MagickCore/thread-private.h"
58#include "MagickCore/string-private.h"
59
60/*
61 Define declarations.
62*/
anthonyafa3dfc2012-03-03 11:31:30 +000063#define USE_WAND_METHODS 0
64#define MAX_STACK_DEPTH 32
65#define UNDEFINED_COMPRESSION_QUALITY 0UL
66
anthony805a2d42011-09-25 08:25:12 +000067/*
68 Constant declaration. (temporary exports)
69*/
70static const char
71 BackgroundColor[] = "#fff", /* white */
anthony72feaa62012-01-17 06:46:23 +000072 BorderColor[] = "#dfdfdf", /* sRGB gray */
73 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
anthony805a2d42011-09-25 08:25:12 +000074
75/*
76** Function to report on the progress of image operations
77*/
78static MagickBooleanType MonitorProgress(const char *text,
79 const MagickOffsetType offset,const MagickSizeType extent,
anthony43f425d2012-02-26 12:58:58 +000080 void *wand_unused(cli_wandent_data))
anthony805a2d42011-09-25 08:25:12 +000081{
82 char
83 message[MaxTextExtent],
84 tag[MaxTextExtent];
85
86 const char
87 *locale_message;
88
89 register char
90 *p;
91
92 if (extent < 2)
93 return(MagickTrue);
94 (void) CopyMagickMemory(tag,text,MaxTextExtent);
95 p=strrchr(tag,'/');
96 if (p != (char *) NULL)
97 *p='\0';
98 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
99 locale_message=GetLocaleMessage(message);
100 if (locale_message == message)
101 locale_message=tag;
102 if (p == (char *) NULL)
103 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
104 locale_message,(long) offset,(unsigned long) extent,(long)
105 (100L*offset/(extent-1)));
106 else
107 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
108 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
109 (100L*offset/(extent-1)));
110 if (offset == (MagickOffsetType) (extent-1))
111 (void) FormatLocaleFile(stderr,"\n");
112 (void) fflush(stderr);
113 return(MagickTrue);
114}
115
116/*
117** GetImageCache() will read an image into a image cache if not already
118** present then return the image that is in the cache under that filename.
119*/
120static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
121 ExceptionInfo *exception)
122{
123 char
124 key[MaxTextExtent];
125
126 ExceptionInfo
127 *sans_exception;
128
129 Image
130 *image;
131
132 ImageInfo
133 *read_info;
134
135 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
136 sans_exception=AcquireExceptionInfo();
137 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
138 sans_exception=DestroyExceptionInfo(sans_exception);
139 if (image != (Image *) NULL)
140 return(image);
141 read_info=CloneImageInfo(image_info);
142 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
143 image=ReadImage(read_info,exception);
144 read_info=DestroyImageInfo(read_info);
145 if (image != (Image *) NULL)
146 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
147 return(image);
148}
149
150/*
anthonya89dd172011-10-04 13:29:35 +0000151 SparseColorOption() parse the complex -sparse-color argument into an
152 an array of floating point values than call SparseColorImage().
153 Argument is a complex mix of floating-point pixel coodinates, and color
154 specifications (or direct floating point numbers). The number of floats
155 needed to represent a color varies depending on teh current channel
156 setting.
anthony43f425d2012-02-26 12:58:58 +0000157
158 This really should be in MagickCore, so that other API's can make use of it.
anthony805a2d42011-09-25 08:25:12 +0000159*/
160static Image *SparseColorOption(const Image *image,
161 const SparseColorMethod method,const char *arguments,
anthony31f1bf72012-01-30 12:37:22 +0000162 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000163{
164 char
165 token[MaxTextExtent];
166
167 const char
168 *p;
169
170 double
171 *sparse_arguments;
172
173 Image
174 *sparse_image;
175
176 PixelInfo
177 color;
178
179 MagickBooleanType
180 error;
181
182 register size_t
183 x;
184
185 size_t
186 number_arguments,
187 number_colors;
188
189 assert(image != (Image *) NULL);
190 assert(image->signature == MagickSignature);
191 if (image->debug != MagickFalse)
192 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
193 assert(exception != (ExceptionInfo *) NULL);
194 assert(exception->signature == MagickSignature);
195 /*
196 Limit channels according to image - and add up number of color channel.
197 */
198 number_colors=0;
199 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
200 number_colors++;
201 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
202 number_colors++;
203 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
204 number_colors++;
205 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
206 (image->colorspace == CMYKColorspace))
207 number_colors++;
208 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
209 (image->matte != MagickFalse))
210 number_colors++;
211
212 /*
213 Read string, to determine number of arguments needed,
214 */
215 p=arguments;
216 x=0;
217 while( *p != '\0' )
218 {
219 GetMagickToken(p,&p,token);
220 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000221 if ( isalpha((int) token[0]) || token[0] == '#' )
222 x += number_colors; /* color argument found */
anthonyce8dcb32012-03-21 13:20:31 +0000223 else
anthony805a2d42011-09-25 08:25:12 +0000224 x++; /* floating point argument */
anthony805a2d42011-09-25 08:25:12 +0000225 }
226 error=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +0000227 /* control points and color values */
228 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
229 number_arguments=x;
anthony805a2d42011-09-25 08:25:12 +0000230 if ( error ) {
231 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000232 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000233 "Invalid number of Arguments");
234 return( (Image *)NULL);
235 }
236
237 /* Allocate and fill in the floating point arguments */
238 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
239 sizeof(*sparse_arguments));
240 if (sparse_arguments == (double *) NULL) {
241 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
242 "MemoryAllocationFailed","%s","SparseColorOption");
243 return( (Image *)NULL);
244 }
245 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
246 sizeof(*sparse_arguments));
247 p=arguments;
248 x=0;
249 while( *p != '\0' && x < number_arguments ) {
250 /* X coordinate */
251 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
252 if ( token[0] == '\0' ) break;
253 if ( isalpha((int) token[0]) || token[0] == '#' ) {
254 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000255 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000256 "Color found, instead of X-coord");
257 error = MagickTrue;
258 break;
259 }
cristydbdd0e32011-11-04 23:29:40 +0000260 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000261 /* Y coordinate */
262 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
263 if ( token[0] == '\0' ) break;
264 if ( isalpha((int) token[0]) || token[0] == '#' ) {
265 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000266 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000267 "Color found, instead of Y-coord");
268 error = MagickTrue;
269 break;
270 }
cristydbdd0e32011-11-04 23:29:40 +0000271 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000272 /* color name or function given in string argument */
273 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
274 if ( token[0] == '\0' ) break;
275 if ( isalpha((int) token[0]) || token[0] == '#' ) {
276 /* Color string given */
277 (void) QueryColorCompliance(token,AllCompliance,&color,
278 exception);
279 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
280 sparse_arguments[x++] = QuantumScale*color.red;
281 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
282 sparse_arguments[x++] = QuantumScale*color.green;
283 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
284 sparse_arguments[x++] = QuantumScale*color.blue;
285 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
286 (image->colorspace == CMYKColorspace))
287 sparse_arguments[x++] = QuantumScale*color.black;
288 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
289 (image->matte != MagickFalse))
290 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000291 }
anthony31f1bf72012-01-30 12:37:22 +0000292 else {
293 /* Colors given as a set of floating point values - experimental */
294 /* NB: token contains the first floating point value to use! */
295 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
296 {
297 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
298 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
299 break;
300 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
301 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000302 }
anthony31f1bf72012-01-30 12:37:22 +0000303 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
304 {
305 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
306 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
307 break;
308 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
309 token[0] = ','; /* used this token - get another */
310 }
311 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
312 {
313 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
314 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
315 break;
316 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
317 token[0] = ','; /* used this token - get another */
318 }
319 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
320 (image->colorspace == CMYKColorspace))
321 {
322 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
323 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
324 break;
325 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
326 token[0] = ','; /* used this token - get another */
327 }
328 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
329 (image->matte != MagickFalse))
330 {
331 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
332 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
333 break;
334 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
335 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000336 }
337 }
338 }
339 if ( number_arguments != x && !error ) {
340 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000341 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000342 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
343 return( (Image *)NULL);
344 }
345 if ( error )
346 return( (Image *)NULL);
347
anthony31f1bf72012-01-30 12:37:22 +0000348 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000349 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
350 exception);
351 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
352 return( sparse_image );
353}
354
355/*
356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357% %
358% %
359% %
anthony43f425d2012-02-26 12:58:58 +0000360+ A c q u i r e W a n d C L I %
anthony805a2d42011-09-25 08:25:12 +0000361% %
362% %
363% %
364%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365%
anthony43f425d2012-02-26 12:58:58 +0000366% AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
367% Wand). The given image_info and exception is included as is if provided.
anthony805a2d42011-09-25 08:25:12 +0000368%
anthony43f425d2012-02-26 12:58:58 +0000369% Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
370% needed.
371%
372% The format of the NewMagickWand method is:
anthonyafa3dfc2012-03-03 11:31:30 +0000373%
anthony43f425d2012-02-26 12:58:58 +0000374% MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
375% ExceptionInfo *exception)
376%
377*/
378WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
379 ExceptionInfo *exception)
380{
381 MagickCLI
382 *cli_wand;
383
384 /* precaution - as per NewMagickWand() */
385 {
386 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
387 const char *quantum = GetMagickQuantumDepth(&depth);
388 if (depth != MAGICKCORE_QUANTUM_DEPTH)
389 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
390 }
391
392 /* allocate memory for MgaickCLI */
393 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
394 if (cli_wand == (MagickCLI *) NULL)
395 {
396 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
397 GetExceptionMessage(errno));
398 return((MagickCLI *)NULL);
399 }
400
401 /* Initialize Wand Part of MagickCLI
402 FUTURE: this is a repeat of code from NewMagickWand()
403 However some parts may be given fro man external source!
404 */
405 cli_wand->wand.id=AcquireWandId();
406 (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
407 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
408 cli_wand->wand.images=NewImageList();
409 if ( image_info == (ImageInfo *)NULL)
410 cli_wand->wand.image_info=AcquireImageInfo();
411 else
412 cli_wand->wand.image_info=image_info;
413 if ( exception == (ExceptionInfo *)NULL)
414 cli_wand->wand.exception=AcquireExceptionInfo();
415 else
416 cli_wand->wand.exception=exception;
417 cli_wand->wand.debug=IsEventLogging();
418 cli_wand->wand.signature=WandSignature;
419
420 /* Initialize CLI Part of MagickCLI */
421 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
422 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
423 cli_wand->image_list_stack=(Stack *)NULL;
424 cli_wand->image_info_stack=(Stack *)NULL;
anthony5330ae02012-03-20 14:17:01 +0000425 cli_wand->location="'%s'"; /* option location not known by default */
426 cli_wand->location2="'%s' '%s'";
anthony319dac62012-03-06 04:12:44 +0000427 cli_wand->filename=cli_wand->wand.name;
anthony1cdc5b72012-03-03 02:31:18 +0000428 cli_wand->line=0;
429 cli_wand->column=0;
anthony43f425d2012-02-26 12:58:58 +0000430 cli_wand->signature=WandSignature;
431
432 if (cli_wand->wand.debug != MagickFalse)
433 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
434 return(cli_wand);
435}
436
437/*
438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439% %
440% %
441% %
442+ D e s t r o y W a n d C L I %
443% %
444% %
445% %
446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447%
448% DestroyMagickCLI() destorys everything in a CLI wand, including image_info
449% and any exceptions, if still present in the wand.
450%
451% The format of the NewMagickWand method is:
anthonyafa3dfc2012-03-03 11:31:30 +0000452%
anthony43f425d2012-02-26 12:58:58 +0000453% MagickWand *DestroyMagickCLI()
454% Exception *exception)
455%
456*/
457WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
458{
459 Stack
460 *node;
461
462 assert(cli_wand != (MagickCLI *) NULL);
463 assert(cli_wand->signature == WandSignature);
464 assert(cli_wand->wand.signature == WandSignature);
465 if (cli_wand->wand.debug != MagickFalse)
466 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
467
468 /* Destroy CLI part of MagickCLI */
469 if (cli_wand->draw_info != (DrawInfo *) NULL )
470 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
471 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
472 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
473 while(cli_wand->image_list_stack != (Stack *)NULL)
474 {
475 node=cli_wand->image_list_stack;
476 cli_wand->image_list_stack=node->next;
477 (void) DestroyImageList((Image *)node->data);
478 (void) RelinquishMagickMemory(node);
479 }
480 while(cli_wand->image_info_stack != (Stack *)NULL)
481 {
482 node=cli_wand->image_info_stack;
483 cli_wand->image_info_stack=node->next;
484 (void) DestroyImageInfo((ImageInfo *)node->data);
485 (void) RelinquishMagickMemory(node);
486 }
487 cli_wand->signature=(~WandSignature);
488
489 /* Destroy Wand part MagickCLI */
490 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
491 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
492 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
493 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
494 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
495 RelinquishWandId(cli_wand->wand.id);
496 cli_wand->wand.signature=(~WandSignature);
497
498 return((MagickCLI *)NULL);
499}
500
501/*
502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
503% %
504% %
505% %
anthony2052d272012-02-28 12:48:29 +0000506+ C L I C a t c h E x c e p t i o n %
507% %
508% %
509% %
510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511%
512% CLICatchException() will report exceptions, either just non-fatal warnings
513% only, or all errors, according to 'all_execeptions' boolean argument.
514%
515% The function returns true is errors are fatal, in which case the caller
516% should abort and re-call with an 'all_exceptions' argument of true before
517% quitting.
518%
519% The cut-off level between fatal and non-fatal may be controlled by options
520% (FUTURE), but defaults to 'Error' exceptions.
521%
522% The format of the CLICatchException method is:
523%
524% MagickBooleanType CLICatchException(MagickCLI *cli_wand,
525% const MagickBooleanType all_exceptions );
526%
527*/
528WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
529 const MagickBooleanType all_exceptions )
530{
531 MagickBooleanType
532 status;
533 assert(cli_wand != (MagickCLI *) NULL);
534 assert(cli_wand->signature == WandSignature);
535 assert(cli_wand->wand.signature == WandSignature);
536 if (cli_wand->wand.debug != MagickFalse)
537 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
538
539 // FUTURE: '-regard_warning' should make this more sensitive.
540 // Note pipelined options may like more control over this level
541
542 status = MagickFalse;
543 if (cli_wand->wand.exception->severity > ErrorException)
544 status = MagickTrue;
545
546 if ( status == MagickFalse || all_exceptions != MagickFalse )
547 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
548
549 return(status);
550}
551
552/*
553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554% %
555% %
556% %
anthony43f425d2012-02-26 12:58:58 +0000557+ C L I S e t t i n g O p t i o n I n f o %
558% %
559% %
560% %
561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562%
563% CLISettingOptionInfo() applies a single settings option into a CLI wand
564% holding the image_info, draw_info, quantize_info structures that will be
565% used when processing the images.
566%
567% These options do no require images to be present in the CLI wand for them
568% to be able to be set, in which case they will generally be applied to image
569% that are read in later
anthony80c37752012-01-16 01:03:11 +0000570%
571% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000572% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000573%
anthony2052d272012-02-28 12:48:29 +0000574% The format of the CLISettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000575%
anthonyafa3dfc2012-03-03 11:31:30 +0000576% void CLISettingOptionInfo(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +0000577% const char *option, const char *arg1)
anthony805a2d42011-09-25 08:25:12 +0000578%
579% A description of each parameter follows:
580%
anthony43f425d2012-02-26 12:58:58 +0000581% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000582%
anthonydcf510d2011-10-30 13:51:40 +0000583% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000584%
anthony24aa8822012-03-11 00:56:06 +0000585% o arg1: The single argument used to set this option.
anthonydcf510d2011-10-30 13:51:40 +0000586%
anthony72feaa62012-01-17 06:46:23 +0000587% Example usage...
588%
anthonyafa3dfc2012-03-03 11:31:30 +0000589% CLISettingOptionInfo(cli_wand, "-background", "Red"); // set value
590% CLISettingOptionInfo(cli_wand, "-adjoin", NULL); // set boolean
591% CLISettingOptionInfo(cli_wand, "+adjoin", NULL); // unset
anthony72feaa62012-01-17 06:46:23 +0000592%
anthony24aa8822012-03-11 00:56:06 +0000593% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +0000594%
595% argc,argv
596% i=index in argv
597%
anthony2052d272012-02-28 12:48:29 +0000598% option_info = GetCommandOptionInfo(argv[i]);
599% count=option_info->type;
600% option_type=option_info->flags;
601%
602% if ( (option_type & SettingOperatorOptionFlags) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +0000603% CLISettingOptionInfo(cli_wand, argv[i],
604% (count>0) ? argv[i+1] : (char *)NULL);
anthonydcf510d2011-10-30 13:51:40 +0000605% i += count+1;
606%
anthony805a2d42011-09-25 08:25:12 +0000607*/
anthonyafa3dfc2012-03-03 11:31:30 +0000608WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +0000609 const char *option,const char *arg1)
anthony805a2d42011-09-25 08:25:12 +0000610{
anthony30b912a2012-03-22 01:20:28 +0000611 ssize_t
612 parse; /* option argument parsing (string to value table lookup) */
613
anthony43f425d2012-02-26 12:58:58 +0000614 assert(cli_wand != (MagickCLI *) NULL);
615 assert(cli_wand->signature == WandSignature);
616 assert(cli_wand->wand.signature == WandSignature);
617 if (cli_wand->wand.debug != MagickFalse)
618 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony1afdc7a2011-10-05 11:54:28 +0000619
anthony92c93bd2012-03-19 14:02:47 +0000620#define _image_info (cli_wand->wand.image_info)
621#define _exception (cli_wand->wand.exception)
622#define _draw_info (cli_wand->draw_info)
623#define _quantize_info (cli_wand->quantize_info)
anthony24aa8822012-03-11 00:56:06 +0000624#define IfSetOption (*option=='-')
625#define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
626#define ArgBooleanNot (IfSetOption?MagickFalse:MagickTrue)
627#define ArgBooleanString (IfSetOption?"true":"false")
628#define ArgOption(def) (IfSetOption?arg1:(const char *)(def))
anthony74b1cfc2011-10-06 12:44:16 +0000629
anthonyafa3dfc2012-03-03 11:31:30 +0000630 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +0000631 {
632 case 'a':
633 {
anthonyafa3dfc2012-03-03 11:31:30 +0000634 if (LocaleCompare("adjoin",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000635 {
anthony92c93bd2012-03-19 14:02:47 +0000636 _image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000637 break;
638 }
anthonyafa3dfc2012-03-03 11:31:30 +0000639 if (LocaleCompare("affine",option+1) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000640 {
anthony92c93bd2012-03-19 14:02:47 +0000641 /* DEPRECIATED: _draw_info setting only: for -draw and -transform */
anthony74b1cfc2011-10-06 12:44:16 +0000642 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000643 (void) ParseAffineGeometry(arg1,&_draw_info->affine,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000644 else
anthony92c93bd2012-03-19 14:02:47 +0000645 GetAffineMatrix(&_draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000646 break;
647 }
anthonyafa3dfc2012-03-03 11:31:30 +0000648 if (LocaleCompare("antialias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000649 {
anthony92c93bd2012-03-19 14:02:47 +0000650 _image_info->antialias =
651 _draw_info->stroke_antialias =
652 _draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000653 break;
654 }
anthony31f1bf72012-01-30 12:37:22 +0000655 if (LocaleCompare("attenuate",option+1) == 0)
656 {
anthony92c93bd2012-03-19 14:02:47 +0000657 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
658 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
659 (void) SetImageOption(_image_info,option+1,ArgOption("1.0"));
anthony31f1bf72012-01-30 12:37:22 +0000660 break;
661 }
anthonyafa3dfc2012-03-03 11:31:30 +0000662 if (LocaleCompare("authenticate",option+1) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000663 {
anthony92c93bd2012-03-19 14:02:47 +0000664 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000665 break;
666 }
667 break;
668 }
669 case 'b':
670 {
anthonyafa3dfc2012-03-03 11:31:30 +0000671 if (LocaleCompare("background",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000672 {
anthony92c93bd2012-03-19 14:02:47 +0000673 /* FUTURE: both _image_info attribute & ImageOption in use!
674 _image_info only used directly for generating new images.
anthony72feaa62012-01-17 06:46:23 +0000675 SyncImageSettings() used to set per-image attribute.
676
anthony92c93bd2012-03-19 14:02:47 +0000677 FUTURE: if _image_info->background_color is not set then
anthony30b912a2012-03-22 01:20:28 +0000678 we should fall back to per-image background_color
679
680 At this time -background will 'wipe out' the per-image
681 background color!
682
683 Better error handling of QueryColorCompliance() needed.
anthony74b1cfc2011-10-06 12:44:16 +0000684 */
anthony92c93bd2012-03-19 14:02:47 +0000685 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +0000686 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000687 &_image_info->background_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000688 break;
689 }
anthonyafa3dfc2012-03-03 11:31:30 +0000690 if (LocaleCompare("bias",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000691 {
anthony74b1cfc2011-10-06 12:44:16 +0000692 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000693 as it is actually rarely used except in direct convolve operations
694 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000695
696 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000697 */
anthony5330ae02012-03-20 14:17:01 +0000698 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
699 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000700 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000701 break;
702 }
anthonyafa3dfc2012-03-03 11:31:30 +0000703 if (LocaleCompare("black-point-compensation",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000704 {
anthony72feaa62012-01-17 06:46:23 +0000705 /* Used as a image chromaticity setting
706 SyncImageSettings() used to set per-image attribute.
707 */
anthony92c93bd2012-03-19 14:02:47 +0000708 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +0000709 break;
710 }
anthonyafa3dfc2012-03-03 11:31:30 +0000711 if (LocaleCompare("blue-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000712 {
anthonyafbaed72011-10-26 12:05:04 +0000713 /* Image chromaticity X,Y NB: Y=X if Y not defined
714 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000715 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000716 */
anthony5330ae02012-03-20 14:17:01 +0000717 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
718 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +0000719 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000720 break;
721 }
anthonyafa3dfc2012-03-03 11:31:30 +0000722 if (LocaleCompare("bordercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000723 {
anthony92c93bd2012-03-19 14:02:47 +0000724 /* FUTURE: both _image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000725 SyncImageSettings() used to set per-image attribute.
anthony30b912a2012-03-22 01:20:28 +0000726 Better error checking of QueryColorCompliance().
anthony72feaa62012-01-17 06:46:23 +0000727 */
anthony74b1cfc2011-10-06 12:44:16 +0000728 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000729 {
anthony92c93bd2012-03-19 14:02:47 +0000730 (void) SetImageOption(_image_info,option+1,arg1);
anthony24aa8822012-03-11 00:56:06 +0000731 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000732 &_image_info->border_color,_exception);
anthony24aa8822012-03-11 00:56:06 +0000733 (void) QueryColorCompliance(arg1,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000734 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000735 break;
736 }
anthony92c93bd2012-03-19 14:02:47 +0000737 (void) DeleteImageOption(_image_info,option+1);
anthony74b1cfc2011-10-06 12:44:16 +0000738 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000739 &_image_info->border_color,_exception);
anthony74b1cfc2011-10-06 12:44:16 +0000740 (void) QueryColorCompliance(BorderColor,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +0000741 &_draw_info->border_color,_exception);
anthony805a2d42011-09-25 08:25:12 +0000742 break;
743 }
anthonyafa3dfc2012-03-03 11:31:30 +0000744 if (LocaleCompare("box",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000745 {
anthonyfd706f92012-01-19 04:22:02 +0000746 /* DEPRECIATED - now "undercolor" */
anthony24aa8822012-03-11 00:56:06 +0000747 CLISettingOptionInfo(cli_wand,"undercolor",arg1);
anthonyfd706f92012-01-19 04:22:02 +0000748 break;
anthony805a2d42011-09-25 08:25:12 +0000749 }
750 break;
751 }
752 case 'c':
753 {
anthonyafa3dfc2012-03-03 11:31:30 +0000754 if (LocaleCompare("cache",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000755 {
756 MagickSizeType
757 limit;
758
anthony5330ae02012-03-20 14:17:01 +0000759 if (IfSetOption && IsGeometry(arg1) == MagickFalse)
760 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +0000761 limit=MagickResourceInfinity;
anthony24aa8822012-03-11 00:56:06 +0000762 if (LocaleCompare("unlimited",arg1) != 0)
763 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg1,100.0);
anthony805a2d42011-09-25 08:25:12 +0000764 (void) SetMagickResourceLimit(MemoryResource,limit);
765 (void) SetMagickResourceLimit(MapResource,2*limit);
766 break;
767 }
anthonyafa3dfc2012-03-03 11:31:30 +0000768 if (LocaleCompare("caption",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000769 {
anthony92c93bd2012-03-19 14:02:47 +0000770 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000771 break;
772 }
anthonyafa3dfc2012-03-03 11:31:30 +0000773 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000774 {
anthony30b912a2012-03-22 01:20:28 +0000775 arg1=ArgOption("default");
776 parse=ParseChannelOption(arg1);
777 if (parse < 0)
778 CLIWandExceptArgBreak(OptionError,"UnrecognizedChannelType",
779 option,arg1);
780 _image_info->channel=(ChannelType) parse;
781 (void) SetImageOption(_image_info,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +0000782 break;
783 }
anthonyafa3dfc2012-03-03 11:31:30 +0000784 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000785 {
anthonyafbaed72011-10-26 12:05:04 +0000786 /* Setting used for new images via AquireImage()
787 But also used as a SimpleImageOperator
788 Undefined colorspace means don't modify images on
789 read or as a operation */
anthony30b912a2012-03-22 01:20:28 +0000790 parse = ParseCommandOption(MagickColorspaceOptions,MagickFalse,
791 ArgOption("undefined"));
792 if (parse < 0)
anthony5330ae02012-03-20 14:17:01 +0000793 CLIWandExceptArgBreak(OptionError,"UnrecognizedColorspace",
794 option,arg1);
anthony30b912a2012-03-22 01:20:28 +0000795 _image_info->colorspace=(ColorspaceType) parse;
anthony805a2d42011-09-25 08:25:12 +0000796 break;
797 }
anthonyafa3dfc2012-03-03 11:31:30 +0000798 if (LocaleCompare("comment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000799 {
anthony92c93bd2012-03-19 14:02:47 +0000800 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000801 break;
802 }
anthonyafa3dfc2012-03-03 11:31:30 +0000803 if (LocaleCompare("compose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000804 {
anthony92c93bd2012-03-19 14:02:47 +0000805 /* FUTURE: _image_info should be used,
anthony72feaa62012-01-17 06:46:23 +0000806 SyncImageSettings() used to set per-image attribute. - REMOVE
807
anthonyafbaed72011-10-26 12:05:04 +0000808 This setting should NOT be used to set image 'compose'
anthony92c93bd2012-03-19 14:02:47 +0000809 "-layer" operators shoud use _image_info if defined otherwise
anthony72feaa62012-01-17 06:46:23 +0000810 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000811 */
anthony92c93bd2012-03-19 14:02:47 +0000812 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
813 _image_info->compose=(CompositeOperator) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000814 MagickComposeOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000815 break;
816 }
anthonyafa3dfc2012-03-03 11:31:30 +0000817 if (LocaleCompare("compress",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000818 {
anthony92c93bd2012-03-19 14:02:47 +0000819 /* FUTURE: What should be used? _image_info or ImageOption ???
anthony5f867ae2011-10-09 10:28:34 +0000820 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000821 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000822
anthony92c93bd2012-03-19 14:02:47 +0000823 The coders appears to use _image_info, not Image_Option
anthony5f867ae2011-10-09 10:28:34 +0000824 however the image attribute (for save) is set from the
825 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000826
827 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000828 */
anthony92c93bd2012-03-19 14:02:47 +0000829 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
830 _image_info->compression=(CompressionType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000831 MagickCompressOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000832 break;
833 }
834 break;
835 }
836 case 'd':
837 {
anthonyafa3dfc2012-03-03 11:31:30 +0000838 if (LocaleCompare("debug",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000839 {
anthony72feaa62012-01-17 06:46:23 +0000840 /* SyncImageSettings() used to set per-image attribute. */
841 (void) SetLogEventMask(ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000842 _image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000843 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000844 break;
845 }
anthonyafa3dfc2012-03-03 11:31:30 +0000846 if (LocaleCompare("define",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000847 {
anthony24aa8822012-03-11 00:56:06 +0000848 if (LocaleNCompare(arg1,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000849 {
anthony5f867ae2011-10-09 10:28:34 +0000850 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000851 (void) DefineImageRegistry(StringRegistryType,arg1+9,_exception);
anthony5f867ae2011-10-09 10:28:34 +0000852 else
anthony24aa8822012-03-11 00:56:06 +0000853 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +0000854 break;
855 }
anthony24aa8822012-03-11 00:56:06 +0000856 /* DefineImageOption() equals SetImageOption() but with '=' */
anthony5f867ae2011-10-09 10:28:34 +0000857 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +0000858 (void) DefineImageOption(_image_info,arg1);
anthony5f867ae2011-10-09 10:28:34 +0000859 else
anthony92c93bd2012-03-19 14:02:47 +0000860 (void) DeleteImageOption(_image_info,arg1);
anthony805a2d42011-09-25 08:25:12 +0000861 break;
862 }
anthonyafa3dfc2012-03-03 11:31:30 +0000863 if (LocaleCompare("delay",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000864 {
anthonyafbaed72011-10-26 12:05:04 +0000865 /* Only used for new images via AcquireImage()
866 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000867 */
anthony92c93bd2012-03-19 14:02:47 +0000868 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000869 break;
870 }
anthonyafa3dfc2012-03-03 11:31:30 +0000871 if (LocaleCompare("density",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000872 {
anthony92c93bd2012-03-19 14:02:47 +0000873 /* FUTURE: strings used in _image_info attr and _draw_info!
anthony72feaa62012-01-17 06:46:23 +0000874 Basically as density can be in a XxY form!
875
876 SyncImageSettings() used to set per-image attribute.
877 */
anthony92c93bd2012-03-19 14:02:47 +0000878 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
879 (void) CloneString(&_image_info->density,ArgOption(NULL));
880 (void) CloneString(&_draw_info->density,_image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000881 break;
882 }
anthonyafa3dfc2012-03-03 11:31:30 +0000883 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000884 {
anthony72feaa62012-01-17 06:46:23 +0000885 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
886 SyncImageSettings() used to set per-image attribute.
887 */
anthony92c93bd2012-03-19 14:02:47 +0000888 _image_info->depth=IfSetOption?StringToUnsignedLong(arg1)
anthony5f867ae2011-10-09 10:28:34 +0000889 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000890 break;
891 }
anthonyafa3dfc2012-03-03 11:31:30 +0000892 if (LocaleCompare("direction",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000893 {
anthony92c93bd2012-03-19 14:02:47 +0000894 /* Image Option is only used to set _draw_info */
895 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
896 _draw_info->direction=(DirectionType) ParseCommandOption(
anthony5f867ae2011-10-09 10:28:34 +0000897 MagickDirectionOptions,MagickFalse,
anthony72feaa62012-01-17 06:46:23 +0000898 ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000899 break;
900 }
anthonyafa3dfc2012-03-03 11:31:30 +0000901 if (LocaleCompare("display",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000902 {
anthony92c93bd2012-03-19 14:02:47 +0000903 (void) CloneString(&_image_info->server_name,ArgOption(NULL));
904 (void) CloneString(&_draw_info->server_name,_image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000905 break;
906 }
anthonyafa3dfc2012-03-03 11:31:30 +0000907 if (LocaleCompare("dispose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000908 {
anthony72feaa62012-01-17 06:46:23 +0000909 /* only used in setting new images */
anthony92c93bd2012-03-19 14:02:47 +0000910 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000911 break;
912 }
anthonyafa3dfc2012-03-03 11:31:30 +0000913 if (LocaleCompare("dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000914 {
anthony92c93bd2012-03-19 14:02:47 +0000915 /* _image_info attr (on/off), _quantize_info attr (on/off)
916 but also ImageInfo and _quantize_info method!
anthony72feaa62012-01-17 06:46:23 +0000917 FUTURE: merge the duality of the dithering options
918 */
anthony92c93bd2012-03-19 14:02:47 +0000919 _image_info->dither = _quantize_info->dither = ArgBoolean;
920 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
921 _quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000922 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony92c93bd2012-03-19 14:02:47 +0000923 if (_quantize_info->dither_method == NoDitherMethod)
924 _image_info->dither = _quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000925 break;
926 }
927 break;
928 }
929 case 'e':
930 {
anthonyafa3dfc2012-03-03 11:31:30 +0000931 if (LocaleCompare("encoding",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000932 {
anthony92c93bd2012-03-19 14:02:47 +0000933 (void) CloneString(&_draw_info->encoding,ArgOption("undefined"));
934 (void) SetImageOption(_image_info,option+1,_draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000935 break;
936 }
anthonyafa3dfc2012-03-03 11:31:30 +0000937 if (LocaleCompare("endian",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000938 {
anthony92c93bd2012-03-19 14:02:47 +0000939 /* Both _image_info attr and ImageInfo */
940 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
941 _image_info->endian=(EndianType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000942 MagickEndianOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000943 break;
944 }
anthonyafa3dfc2012-03-03 11:31:30 +0000945 if (LocaleCompare("extract",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000946 {
anthony92c93bd2012-03-19 14:02:47 +0000947 (void) CloneString(&_image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000948 break;
949 }
950 break;
951 }
952 case 'f':
953 {
anthonyafa3dfc2012-03-03 11:31:30 +0000954 if (LocaleCompare("family",option+1) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000955 {
anthony92c93bd2012-03-19 14:02:47 +0000956 (void) CloneString(&_draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000957 break;
958 }
anthonyafa3dfc2012-03-03 11:31:30 +0000959 if (LocaleCompare("fill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000960 {
anthony92c93bd2012-03-19 14:02:47 +0000961 /* Set "fill" OR "fill-pattern" in _draw_info
anthonyfd706f92012-01-19 04:22:02 +0000962 The original fill color is preserved if a fill-pattern is given.
963 That way it does not effect other operations that directly using
964 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000965 */
anthony6dc09cd2011-10-12 08:56:49 +0000966 const char
anthony72feaa62012-01-17 06:46:23 +0000967 *value;
968
969 MagickBooleanType
970 status;
anthony6dc09cd2011-10-12 08:56:49 +0000971
972 ExceptionInfo
973 *sans;
974
anthonyfd706f92012-01-19 04:22:02 +0000975 PixelInfo
976 color;
977
anthony72feaa62012-01-17 06:46:23 +0000978 value = ArgOption("none");
anthony92c93bd2012-03-19 14:02:47 +0000979 (void) SetImageOption(_image_info,option+1,value);
980 if (_draw_info->fill_pattern != (Image *) NULL)
981 _draw_info->fill_pattern=DestroyImage(_draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000982
983 /* is it a color or a image? -- ignore exceptions */
984 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +0000985 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000986 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000987
anthony6dc09cd2011-10-12 08:56:49 +0000988 if (status == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +0000989 _draw_info->fill_pattern=GetImageCache(_image_info,value,_exception);
anthonyfd706f92012-01-19 04:22:02 +0000990 else
anthony92c93bd2012-03-19 14:02:47 +0000991 _draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000992 break;
993 }
anthonyafa3dfc2012-03-03 11:31:30 +0000994 if (LocaleCompare("filter",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +0000995 {
anthony72feaa62012-01-17 06:46:23 +0000996 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +0000997 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000998 break;
999 }
anthonyafa3dfc2012-03-03 11:31:30 +00001000 if (LocaleCompare("font",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001001 {
anthony92c93bd2012-03-19 14:02:47 +00001002 (void) CloneString(&_draw_info->font,ArgOption(NULL));
1003 (void) CloneString(&_image_info->font,_draw_info->font);
anthony805a2d42011-09-25 08:25:12 +00001004 break;
1005 }
anthonyafa3dfc2012-03-03 11:31:30 +00001006 if (LocaleCompare("format",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001007 {
anthonydcf510d2011-10-30 13:51:40 +00001008 /* FUTURE: why the ping test, you could set ping after this! */
1009 /*
anthony805a2d42011-09-25 08:25:12 +00001010 register const char
1011 *q;
1012
anthony24aa8822012-03-11 00:56:06 +00001013 for (q=strchr(arg1,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +00001014 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00001015 _image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +00001016 */
anthony92c93bd2012-03-19 14:02:47 +00001017 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001018 break;
1019 }
anthonyafa3dfc2012-03-03 11:31:30 +00001020 if (LocaleCompare("fuzz",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001021 {
anthony72feaa62012-01-17 06:46:23 +00001022 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +00001023 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +00001024 SyncImageSettings() used to set per-image attribute.
1025
anthony92c93bd2012-03-19 14:02:47 +00001026 Can't find anything else using _image_info->fuzz directly!
anthony6613bf32011-10-15 07:24:44 +00001027 */
1028 if (IfSetOption)
cristy947cb4c2011-10-20 18:41:46 +00001029 {
anthony92c93bd2012-03-19 14:02:47 +00001030 _image_info->fuzz=StringToDoubleInterval(arg1,(double)
anthony80c37752012-01-16 01:03:11 +00001031 QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00001032 (void) SetImageOption(_image_info,option+1,arg1);
cristy947cb4c2011-10-20 18:41:46 +00001033 break;
1034 }
anthony92c93bd2012-03-19 14:02:47 +00001035 _image_info->fuzz=0.0;
1036 (void) SetImageOption(_image_info,option+1,"0");
anthony805a2d42011-09-25 08:25:12 +00001037 break;
1038 }
1039 break;
1040 }
1041 case 'g':
1042 {
anthonyafa3dfc2012-03-03 11:31:30 +00001043 if (LocaleCompare("gravity",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001044 {
anthony72feaa62012-01-17 06:46:23 +00001045 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001046 (void) SetImageOption(_image_info,option+1,ArgOption("none"));
1047 _draw_info->gravity=(GravityType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001048 MagickGravityOptions,MagickFalse,ArgOption("none"));
anthony805a2d42011-09-25 08:25:12 +00001049 break;
1050 }
anthonyafa3dfc2012-03-03 11:31:30 +00001051 if (LocaleCompare("green-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001052 {
anthonydcf510d2011-10-30 13:51:40 +00001053 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +00001054 SyncImageSettings() used to set per-image attribute.
1055 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +00001056 */
anthony92c93bd2012-03-19 14:02:47 +00001057 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001058 break;
1059 }
1060 break;
1061 }
1062 case 'i':
1063 {
anthonyafa3dfc2012-03-03 11:31:30 +00001064 if (LocaleCompare("intent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001065 {
anthony72feaa62012-01-17 06:46:23 +00001066 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +00001067 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +00001068 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001069 */
anthony92c93bd2012-03-19 14:02:47 +00001070 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001071 break;
1072 }
anthonyafa3dfc2012-03-03 11:31:30 +00001073 if (LocaleCompare("interlace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001074 {
anthony92c93bd2012-03-19 14:02:47 +00001075 /* _image_info is directly used by coders (so why an image setting?)
anthony72feaa62012-01-17 06:46:23 +00001076 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001077 */
anthony92c93bd2012-03-19 14:02:47 +00001078 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
1079 _image_info->interlace=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001080 MagickInterlaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001081 break;
1082 }
anthonyafa3dfc2012-03-03 11:31:30 +00001083 if (LocaleCompare("interline-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001084 {
anthony92c93bd2012-03-19 14:02:47 +00001085 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1086 _draw_info->interline_spacing=StringToDouble(ArgOption("0"),
anthony72feaa62012-01-17 06:46:23 +00001087 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001088 break;
1089 }
anthonyafa3dfc2012-03-03 11:31:30 +00001090 if (LocaleCompare("interpolate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001091 {
anthonyfd706f92012-01-19 04:22:02 +00001092 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001093 (void) SetImageOption(_image_info,option+1,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001094 break;
1095 }
anthonyafa3dfc2012-03-03 11:31:30 +00001096 if (LocaleCompare("interword-spacing",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001097 {
anthony92c93bd2012-03-19 14:02:47 +00001098 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1099 _draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001100 break;
1101 }
1102 break;
1103 }
1104 case 'k':
1105 {
anthonyafa3dfc2012-03-03 11:31:30 +00001106 if (LocaleCompare("kerning",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001107 {
anthony92c93bd2012-03-19 14:02:47 +00001108 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1109 _draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001110 break;
1111 }
1112 break;
1113 }
1114 case 'l':
1115 {
anthonyafa3dfc2012-03-03 11:31:30 +00001116 if (LocaleCompare("label",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001117 {
anthony72feaa62012-01-17 06:46:23 +00001118 /* only used for new images - not in SyncImageOptions() */
anthony92c93bd2012-03-19 14:02:47 +00001119 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001120 break;
1121 }
anthonyafa3dfc2012-03-03 11:31:30 +00001122 if (LocaleCompare("log",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001123 {
anthonydcf510d2011-10-30 13:51:40 +00001124 if (IfSetOption)
anthony24aa8822012-03-11 00:56:06 +00001125 (void) SetLogFormat(arg1);
anthony805a2d42011-09-25 08:25:12 +00001126 break;
1127 }
anthonyafa3dfc2012-03-03 11:31:30 +00001128 if (LocaleCompare("loop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001129 {
anthony72feaa62012-01-17 06:46:23 +00001130 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001131 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001132 break;
1133 }
1134 break;
1135 }
1136 case 'm':
1137 {
anthonyafa3dfc2012-03-03 11:31:30 +00001138 if (LocaleCompare("mattecolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001139 {
anthony72feaa62012-01-17 06:46:23 +00001140 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001141 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001142 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001143 &_image_info->matte_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001144 break;
1145 }
anthonyafa3dfc2012-03-03 11:31:30 +00001146 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001147 {
anthony92c93bd2012-03-19 14:02:47 +00001148 (void) SetImageInfoProgressMonitor(_image_info, IfSetOption?
anthony31f1bf72012-01-30 12:37:22 +00001149 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001150 break;
1151 }
anthonyafa3dfc2012-03-03 11:31:30 +00001152 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001153 {
anthony24aa8822012-03-11 00:56:06 +00001154 /* Setting (used by some input coders!) -- why?
1155 Warning: This is also Special '-type' SimpleOperator
anthony72feaa62012-01-17 06:46:23 +00001156 */
anthony92c93bd2012-03-19 14:02:47 +00001157 _image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001158 break;
1159 }
1160 break;
1161 }
1162 case 'o':
1163 {
anthonyafa3dfc2012-03-03 11:31:30 +00001164 if (LocaleCompare("orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001165 {
anthony72feaa62012-01-17 06:46:23 +00001166 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001167 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001168 FUTURE: make set meta-data operator instead.
1169 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001170 */
anthony92c93bd2012-03-19 14:02:47 +00001171 (void) SetImageOption(_image_info,option+1, ArgOption(NULL));
1172 _image_info->orientation=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001173 MagickOrientationOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001174 break;
1175 }
1176 }
1177 case 'p':
1178 {
anthonyafa3dfc2012-03-03 11:31:30 +00001179 if (LocaleCompare("page",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001180 {
anthony72feaa62012-01-17 06:46:23 +00001181 /* Only used for new images and image generators
1182 SyncImageSettings() used to set per-image attribute. ?????
1183 That last is WRONG!!!!
1184 */
anthony805a2d42011-09-25 08:25:12 +00001185 char
1186 *canonical_page,
1187 page[MaxTextExtent];
1188
1189 const char
1190 *image_option;
1191
1192 MagickStatusType
1193 flags;
1194
1195 RectangleInfo
1196 geometry;
1197
anthonydcf510d2011-10-30 13:51:40 +00001198 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001199 {
anthony92c93bd2012-03-19 14:02:47 +00001200 (void) DeleteImageOption(_image_info,option+1);
1201 (void) CloneString(&_image_info->page,(char *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001202 break;
1203 }
1204 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
anthony92c93bd2012-03-19 14:02:47 +00001205 image_option=GetImageOption(_image_info,"page");
anthony805a2d42011-09-25 08:25:12 +00001206 if (image_option != (const char *) NULL)
1207 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthony24aa8822012-03-11 00:56:06 +00001208 canonical_page=GetPageGeometry(arg1);
anthony805a2d42011-09-25 08:25:12 +00001209 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1210 canonical_page=DestroyString(canonical_page);
1211 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1212 (unsigned long) geometry.width,(unsigned long) geometry.height);
1213 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1214 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1215 (unsigned long) geometry.width,(unsigned long) geometry.height,
1216 (long) geometry.x,(long) geometry.y);
anthony92c93bd2012-03-19 14:02:47 +00001217 (void) SetImageOption(_image_info,option+1,page);
1218 (void) CloneString(&_image_info->page,page);
anthony805a2d42011-09-25 08:25:12 +00001219 break;
1220 }
anthonyafa3dfc2012-03-03 11:31:30 +00001221 if (LocaleCompare("ping",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001222 {
anthony92c93bd2012-03-19 14:02:47 +00001223 _image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001224 break;
1225 }
anthonyafa3dfc2012-03-03 11:31:30 +00001226 if (LocaleCompare("pointsize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001227 {
anthony92c93bd2012-03-19 14:02:47 +00001228 _image_info->pointsize=_draw_info->pointsize=
anthony72feaa62012-01-17 06:46:23 +00001229 StringToDouble(ArgOption("12"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001230 break;
1231 }
anthonyafa3dfc2012-03-03 11:31:30 +00001232 if (LocaleCompare("precision",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001233 {
anthony72feaa62012-01-17 06:46:23 +00001234 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
anthony805a2d42011-09-25 08:25:12 +00001235 break;
1236 }
anthonydcf510d2011-10-30 13:51:40 +00001237 /* FUTURE: Only the 'preview' coder appears to use this
anthonya3ef4ed2012-03-17 06:52:53 +00001238 * DEPRECIATE the coder? Leaving only the 'preview' operator.
anthonyafa3dfc2012-03-03 11:31:30 +00001239 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001240 {
anthony92c93bd2012-03-19 14:02:47 +00001241 _image_info->preview_type=UndefinedPreview;
anthonydcf510d2011-10-30 13:51:40 +00001242 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001243 _image_info->preview_type=(PreviewType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001244 MagickPreviewOptions,MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00001245 break;
1246 }
anthonydcf510d2011-10-30 13:51:40 +00001247 */
anthony805a2d42011-09-25 08:25:12 +00001248 break;
1249 }
1250 case 'q':
1251 {
anthonyafa3dfc2012-03-03 11:31:30 +00001252 if (LocaleCompare("quality",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001253 {
anthony92c93bd2012-03-19 14:02:47 +00001254 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1255 _image_info->quality=UNDEFINED_COMPRESSION_QUALITY;
anthony72feaa62012-01-17 06:46:23 +00001256 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001257 _image_info->quality=StringToUnsignedLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00001258 break;
1259 }
anthonyafa3dfc2012-03-03 11:31:30 +00001260 if (LocaleCompare("quantize",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001261 {
anthony92c93bd2012-03-19 14:02:47 +00001262 /* Just a set direct in _quantize_info */
1263 _quantize_info->colorspace=UndefinedColorspace;
anthonyafbaed72011-10-26 12:05:04 +00001264 if (IfSetOption)
anthony92c93bd2012-03-19 14:02:47 +00001265 _quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
anthony24aa8822012-03-11 00:56:06 +00001266 MagickColorspaceOptions,MagickFalse,arg1);
anthonyafbaed72011-10-26 12:05:04 +00001267 break;
1268 }
anthonyafa3dfc2012-03-03 11:31:30 +00001269 if (LocaleCompare("quiet",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001270 {
anthonydcf510d2011-10-30 13:51:40 +00001271 /* FUTURE: if two -quiet is performed you can not do +quiet! */
anthony805a2d42011-09-25 08:25:12 +00001272 static WarningHandler
1273 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001274
anthonyafbaed72011-10-26 12:05:04 +00001275 WarningHandler
1276 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001277
anthonyafbaed72011-10-26 12:05:04 +00001278 if ( tmp != (WarningHandler) NULL)
1279 warning_handler = tmp; /* remember the old handler */
1280 if (!IfSetOption) /* set the old handler */
1281 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001282 break;
1283 }
1284 break;
1285 }
1286 case 'r':
1287 {
anthonyafa3dfc2012-03-03 11:31:30 +00001288 if (LocaleCompare("red-primary",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001289 {
anthonydcf510d2011-10-30 13:51:40 +00001290 /* Image chromaticity X,Y NB: Y=X if Y not defined
1291 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001292 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001293 */
anthony92c93bd2012-03-19 14:02:47 +00001294 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001295 break;
1296 }
anthonyafa3dfc2012-03-03 11:31:30 +00001297 if (LocaleCompare("render",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001298 {
anthony92c93bd2012-03-19 14:02:47 +00001299 /* _draw_info only setting */
1300 _draw_info->render= ArgBooleanNot;
anthonyafbaed72011-10-26 12:05:04 +00001301 break;
1302 }
anthony805a2d42011-09-25 08:25:12 +00001303 break;
1304 }
1305 case 's':
1306 {
anthonyafa3dfc2012-03-03 11:31:30 +00001307 if (LocaleCompare("sampling-factor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001308 {
anthonyafbaed72011-10-26 12:05:04 +00001309 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony92c93bd2012-03-19 14:02:47 +00001310 (void) CloneString(&_image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001311 break;
1312 }
anthonyafa3dfc2012-03-03 11:31:30 +00001313 if (LocaleCompare("scene",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001314 {
anthony72feaa62012-01-17 06:46:23 +00001315 /* SyncImageSettings() used to set per-image attribute.
1316 What ??? Why ????
1317 */
anthony92c93bd2012-03-19 14:02:47 +00001318 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1319 _image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001320 break;
1321 }
anthonyafa3dfc2012-03-03 11:31:30 +00001322 if (LocaleCompare("seed",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001323 {
anthonyafbaed72011-10-26 12:05:04 +00001324 SeedPseudoRandomGenerator(
anthony24aa8822012-03-11 00:56:06 +00001325 IfSetOption ? (size_t) StringToUnsignedLong(arg1)
anthonyafbaed72011-10-26 12:05:04 +00001326 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001327 break;
1328 }
anthonyafa3dfc2012-03-03 11:31:30 +00001329 if (LocaleCompare("size",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001330 {
anthony92c93bd2012-03-19 14:02:47 +00001331 /* FUTURE: string in _image_info -- convert to Option ???
anthonyafbaed72011-10-26 12:05:04 +00001332 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001333 */
anthony92c93bd2012-03-19 14:02:47 +00001334 (void) CloneString(&_image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001335 break;
1336 }
anthonyafa3dfc2012-03-03 11:31:30 +00001337 if (LocaleCompare("stretch",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001338 {
anthony92c93bd2012-03-19 14:02:47 +00001339 _draw_info->stretch=(StretchType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001340 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001341 break;
1342 }
anthonyafa3dfc2012-03-03 11:31:30 +00001343 if (LocaleCompare("stroke",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001344 {
anthonyafbaed72011-10-26 12:05:04 +00001345 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001346 UPDATE: ensure stroke color is not destroyed is a pattern
1347 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001348 */
1349 const char
anthony72feaa62012-01-17 06:46:23 +00001350 *value;
1351
1352 MagickBooleanType
1353 status;
anthonyafbaed72011-10-26 12:05:04 +00001354
1355 ExceptionInfo
1356 *sans;
1357
anthonyfd706f92012-01-19 04:22:02 +00001358 PixelInfo
1359 color;
1360
anthony72feaa62012-01-17 06:46:23 +00001361 value = ArgOption("none");
anthony92c93bd2012-03-19 14:02:47 +00001362 (void) SetImageOption(_image_info,option+1,value);
1363 if (_draw_info->stroke_pattern != (Image *) NULL)
1364 _draw_info->stroke_pattern=DestroyImage(_draw_info->stroke_pattern);
anthony72feaa62012-01-17 06:46:23 +00001365
1366 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001367 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +00001368 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001369 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001370
anthonyafbaed72011-10-26 12:05:04 +00001371 if (status == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00001372 _draw_info->stroke_pattern=GetImageCache(_image_info,value,_exception);
anthonyfd706f92012-01-19 04:22:02 +00001373 else
anthony92c93bd2012-03-19 14:02:47 +00001374 _draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001375 break;
1376 }
anthonyafa3dfc2012-03-03 11:31:30 +00001377 if (LocaleCompare("strokewidth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001378 {
anthony92c93bd2012-03-19 14:02:47 +00001379 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1380 _draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
anthony72feaa62012-01-17 06:46:23 +00001381 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001382 break;
1383 }
anthonyafa3dfc2012-03-03 11:31:30 +00001384 if (LocaleCompare("style",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001385 {
anthony92c93bd2012-03-19 14:02:47 +00001386 _draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
anthony72feaa62012-01-17 06:46:23 +00001387 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001388 break;
1389 }
anthonyafa3dfc2012-03-03 11:31:30 +00001390 if (LocaleCompare("synchronize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001391 {
anthony92c93bd2012-03-19 14:02:47 +00001392 _image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001393 break;
1394 }
1395 break;
1396 }
1397 case 't':
1398 {
anthonyafa3dfc2012-03-03 11:31:30 +00001399 if (LocaleCompare("taint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001400 {
anthony72feaa62012-01-17 06:46:23 +00001401 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001402 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
anthony805a2d42011-09-25 08:25:12 +00001403 break;
1404 }
anthonyafa3dfc2012-03-03 11:31:30 +00001405 if (LocaleCompare("texture",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001406 {
anthony92c93bd2012-03-19 14:02:47 +00001407 /* FUTURE: move _image_info string to option splay-tree */
1408 (void) CloneString(&_image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001409 break;
1410 }
anthonyafa3dfc2012-03-03 11:31:30 +00001411 if (LocaleCompare("tile",option+1) == 0)
anthonyafbaed72011-10-26 12:05:04 +00001412 {
anthony92c93bd2012-03-19 14:02:47 +00001413 _draw_info->fill_pattern=IfSetOption
1414 ?GetImageCache(_image_info,arg1,_exception)
1415 :DestroyImage(_draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001416 break;
1417 }
anthonyafa3dfc2012-03-03 11:31:30 +00001418 if (LocaleCompare("tile-offset",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001419 {
anthony72feaa62012-01-17 06:46:23 +00001420 /* SyncImageSettings() used to set per-image attribute. ??? */
anthony92c93bd2012-03-19 14:02:47 +00001421 (void) SetImageOption(_image_info,option+1,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001422 break;
1423 }
anthonyafa3dfc2012-03-03 11:31:30 +00001424 if (LocaleCompare("transparent-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001425 {
anthony92c93bd2012-03-19 14:02:47 +00001426 /* FUTURE: both _image_info attribute & ImageOption in use!
1427 _image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001428 SyncImageSettings() used to set per-image attribute.
1429
anthonyafbaed72011-10-26 12:05:04 +00001430 Note that +transparent-color, means fall-back to image
1431 attribute so ImageOption is deleted, not set to a default.
1432 */
anthony92c93bd2012-03-19 14:02:47 +00001433 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001434 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001435 &_image_info->transparent_color,_exception);
anthony805a2d42011-09-25 08:25:12 +00001436 break;
1437 }
anthonyafa3dfc2012-03-03 11:31:30 +00001438 if (LocaleCompare("treedepth",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00001439 {
anthony92c93bd2012-03-19 14:02:47 +00001440 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1441 _quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
anthony31f1bf72012-01-30 12:37:22 +00001442 break;
1443 }
anthonyafa3dfc2012-03-03 11:31:30 +00001444 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001445 {
anthony72feaa62012-01-17 06:46:23 +00001446 /* SyncImageSettings() used to set per-image attribute. */
anthony92c93bd2012-03-19 14:02:47 +00001447 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1448 _image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
anthony72feaa62012-01-17 06:46:23 +00001449 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001450 break;
1451 }
1452 break;
1453 }
1454 case 'u':
1455 {
anthonyafa3dfc2012-03-03 11:31:30 +00001456 if (LocaleCompare("undercolor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001457 {
anthony92c93bd2012-03-19 14:02:47 +00001458 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001459 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00001460 &_draw_info->undercolor,_exception);
anthony805a2d42011-09-25 08:25:12 +00001461 break;
1462 }
anthonyafa3dfc2012-03-03 11:31:30 +00001463 if (LocaleCompare("units",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001464 {
anthony72feaa62012-01-17 06:46:23 +00001465 /* SyncImageSettings() used to set per-image attribute.
anthony92c93bd2012-03-19 14:02:47 +00001466 Should this effect _draw_info X and Y resolution?
anthony72feaa62012-01-17 06:46:23 +00001467 FUTURE: this probably should be part of the density setting
1468 */
anthony92c93bd2012-03-19 14:02:47 +00001469 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
1470 _image_info->units=(ResolutionType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001471 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001472 break;
1473 }
1474 break;
1475 }
1476 case 'v':
1477 {
anthonyafa3dfc2012-03-03 11:31:30 +00001478 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001479 {
anthony24aa8822012-03-11 00:56:06 +00001480 /* FUTURE: Remember all options become image artifacts
anthony92c93bd2012-03-19 14:02:47 +00001481 _image_info->verbose is only used by coders.
anthonyab3a50c2011-10-27 11:48:57 +00001482 */
anthony92c93bd2012-03-19 14:02:47 +00001483 (void) SetImageOption(_image_info,option+1,ArgBooleanString);
1484 _image_info->verbose= ArgBoolean;
1485 _image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001486 break;
1487 }
anthonyafa3dfc2012-03-03 11:31:30 +00001488 if (LocaleCompare("view",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001489 {
anthony92c93bd2012-03-19 14:02:47 +00001490 /* FUTURE: Convert from _image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001491 Only used by coder FPX
1492 */
anthony92c93bd2012-03-19 14:02:47 +00001493 (void) CloneString(&_image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001494 break;
1495 }
anthonyafa3dfc2012-03-03 11:31:30 +00001496 if (LocaleCompare("virtual-pixel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001497 {
anthonyfd706f92012-01-19 04:22:02 +00001498 /* SyncImageSettings() used to set per-image attribute.
1499 This is VERY deep in the image caching structure.
1500 */
anthony92c93bd2012-03-19 14:02:47 +00001501 (void) SetImageOption(_image_info,option+1,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001502 break;
1503 }
1504 break;
1505 }
1506 case 'w':
1507 {
anthonyafa3dfc2012-03-03 11:31:30 +00001508 if (LocaleCompare("weight",option+1) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001509 {
anthony72feaa62012-01-17 06:46:23 +00001510 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001511 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001512 */
anthony72feaa62012-01-17 06:46:23 +00001513 if (!IfSetOption)
1514 break;
anthony92c93bd2012-03-19 14:02:47 +00001515 _draw_info->weight=StringToUnsignedLong(arg1);
anthony24aa8822012-03-11 00:56:06 +00001516 if (LocaleCompare(arg1,"all") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001517 _draw_info->weight=0;
anthony24aa8822012-03-11 00:56:06 +00001518 if (LocaleCompare(arg1,"bold") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001519 _draw_info->weight=700;
anthony24aa8822012-03-11 00:56:06 +00001520 if (LocaleCompare(arg1,"bolder") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001521 if (_draw_info->weight <= 800)
1522 _draw_info->weight+=100;
anthony24aa8822012-03-11 00:56:06 +00001523 if (LocaleCompare(arg1,"lighter") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001524 if (_draw_info->weight >= 100)
1525 _draw_info->weight-=100;
anthony24aa8822012-03-11 00:56:06 +00001526 if (LocaleCompare(arg1,"normal") == 0)
anthony92c93bd2012-03-19 14:02:47 +00001527 _draw_info->weight=400;
anthonyab3a50c2011-10-27 11:48:57 +00001528 break;
1529 }
anthonyafa3dfc2012-03-03 11:31:30 +00001530 if (LocaleCompare("white-point",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001531 {
anthony72feaa62012-01-17 06:46:23 +00001532 /* Used as a image chromaticity setting
1533 SyncImageSettings() used to set per-image attribute.
1534 */
anthony92c93bd2012-03-19 14:02:47 +00001535 (void) SetImageOption(_image_info,option+1,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001536 break;
1537 }
1538 break;
1539 }
1540 default:
1541 break;
1542 }
anthony24aa8822012-03-11 00:56:06 +00001543
anthony92c93bd2012-03-19 14:02:47 +00001544#undef _image_info
1545#undef _exception
1546#undef _draw_info
1547#undef _quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001548#undef IfSetOption
anthonyfd706f92012-01-19 04:22:02 +00001549#undef ArgBoolean
anthony24aa8822012-03-11 00:56:06 +00001550#undef ArgBooleanNot
1551#undef ArgBooleanString
1552#undef ArgOption
anthonyfd706f92012-01-19 04:22:02 +00001553
anthony31f1bf72012-01-30 12:37:22 +00001554 return;
anthony805a2d42011-09-25 08:25:12 +00001555}
1556
1557/*
1558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1559% %
1560% %
1561% %
anthony43f425d2012-02-26 12:58:58 +00001562+ 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 +00001563% %
1564% %
1565% %
1566%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1567%
anthony31f1bf72012-01-30 12:37:22 +00001568% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001569% the images in the CLI wand, with the settings that was previously saved in
1570% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001571%
1572% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001573% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001574%
anthonyd1447672012-01-19 05:33:53 +00001575% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001576%
anthony43f425d2012-02-26 12:58:58 +00001577% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001578% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001579%
1580% A description of each parameter follows:
1581%
anthony43f425d2012-02-26 12:58:58 +00001582% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001583%
anthonyfd706f92012-01-19 04:22:02 +00001584% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001585%
anthonyfd706f92012-01-19 04:22:02 +00001586% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001587%
anthony31f1bf72012-01-30 12:37:22 +00001588% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001589%
anthony31f1bf72012-01-30 12:37:22 +00001590% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001591%
anthonyafa3dfc2012-03-03 11:31:30 +00001592% CLISimpleOperatorImages(cli_wand, "-crop","100x100+20+30",NULL);
1593% CLISimpleOperatorImages(cli_wand, "+repage",NULL,NULL);
1594% CLISimpleOperatorImages(cli_wand, "+distort","SRT","45");
anthonyfd706f92012-01-19 04:22:02 +00001595%
anthony24aa8822012-03-11 00:56:06 +00001596% Or for handling command line arguments EG: +/-option ["arg1"]
anthonydcf510d2011-10-30 13:51:40 +00001597%
anthony43f425d2012-02-26 12:58:58 +00001598% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001599% argc,argv
1600% i=index in argv
1601%
anthony2052d272012-02-28 12:48:29 +00001602% option_info = GetCommandOptionInfo(argv[i]);
1603% count=option_info->type;
1604% option_type=option_info->flags;
1605%
1606% if ( (option_type & SimpleOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00001607% CLISimpleOperatorImages(cli_wand, argv[i],
anthonyfd706f92012-01-19 04:22:02 +00001608% count>=1 ? argv[i+1] : (char *)NULL,
1609% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001610% i += count+1;
1611%
anthony805a2d42011-09-25 08:25:12 +00001612*/
anthony31f1bf72012-01-30 12:37:22 +00001613
1614/*
1615 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001616 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001617
1618 The image in the list may be modified in three different ways...
1619 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1620 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1621 * one image replace by a list of images (-separate and -crop only!)
1622
anthonyafa3dfc2012-03-03 11:31:30 +00001623 In each case the result replaces the single original image in the list, as
1624 well as the pointer to the modified image (last image added if replaced by a
1625 list of images) is returned.
anthony31f1bf72012-01-30 12:37:22 +00001626
1627 As the image pointed to may be replaced, the first image in the list may
1628 also change. GetFirstImageInList() should be used by caller if they wish
1629 return the Image pointer to the first image in list.
1630*/
anthony43f425d2012-02-26 12:58:58 +00001631static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00001632 const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001633{
1634 Image *
1635 new_image;
1636
anthony805a2d42011-09-25 08:25:12 +00001637 GeometryInfo
1638 geometry_info;
1639
1640 RectangleInfo
1641 geometry;
1642
1643 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001644 flags;
1645
anthony92c93bd2012-03-19 14:02:47 +00001646 ssize_t
1647 type;
1648
1649#define _image_info (cli_wand->wand.image_info)
1650#define _image (cli_wand->wand.images)
1651#define _exception (cli_wand->wand.exception)
1652#define _draw_info (cli_wand->draw_info)
1653#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00001654#define IfNormalOp (*option=='-')
1655#define IfPlusOp (*option!='-')
1656#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
1657#define plus_alt_op (IfNormalOp?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001658
anthony43f425d2012-02-26 12:58:58 +00001659 assert(cli_wand != (MagickCLI *) NULL);
1660 assert(cli_wand->signature == WandSignature);
1661 assert(cli_wand->wand.signature == WandSignature);
anthony5330ae02012-03-20 14:17:01 +00001662 assert(_image != (Image *) NULL); /* an image must be present */
anthony43f425d2012-02-26 12:58:58 +00001663 if (cli_wand->wand.debug != MagickFalse)
1664 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001665
anthony92c93bd2012-03-19 14:02:47 +00001666 (void) SyncImageSettings(_image_info,_image,_exception);
anthony24aa8822012-03-11 00:56:06 +00001667
anthony805a2d42011-09-25 08:25:12 +00001668 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001669
anthony5330ae02012-03-20 14:17:01 +00001670 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001671
anthonyfd706f92012-01-19 04:22:02 +00001672 /* FUTURE: We may need somthing a little more optimized than this!
1673 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1674 */
anthonyafa3dfc2012-03-03 11:31:30 +00001675 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00001676 {
1677 case 'a':
1678 {
anthonyafa3dfc2012-03-03 11:31:30 +00001679 if (LocaleCompare("adaptive-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001680 {
anthony92c93bd2012-03-19 14:02:47 +00001681 if (IsGeometry(arg1) == MagickFalse)
1682 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001683 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001684 if ((flags & SigmaValue) == 0)
1685 geometry_info.sigma=1.0;
1686 if ((flags & XiValue) == 0)
1687 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001688 new_image=AdaptiveBlurImage(_image,geometry_info.rho,
1689 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001690 break;
1691 }
anthonyafa3dfc2012-03-03 11:31:30 +00001692 if (LocaleCompare("adaptive-resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001693 {
anthony92c93bd2012-03-19 14:02:47 +00001694 if (IsGeometry(arg1) == MagickFalse)
1695 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1696 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
1697 new_image=AdaptiveResizeImage(_image,geometry.width,geometry.height,
1698 _exception);
anthony805a2d42011-09-25 08:25:12 +00001699 break;
1700 }
anthonyafa3dfc2012-03-03 11:31:30 +00001701 if (LocaleCompare("adaptive-sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001702 {
anthony92c93bd2012-03-19 14:02:47 +00001703 if (IsGeometry(arg1) == MagickFalse)
1704 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001705 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001706 if ((flags & SigmaValue) == 0)
1707 geometry_info.sigma=1.0;
1708 if ((flags & XiValue) == 0)
1709 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001710 new_image=AdaptiveSharpenImage(_image,geometry_info.rho,
1711 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001712 break;
1713 }
anthonyafa3dfc2012-03-03 11:31:30 +00001714 if (LocaleCompare("alpha",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001715 {
anthony92c93bd2012-03-19 14:02:47 +00001716 type=ParseCommandOption(MagickAlphaOptions,MagickFalse,arg1);
1717 if (type < 0)
1718 CLIWandExceptArgBreak(OptionError,"UnrecognizedAlphaChannelType",
1719 option,arg1);
1720 (void) SetImageAlphaChannel(_image,(AlphaChannelType)type,_exception);
anthony805a2d42011-09-25 08:25:12 +00001721 break;
1722 }
anthonyafa3dfc2012-03-03 11:31:30 +00001723 if (LocaleCompare("annotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001724 {
1725 char
1726 *text,
1727 geometry[MaxTextExtent];
1728
anthony92c93bd2012-03-19 14:02:47 +00001729 if (IsGeometry(arg1) == MagickFalse)
1730 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony805a2d42011-09-25 08:25:12 +00001731 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001732 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001733 if ((flags & SigmaValue) == 0)
1734 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00001735 text=InterpretImageProperties(_image_info,_image,arg2,
1736 _exception);
anthony805a2d42011-09-25 08:25:12 +00001737 if (text == (char *) NULL)
1738 break;
anthony92c93bd2012-03-19 14:02:47 +00001739 (void) CloneString(&_draw_info->text,text);
anthony805a2d42011-09-25 08:25:12 +00001740 text=DestroyString(text);
1741 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1742 geometry_info.xi,geometry_info.psi);
anthony92c93bd2012-03-19 14:02:47 +00001743 (void) CloneString(&_draw_info->geometry,geometry);
1744 _draw_info->affine.sx=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001745 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001746 _draw_info->affine.rx=sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001747 fmod(geometry_info.rho,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001748 _draw_info->affine.ry=(-sin(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001749 fmod(geometry_info.sigma,360.0))));
anthony92c93bd2012-03-19 14:02:47 +00001750 _draw_info->affine.sy=cos(DegreesToRadians(
anthony805a2d42011-09-25 08:25:12 +00001751 fmod(geometry_info.sigma,360.0)));
anthony92c93bd2012-03-19 14:02:47 +00001752 (void) AnnotateImage(_image,_draw_info,_exception);
1753 GetAffineMatrix(&_draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001754 break;
1755 }
anthonyafa3dfc2012-03-03 11:31:30 +00001756 if (LocaleCompare("auto-gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001757 {
anthony92c93bd2012-03-19 14:02:47 +00001758 (void) AutoGammaImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001759 break;
1760 }
anthonyafa3dfc2012-03-03 11:31:30 +00001761 if (LocaleCompare("auto-level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001762 {
anthony92c93bd2012-03-19 14:02:47 +00001763 (void) AutoLevelImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001764 break;
1765 }
anthonyafa3dfc2012-03-03 11:31:30 +00001766 if (LocaleCompare("auto-orient",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001767 {
anthony5330ae02012-03-20 14:17:01 +00001768 /* This should probably be a MagickCore function */
anthony92c93bd2012-03-19 14:02:47 +00001769 switch (_image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001770 {
1771 case TopRightOrientation:
1772 {
anthony92c93bd2012-03-19 14:02:47 +00001773 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001774 break;
1775 }
1776 case BottomRightOrientation:
1777 {
anthony92c93bd2012-03-19 14:02:47 +00001778 new_image=RotateImage(_image,180.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001779 break;
1780 }
1781 case BottomLeftOrientation:
1782 {
anthony92c93bd2012-03-19 14:02:47 +00001783 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001784 break;
1785 }
1786 case LeftTopOrientation:
1787 {
anthony92c93bd2012-03-19 14:02:47 +00001788 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001789 break;
1790 }
1791 case RightTopOrientation:
1792 {
anthony92c93bd2012-03-19 14:02:47 +00001793 new_image=RotateImage(_image,90.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001794 break;
1795 }
1796 case RightBottomOrientation:
1797 {
anthony92c93bd2012-03-19 14:02:47 +00001798 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001799 break;
1800 }
1801 case LeftBottomOrientation:
1802 {
anthony92c93bd2012-03-19 14:02:47 +00001803 new_image=RotateImage(_image,270.0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001804 break;
1805 }
1806 default:
1807 break;
1808 }
1809 if (new_image != (Image *) NULL)
1810 new_image->orientation=TopLeftOrientation;
1811 break;
1812 }
1813 break;
1814 }
1815 case 'b':
1816 {
anthonyafa3dfc2012-03-03 11:31:30 +00001817 if (LocaleCompare("black-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001818 {
anthony5330ae02012-03-20 14:17:01 +00001819 if (IsGeometry(arg1) == MagickFalse)
1820 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001821 (void) BlackThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001822 break;
1823 }
anthonyafa3dfc2012-03-03 11:31:30 +00001824 if (LocaleCompare("blue-shift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001825 {
anthony805a2d42011-09-25 08:25:12 +00001826 geometry_info.rho=1.5;
anthony5330ae02012-03-20 14:17:01 +00001827 if (IfNormalOp) {
1828 if (IsGeometry(arg1) == MagickFalse)
1829 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001830 flags=ParseGeometry(arg1,&geometry_info);
anthony5330ae02012-03-20 14:17:01 +00001831 }
anthony92c93bd2012-03-19 14:02:47 +00001832 new_image=BlueShiftImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00001833 break;
1834 }
anthonyafa3dfc2012-03-03 11:31:30 +00001835 if (LocaleCompare("blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001836 {
anthony74b1cfc2011-10-06 12:44:16 +00001837 /* FUTURE: use of "bias" in a blur is non-sensible */
anthony5330ae02012-03-20 14:17:01 +00001838 if (IsGeometry(arg1) == MagickFalse)
1839 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001840 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001841 if ((flags & SigmaValue) == 0)
1842 geometry_info.sigma=1.0;
1843 if ((flags & XiValue) == 0)
1844 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00001845 new_image=BlurImage(_image,geometry_info.rho,
1846 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001847 break;
1848 }
anthonyafa3dfc2012-03-03 11:31:30 +00001849 if (LocaleCompare("border",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001850 {
anthony31f1bf72012-01-30 12:37:22 +00001851 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001852 compose;
1853
1854 const char*
anthony5f867ae2011-10-09 10:28:34 +00001855 value;
1856
anthony5330ae02012-03-20 14:17:01 +00001857 if (IsGeometry(arg1) == MagickFalse)
1858 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
1859
anthony92c93bd2012-03-19 14:02:47 +00001860 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00001861 if (value != (const char *) NULL)
1862 compose=(CompositeOperator) ParseCommandOption(
1863 MagickComposeOptions,MagickFalse,value);
1864 else
anthony92c93bd2012-03-19 14:02:47 +00001865 compose=OverCompositeOp; /* use Over not _image->compose */
anthony5f867ae2011-10-09 10:28:34 +00001866
anthony92c93bd2012-03-19 14:02:47 +00001867 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001868 if ((flags & SigmaValue) == 0)
1869 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00001870 new_image=BorderImage(_image,&geometry,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00001871 break;
1872 }
anthonyafa3dfc2012-03-03 11:31:30 +00001873 if (LocaleCompare("brightness-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001874 {
1875 double
1876 brightness,
1877 contrast;
1878
1879 GeometryInfo
1880 geometry_info;
1881
1882 MagickStatusType
1883 flags;
1884
anthony5330ae02012-03-20 14:17:01 +00001885 if (IsGeometry(arg1) == MagickFalse)
1886 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001887 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001888 brightness=geometry_info.rho;
1889 contrast=0.0;
1890 if ((flags & SigmaValue) != 0)
1891 contrast=geometry_info.sigma;
anthony92c93bd2012-03-19 14:02:47 +00001892 (void) BrightnessContrastImage(_image,brightness,contrast,
1893 _exception);
anthony805a2d42011-09-25 08:25:12 +00001894 break;
1895 }
1896 break;
1897 }
1898 case 'c':
1899 {
anthonyafa3dfc2012-03-03 11:31:30 +00001900 if (LocaleCompare("cdl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001901 {
1902 char
1903 *color_correction_collection;
1904
1905 /*
1906 Color correct with a color decision list.
1907 */
anthony92c93bd2012-03-19 14:02:47 +00001908 color_correction_collection=FileToString(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00001909 if (color_correction_collection == (char *) NULL)
1910 break;
anthony92c93bd2012-03-19 14:02:47 +00001911 (void) ColorDecisionListImage(_image,color_correction_collection,
1912 _exception);
anthony805a2d42011-09-25 08:25:12 +00001913 break;
1914 }
anthonyafa3dfc2012-03-03 11:31:30 +00001915 if (LocaleCompare("channel",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001916 {
anthonyfd706f92012-01-19 04:22:02 +00001917 /* The "channel" setting has already been set
anthony24aa8822012-03-11 00:56:06 +00001918 FUTURE: This probably should be part of SyncImageSettings().
anthony5330ae02012-03-20 14:17:01 +00001919 How is it applied to new images?
anthony92c93bd2012-03-19 14:02:47 +00001920 SetPixelChannelMapMask(_image,_image_info->channel);
cristyddf87b62012-03-21 21:00:20 +00001921 */
anthony805a2d42011-09-25 08:25:12 +00001922 break;
1923 }
anthonyafa3dfc2012-03-03 11:31:30 +00001924 if (LocaleCompare("charcoal",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001925 {
anthony5330ae02012-03-20 14:17:01 +00001926 if (IsGeometry(arg1) == MagickFalse)
1927 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthonyfd706f92012-01-19 04:22:02 +00001928 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001929 if ((flags & SigmaValue) == 0)
1930 geometry_info.sigma=1.0;
1931 if ((flags & XiValue) == 0)
1932 geometry_info.xi=1.0;
anthony92c93bd2012-03-19 14:02:47 +00001933 new_image=CharcoalImage(_image,geometry_info.rho,
1934 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00001935 break;
1936 }
anthonyafa3dfc2012-03-03 11:31:30 +00001937 if (LocaleCompare("chop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001938 {
anthony5330ae02012-03-20 14:17:01 +00001939 if (IsGeometry(arg1) == MagickFalse)
1940 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00001941 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
1942 new_image=ChopImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00001943 break;
1944 }
anthonyafa3dfc2012-03-03 11:31:30 +00001945 if (LocaleCompare("clamp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001946 {
anthony92c93bd2012-03-19 14:02:47 +00001947 (void) ClampImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00001948 break;
1949 }
anthonyafa3dfc2012-03-03 11:31:30 +00001950 if (LocaleCompare("clip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001951 {
anthonyafa3dfc2012-03-03 11:31:30 +00001952 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00001953 (void) ClipImage(_image,_exception);
anthony43f425d2012-02-26 12:58:58 +00001954 else /* "+mask" remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001955 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00001956 break;
1957 }
anthonyafa3dfc2012-03-03 11:31:30 +00001958 if (LocaleCompare("clip-mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00001959 {
1960 CacheView
1961 *mask_view;
1962
1963 Image
1964 *mask_image;
1965
1966 register Quantum
1967 *restrict q;
1968
1969 register ssize_t
1970 x;
1971
1972 ssize_t
1973 y;
1974
anthonyafa3dfc2012-03-03 11:31:30 +00001975 if (IfPlusOp) {
1976 /* "+clip-mask" Remove the write mask */
anthony92c93bd2012-03-19 14:02:47 +00001977 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00001978 break;
1979 }
anthony92c93bd2012-03-19 14:02:47 +00001980 mask_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00001981 if (mask_image == (Image *) NULL)
1982 break;
anthony92c93bd2012-03-19 14:02:47 +00001983 if (SetImageStorageClass(mask_image,DirectClass,_exception)
anthonyfd706f92012-01-19 04:22:02 +00001984 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001985 break;
anthony5330ae02012-03-20 14:17:01 +00001986 /* Create a write mask from cli_wand mask image */
anthonyfd706f92012-01-19 04:22:02 +00001987 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00001988 mask_view=AcquireCacheView(mask_image);
1989 for (y=0; y < (ssize_t) mask_image->rows; y++)
1990 {
1991 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
anthony92c93bd2012-03-19 14:02:47 +00001992 _exception);
anthony805a2d42011-09-25 08:25:12 +00001993 if (q == (Quantum *) NULL)
1994 break;
1995 for (x=0; x < (ssize_t) mask_image->columns; x++)
1996 {
1997 if (mask_image->matte == MagickFalse)
1998 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1999 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
2000 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
2001 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
2002 q+=GetPixelChannels(mask_image);
2003 }
anthony92c93bd2012-03-19 14:02:47 +00002004 if (SyncCacheViewAuthenticPixels(mask_view,_exception) == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002005 break;
2006 }
anthonyfd706f92012-01-19 04:22:02 +00002007 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00002008 mask_view=DestroyCacheView(mask_view);
2009 mask_image->matte=MagickTrue;
anthony92c93bd2012-03-19 14:02:47 +00002010 (void) SetImageMask(_image,mask_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002011 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00002012 break;
2013 }
anthonyafa3dfc2012-03-03 11:31:30 +00002014 if (LocaleCompare("clip-path",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002015 {
anthony92c93bd2012-03-19 14:02:47 +00002016 (void) ClipImagePath(_image,arg1,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002017 break;
2018 }
anthonyafa3dfc2012-03-03 11:31:30 +00002019 if (LocaleCompare("colorize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002020 {
anthony5330ae02012-03-20 14:17:01 +00002021 if (IsGeometry(arg1) == MagickFalse)
2022 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002023 new_image=ColorizeImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00002024 break;
2025 }
anthonyafa3dfc2012-03-03 11:31:30 +00002026 if (LocaleCompare("color-matrix",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002027 {
2028 KernelInfo
2029 *kernel;
2030
anthonyfd706f92012-01-19 04:22:02 +00002031 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002032 if (kernel == (KernelInfo *) NULL)
anthony5330ae02012-03-20 14:17:01 +00002033 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002034 new_image=ColorMatrixImage(_image,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002035 kernel=DestroyKernelInfo(kernel);
2036 break;
2037 }
anthonyafa3dfc2012-03-03 11:31:30 +00002038 if (LocaleCompare("colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002039 {
anthony5330ae02012-03-20 14:17:01 +00002040 /* Reduce the number of colors in the image.
2041 FUTURE: also provide 'plus version with image 'color counts'
anthonyfd706f92012-01-19 04:22:02 +00002042 */
anthony92c93bd2012-03-19 14:02:47 +00002043 _quantize_info->number_colors=StringToUnsignedLong(arg1);
2044 if (_quantize_info->number_colors == 0)
anthony5330ae02012-03-20 14:17:01 +00002045 CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002046 if ((_image->storage_class == DirectClass) ||
2047 _image->colors > _quantize_info->number_colors)
2048 (void) QuantizeImage(_quantize_info,_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002049 else
anthony92c93bd2012-03-19 14:02:47 +00002050 (void) CompressImageColormap(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002051 break;
2052 }
anthonyafa3dfc2012-03-03 11:31:30 +00002053 if (LocaleCompare("colorspace",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002054 {
anthony5330ae02012-03-20 14:17:01 +00002055 /* WARNING: this is both a image_info setting (already done)
2056 and a operator to change image colorspace.
anthony31f1bf72012-01-30 12:37:22 +00002057
2058 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00002059 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00002060
anthonyd2cdc862011-10-07 14:07:17 +00002061 Note that +colorspace sets "undefined" or no effect on
2062 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00002063 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00002064 */
anthony92c93bd2012-03-19 14:02:47 +00002065 (void) TransformImageColorspace(_image,
2066 IfNormalOp ? _image_info->colorspace : RGBColorspace,
2067 _exception);
anthony805a2d42011-09-25 08:25:12 +00002068 break;
2069 }
anthonyafa3dfc2012-03-03 11:31:30 +00002070 if (LocaleCompare("contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002071 {
anthony92c93bd2012-03-19 14:02:47 +00002072 (void) ContrastImage(_image,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002073 break;
2074 }
anthonyafa3dfc2012-03-03 11:31:30 +00002075 if (LocaleCompare("contrast-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002076 {
2077 double
2078 black_point,
2079 white_point;
2080
2081 MagickStatusType
2082 flags;
2083
anthonyfd706f92012-01-19 04:22:02 +00002084 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002085 black_point=geometry_info.rho;
2086 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2087 black_point;
2088 if ((flags & PercentValue) != 0)
2089 {
anthony92c93bd2012-03-19 14:02:47 +00002090 black_point*=(double) _image->columns*_image->rows/100.0;
2091 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002092 }
anthony92c93bd2012-03-19 14:02:47 +00002093 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002094 white_point;
anthony92c93bd2012-03-19 14:02:47 +00002095 (void) ContrastStretchImage(_image,black_point,white_point,
2096 _exception);
anthony805a2d42011-09-25 08:25:12 +00002097 break;
2098 }
anthonyafa3dfc2012-03-03 11:31:30 +00002099 if (LocaleCompare("convolve",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002100 {
2101 KernelInfo
2102 *kernel_info;
2103
anthonyfd706f92012-01-19 04:22:02 +00002104 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002105 if (kernel_info == (KernelInfo *) NULL)
2106 break;
anthony92c93bd2012-03-19 14:02:47 +00002107 kernel_info->bias=_image->bias;
2108 new_image=ConvolveImage(_image,kernel_info,_exception);
anthony805a2d42011-09-25 08:25:12 +00002109 kernel_info=DestroyKernelInfo(kernel_info);
2110 break;
2111 }
anthonyafa3dfc2012-03-03 11:31:30 +00002112 if (LocaleCompare("crop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002113 {
anthony31f1bf72012-01-30 12:37:22 +00002114 /* WARNING: This can generate multiple images! */
anthony92c93bd2012-03-19 14:02:47 +00002115 new_image=CropImageToTiles(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002116 break;
2117 }
anthonyafa3dfc2012-03-03 11:31:30 +00002118 if (LocaleCompare("cycle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002119 {
anthony92c93bd2012-03-19 14:02:47 +00002120 (void) CycleColormapImage(_image,(ssize_t) StringToLong(arg1),
2121 _exception);
anthony805a2d42011-09-25 08:25:12 +00002122 break;
2123 }
2124 break;
2125 }
2126 case 'd':
2127 {
anthonyafa3dfc2012-03-03 11:31:30 +00002128 if (LocaleCompare("decipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002129 {
2130 StringInfo
2131 *passkey;
2132
anthony92c93bd2012-03-19 14:02:47 +00002133 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002134 if (passkey != (StringInfo *) NULL)
2135 {
anthony92c93bd2012-03-19 14:02:47 +00002136 (void) PasskeyDecipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002137 passkey=DestroyStringInfo(passkey);
2138 }
2139 break;
2140 }
anthonyafa3dfc2012-03-03 11:31:30 +00002141 if (LocaleCompare("depth",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002142 {
anthony92c93bd2012-03-19 14:02:47 +00002143 /* The _image_info->depth setting has already been set
anthonydcf510d2011-10-30 13:51:40 +00002144 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002145
anthonydcf510d2011-10-30 13:51:40 +00002146 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2147 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002148
anthonyfd706f92012-01-19 04:22:02 +00002149 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002150 */
anthony92c93bd2012-03-19 14:02:47 +00002151 (void) SetImageDepth(_image,_image_info->depth,_exception);
anthony805a2d42011-09-25 08:25:12 +00002152 break;
2153 }
anthonyafa3dfc2012-03-03 11:31:30 +00002154 if (LocaleCompare("deskew",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002155 {
2156 double
2157 threshold;
2158
anthonyafa3dfc2012-03-03 11:31:30 +00002159 if (IfNormalOp)
anthonyfd706f92012-01-19 04:22:02 +00002160 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthonyafa3dfc2012-03-03 11:31:30 +00002161 else
2162 threshold=40.0*QuantumRange/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002163 new_image=DeskewImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00002164 break;
2165 }
anthonyafa3dfc2012-03-03 11:31:30 +00002166 if (LocaleCompare("despeckle",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002167 {
anthony92c93bd2012-03-19 14:02:47 +00002168 new_image=DespeckleImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002169 break;
2170 }
anthonyafa3dfc2012-03-03 11:31:30 +00002171 if (LocaleCompare("distort",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002172 {
2173 char
2174 *args,
2175 token[MaxTextExtent];
2176
2177 const char
2178 *p;
2179
2180 DistortImageMethod
2181 method;
2182
2183 double
2184 *arguments;
2185
2186 register ssize_t
2187 x;
2188
2189 size_t
2190 number_arguments;
2191
anthony805a2d42011-09-25 08:25:12 +00002192 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
anthonyfd706f92012-01-19 04:22:02 +00002193 MagickFalse,arg1);
anthony80c37752012-01-16 01:03:11 +00002194 if (method == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002195 {
anthony80c37752012-01-16 01:03:11 +00002196 double
2197 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002198 /* Special Case - Argument is actually a resize geometry!
2199 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002200 ** FUTURE: make a separate special resize operator
anthony805a2d42011-09-25 08:25:12 +00002201 */
anthony92c93bd2012-03-19 14:02:47 +00002202 (void) ParseRegionGeometry(_image,arg2,&geometry,
2203 _exception);
anthony80c37752012-01-16 01:03:11 +00002204 resize_args[0]=(double) geometry.width;
2205 resize_args[1]=(double) geometry.height;
anthony92c93bd2012-03-19 14:02:47 +00002206 new_image=DistortImage(_image,method,(size_t)2,
2207 resize_args,MagickTrue,_exception);
anthony805a2d42011-09-25 08:25:12 +00002208 break;
2209 }
anthonyfd706f92012-01-19 04:22:02 +00002210 /* handle percent arguments */
anthony92c93bd2012-03-19 14:02:47 +00002211 args=InterpretImageProperties(_image_info,_image,arg2,
2212 _exception);
anthony805a2d42011-09-25 08:25:12 +00002213 if (args == (char *) NULL)
2214 break;
anthonyfd706f92012-01-19 04:22:02 +00002215 /* convert arguments into an array of doubles
2216 FUTURE: make this a separate function.
2217 Also make use of new 'sentinal' feature to avoid need for
2218 tokenization.
2219 */
anthony805a2d42011-09-25 08:25:12 +00002220 p=(char *) args;
2221 for (x=0; *p != '\0'; x++)
2222 {
2223 GetMagickToken(p,&p,token);
2224 if (*token == ',')
2225 GetMagickToken(p,&p,token);
2226 }
2227 number_arguments=(size_t) x;
2228 arguments=(double *) AcquireQuantumMemory(number_arguments,
2229 sizeof(*arguments));
2230 if (arguments == (double *) NULL)
2231 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002232 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002233 (void) ResetMagickMemory(arguments,0,number_arguments*
2234 sizeof(*arguments));
2235 p=(char *) args;
2236 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2237 {
2238 GetMagickToken(p,&p,token);
2239 if (*token == ',')
2240 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002241 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002242 }
2243 args=DestroyString(args);
anthony92c93bd2012-03-19 14:02:47 +00002244 new_image=DistortImage(_image,method,number_arguments,arguments,
2245 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002246 arguments=(double *) RelinquishMagickMemory(arguments);
2247 break;
2248 }
anthonyafa3dfc2012-03-03 11:31:30 +00002249 if (LocaleCompare("draw",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002250 {
anthony92c93bd2012-03-19 14:02:47 +00002251 (void) CloneString(&_draw_info->primitive,arg1);
2252 (void) DrawImage(_image,_draw_info,_exception);
2253 (void) CloneString(&_draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002254 break;
2255 }
2256 break;
2257 }
2258 case 'e':
2259 {
anthonyafa3dfc2012-03-03 11:31:30 +00002260 if (LocaleCompare("edge",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002261 {
anthonyfd706f92012-01-19 04:22:02 +00002262 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002263 if ((flags & SigmaValue) == 0)
2264 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002265 new_image=EdgeImage(_image,geometry_info.rho,
2266 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002267 break;
2268 }
anthonyafa3dfc2012-03-03 11:31:30 +00002269 if (LocaleCompare("emboss",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002270 {
anthonyfd706f92012-01-19 04:22:02 +00002271 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002272 if ((flags & SigmaValue) == 0)
2273 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002274 new_image=EmbossImage(_image,geometry_info.rho,
2275 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002276 break;
2277 }
anthonyafa3dfc2012-03-03 11:31:30 +00002278 if (LocaleCompare("encipher",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002279 {
2280 StringInfo
2281 *passkey;
2282
anthony92c93bd2012-03-19 14:02:47 +00002283 passkey=FileToStringInfo(arg1,~0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002284 if (passkey != (StringInfo *) NULL)
2285 {
anthony92c93bd2012-03-19 14:02:47 +00002286 (void) PasskeyEncipherImage(_image,passkey,_exception);
anthony805a2d42011-09-25 08:25:12 +00002287 passkey=DestroyStringInfo(passkey);
2288 }
2289 break;
2290 }
anthonyafa3dfc2012-03-03 11:31:30 +00002291 if (LocaleCompare("enhance",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002292 {
anthony92c93bd2012-03-19 14:02:47 +00002293 new_image=EnhanceImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002294 break;
2295 }
anthonyafa3dfc2012-03-03 11:31:30 +00002296 if (LocaleCompare("equalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002297 {
anthony92c93bd2012-03-19 14:02:47 +00002298 (void) EqualizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002299 break;
2300 }
anthonyafa3dfc2012-03-03 11:31:30 +00002301 if (LocaleCompare("evaluate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002302 {
2303 double
2304 constant;
2305
2306 MagickEvaluateOperator
2307 op;
2308
anthony805a2d42011-09-25 08:25:12 +00002309 op=(MagickEvaluateOperator) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00002310 MagickEvaluateOptions,MagickFalse,arg1);
2311 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00002312 (void) EvaluateImage(_image,op,constant,_exception);
anthony805a2d42011-09-25 08:25:12 +00002313 break;
2314 }
anthonyafa3dfc2012-03-03 11:31:30 +00002315 if (LocaleCompare("extent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002316 {
anthony92c93bd2012-03-19 14:02:47 +00002317 flags=ParseGravityGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002318 if (geometry.width == 0)
anthony92c93bd2012-03-19 14:02:47 +00002319 geometry.width=_image->columns;
anthony805a2d42011-09-25 08:25:12 +00002320 if (geometry.height == 0)
anthony92c93bd2012-03-19 14:02:47 +00002321 geometry.height=_image->rows;
2322 new_image=ExtentImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002323 break;
2324 }
2325 break;
2326 }
2327 case 'f':
2328 {
anthonyafa3dfc2012-03-03 11:31:30 +00002329 if (LocaleCompare("features",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002330 {
anthony31f1bf72012-01-30 12:37:22 +00002331 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthonyafa3dfc2012-03-03 11:31:30 +00002332 if (IfPlusOp) {
anthony92c93bd2012-03-19 14:02:47 +00002333 (void) DeleteImageArtifact(_image,"identify:features");
anthony31f1bf72012-01-30 12:37:22 +00002334 break;
2335 }
anthony92c93bd2012-03-19 14:02:47 +00002336 (void) SetImageArtifact(_image,"identify:features","true");
2337 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002338 break;
2339 }
anthonyafa3dfc2012-03-03 11:31:30 +00002340 if (LocaleCompare("flip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002341 {
anthony92c93bd2012-03-19 14:02:47 +00002342 new_image=FlipImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002343 break;
2344 }
anthonyafa3dfc2012-03-03 11:31:30 +00002345 if (LocaleCompare("flop",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002346 {
anthony92c93bd2012-03-19 14:02:47 +00002347 new_image=FlopImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002348 break;
2349 }
anthonyafa3dfc2012-03-03 11:31:30 +00002350 if (LocaleCompare("floodfill",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002351 {
2352 PixelInfo
2353 target;
2354
anthony92c93bd2012-03-19 14:02:47 +00002355 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
2356 (void) QueryColorCompliance(arg2,AllCompliance,&target,_exception);
2357 (void) FloodfillPaintImage(_image,_draw_info,&target,geometry.x,
2358 geometry.y,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002359 break;
2360 }
anthonyafa3dfc2012-03-03 11:31:30 +00002361 if (LocaleCompare("frame",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002362 {
2363 FrameInfo
2364 frame_info;
2365
anthony31f1bf72012-01-30 12:37:22 +00002366 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002367 compose;
2368
2369 const char*
2370 value;
2371
anthony92c93bd2012-03-19 14:02:47 +00002372 value=GetImageOption(_image_info,"compose");
anthonyfd706f92012-01-19 04:22:02 +00002373 if (value != (const char *) NULL)
2374 compose=(CompositeOperator) ParseCommandOption(
2375 MagickComposeOptions,MagickFalse,value);
2376 else
anthony92c93bd2012-03-19 14:02:47 +00002377 compose=OverCompositeOp; /* use Over not _image->compose */
anthonyfd706f92012-01-19 04:22:02 +00002378
anthony92c93bd2012-03-19 14:02:47 +00002379 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002380 frame_info.width=geometry.width;
2381 frame_info.height=geometry.height;
2382 if ((flags & HeightValue) == 0)
2383 frame_info.height=geometry.width;
2384 frame_info.outer_bevel=geometry.x;
2385 frame_info.inner_bevel=geometry.y;
2386 frame_info.x=(ssize_t) frame_info.width;
2387 frame_info.y=(ssize_t) frame_info.height;
anthony92c93bd2012-03-19 14:02:47 +00002388 frame_info.width=_image->columns+2*frame_info.width;
2389 frame_info.height=_image->rows+2*frame_info.height;
2390 new_image=FrameImage(_image,&frame_info,compose,_exception);
anthony805a2d42011-09-25 08:25:12 +00002391 break;
2392 }
anthonyafa3dfc2012-03-03 11:31:30 +00002393 if (LocaleCompare("function",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002394 {
2395 char
2396 *arguments,
2397 token[MaxTextExtent];
2398
2399 const char
2400 *p;
2401
2402 double
2403 *parameters;
2404
2405 MagickFunction
2406 function;
2407
2408 register ssize_t
2409 x;
2410
2411 size_t
2412 number_parameters;
2413
cristy947cb4c2011-10-20 18:41:46 +00002414 /*
2415 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002416 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002417 */
anthony805a2d42011-09-25 08:25:12 +00002418 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
anthonyfd706f92012-01-19 04:22:02 +00002419 MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002420 arguments=InterpretImageProperties(_image_info,_image,arg2,
2421 _exception);
anthony805a2d42011-09-25 08:25:12 +00002422 if (arguments == (char *) NULL)
2423 break;
2424 p=(char *) arguments;
2425 for (x=0; *p != '\0'; x++)
2426 {
2427 GetMagickToken(p,&p,token);
2428 if (*token == ',')
2429 GetMagickToken(p,&p,token);
2430 }
2431 number_parameters=(size_t) x;
2432 parameters=(double *) AcquireQuantumMemory(number_parameters,
2433 sizeof(*parameters));
2434 if (parameters == (double *) NULL)
2435 ThrowWandFatalException(ResourceLimitFatalError,
anthony92c93bd2012-03-19 14:02:47 +00002436 "MemoryAllocationFailed",_image->filename);
anthony805a2d42011-09-25 08:25:12 +00002437 (void) ResetMagickMemory(parameters,0,number_parameters*
2438 sizeof(*parameters));
2439 p=(char *) arguments;
2440 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2441 {
2442 GetMagickToken(p,&p,token);
2443 if (*token == ',')
2444 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002445 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002446 }
2447 arguments=DestroyString(arguments);
anthony92c93bd2012-03-19 14:02:47 +00002448 (void) FunctionImage(_image,function,number_parameters,parameters,
2449 _exception);
anthony805a2d42011-09-25 08:25:12 +00002450 parameters=(double *) RelinquishMagickMemory(parameters);
2451 break;
2452 }
2453 break;
2454 }
2455 case 'g':
2456 {
anthonyafa3dfc2012-03-03 11:31:30 +00002457 if (LocaleCompare("gamma",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002458 {
anthonyafa3dfc2012-03-03 11:31:30 +00002459 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00002460 (void) GammaImage(_image,StringToDouble(arg1,(char **) NULL),
2461 _exception);
anthonyafa3dfc2012-03-03 11:31:30 +00002462 else
anthony92c93bd2012-03-19 14:02:47 +00002463 _image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002464 break;
2465 }
anthonyafa3dfc2012-03-03 11:31:30 +00002466 if ((LocaleCompare("gaussian-blur",option+1) == 0) ||
2467 (LocaleCompare("gaussian",option+1) == 0))
anthony805a2d42011-09-25 08:25:12 +00002468 {
anthonyfd706f92012-01-19 04:22:02 +00002469 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002470 if ((flags & SigmaValue) == 0)
2471 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002472 new_image=GaussianBlurImage(_image,geometry_info.rho,
2473 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002474 break;
2475 }
anthonyafa3dfc2012-03-03 11:31:30 +00002476 if (LocaleCompare("geometry",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002477 {
anthonyfd706f92012-01-19 04:22:02 +00002478 /*
anthony31f1bf72012-01-30 12:37:22 +00002479 Record Image offset for composition. (A Setting)
anthony92c93bd2012-03-19 14:02:47 +00002480 Resize last _image. (ListOperator)
anthony31f1bf72012-01-30 12:37:22 +00002481 FUTURE: Why if no 'offset' does this resize ALL images?
2482 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002483 */
anthonyafa3dfc2012-03-03 11:31:30 +00002484 if (IfPlusOp)
anthonyfd706f92012-01-19 04:22:02 +00002485 { /* remove the previous composition geometry offset! */
anthony92c93bd2012-03-19 14:02:47 +00002486 if (_image->geometry != (char *) NULL)
2487 _image->geometry=DestroyString(_image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002488 break;
2489 }
anthony92c93bd2012-03-19 14:02:47 +00002490 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002491 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002492 (void) CloneString(&_image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002493 else
anthony92c93bd2012-03-19 14:02:47 +00002494 new_image=ResizeImage(_image,geometry.width,geometry.height,
2495 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00002496 break;
2497 }
anthony805a2d42011-09-25 08:25:12 +00002498 break;
2499 }
2500 case 'h':
2501 {
anthonyafa3dfc2012-03-03 11:31:30 +00002502 if (LocaleCompare("highlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002503 {
anthony92c93bd2012-03-19 14:02:47 +00002504 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002505 break;
2506 }
2507 break;
2508 }
2509 case 'i':
2510 {
anthonyafa3dfc2012-03-03 11:31:30 +00002511 if (LocaleCompare("identify",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002512 {
anthony31f1bf72012-01-30 12:37:22 +00002513 const char
2514 *format,
anthony805a2d42011-09-25 08:25:12 +00002515 *text;
2516
anthony92c93bd2012-03-19 14:02:47 +00002517 format=GetImageOption(_image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002518 if (format == (char *) NULL)
2519 {
anthony92c93bd2012-03-19 14:02:47 +00002520 (void) IdentifyImage(_image,stdout,_image_info->verbose,
2521 _exception);
anthony805a2d42011-09-25 08:25:12 +00002522 break;
2523 }
anthony92c93bd2012-03-19 14:02:47 +00002524 text=InterpretImageProperties(_image_info,_image,format,_exception);
anthony805a2d42011-09-25 08:25:12 +00002525 if (text == (char *) NULL)
2526 break;
2527 (void) fputs(text,stdout);
2528 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002529 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002530 break;
2531 }
anthonyafa3dfc2012-03-03 11:31:30 +00002532 if (LocaleCompare("implode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002533 {
anthonyfd706f92012-01-19 04:22:02 +00002534 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002535 new_image=ImplodeImage(_image,geometry_info.rho,
2536 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002537 break;
2538 }
anthonyafa3dfc2012-03-03 11:31:30 +00002539 if (LocaleCompare("interpolative-resize",option+1) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002540 {
anthony92c93bd2012-03-19 14:02:47 +00002541 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
2542 new_image=InterpolativeResizeImage(_image,geometry.width,
2543 geometry.height,_image->interpolate,_exception);
cristy947cb4c2011-10-20 18:41:46 +00002544 break;
2545 }
anthony805a2d42011-09-25 08:25:12 +00002546 break;
2547 }
2548 case 'l':
2549 {
anthonyafa3dfc2012-03-03 11:31:30 +00002550 if (LocaleCompare("lat",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002551 {
anthonyfd706f92012-01-19 04:22:02 +00002552 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002553 if ((flags & PercentValue) != 0)
2554 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00002555 new_image=AdaptiveThresholdImage(_image,(size_t) geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002556 (size_t) geometry_info.sigma,(double) geometry_info.xi,
anthony92c93bd2012-03-19 14:02:47 +00002557 _exception);
anthony805a2d42011-09-25 08:25:12 +00002558 break;
2559 }
anthonyafa3dfc2012-03-03 11:31:30 +00002560 if (LocaleCompare("level",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002561 {
2562 MagickRealType
2563 black_point,
2564 gamma,
2565 white_point;
2566
2567 MagickStatusType
2568 flags;
2569
anthonyfd706f92012-01-19 04:22:02 +00002570 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002571 black_point=geometry_info.rho;
2572 white_point=(MagickRealType) QuantumRange;
2573 if ((flags & SigmaValue) != 0)
2574 white_point=geometry_info.sigma;
2575 gamma=1.0;
2576 if ((flags & XiValue) != 0)
2577 gamma=geometry_info.xi;
2578 if ((flags & PercentValue) != 0)
2579 {
2580 black_point*=(MagickRealType) (QuantumRange/100.0);
2581 white_point*=(MagickRealType) (QuantumRange/100.0);
2582 }
2583 if ((flags & SigmaValue) == 0)
2584 white_point=(MagickRealType) QuantumRange-black_point;
anthonyafa3dfc2012-03-03 11:31:30 +00002585 if (IfPlusOp || ((flags & AspectValue) != 0))
anthony92c93bd2012-03-19 14:02:47 +00002586 (void) LevelizeImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002587 else
anthony92c93bd2012-03-19 14:02:47 +00002588 (void) LevelImage(_image,black_point,white_point,gamma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002589 break;
2590 }
anthonyafa3dfc2012-03-03 11:31:30 +00002591 if (LocaleCompare("level-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002592 {
2593 char
2594 token[MaxTextExtent];
2595
2596 const char
2597 *p;
2598
2599 PixelInfo
2600 black_point,
2601 white_point;
2602
anthonyfd706f92012-01-19 04:22:02 +00002603 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002604 GetMagickToken(p,&p,token); /* get black point color */
2605 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002606 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002607 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002608 else
cristy269c9412011-10-13 23:41:15 +00002609 (void) QueryColorCompliance("#000000",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002610 &black_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002611 if (isalpha((int) token[0]) || (token[0] == '#'))
2612 GetMagickToken(p,&p,token);
2613 if (*token == '\0')
2614 white_point=black_point; /* set everything to that color */
2615 else
2616 {
2617 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2618 GetMagickToken(p,&p,token); /* Get white point color. */
2619 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002620 (void) QueryColorCompliance(token,AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002621 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002622 else
cristy269c9412011-10-13 23:41:15 +00002623 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthony92c93bd2012-03-19 14:02:47 +00002624 &white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002625 }
anthony92c93bd2012-03-19 14:02:47 +00002626 (void) LevelImageColors(_image,&black_point,&white_point,
2627 plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002628 break;
2629 }
anthonyafa3dfc2012-03-03 11:31:30 +00002630 if (LocaleCompare("linear-stretch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002631 {
2632 double
2633 black_point,
2634 white_point;
2635
2636 MagickStatusType
2637 flags;
2638
anthonyfd706f92012-01-19 04:22:02 +00002639 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002640 black_point=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002641 white_point=(MagickRealType) _image->columns*_image->rows;
anthony805a2d42011-09-25 08:25:12 +00002642 if ((flags & SigmaValue) != 0)
2643 white_point=geometry_info.sigma;
2644 if ((flags & PercentValue) != 0)
2645 {
anthony92c93bd2012-03-19 14:02:47 +00002646 black_point*=(double) _image->columns*_image->rows/100.0;
2647 white_point*=(double) _image->columns*_image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002648 }
2649 if ((flags & SigmaValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00002650 white_point=(MagickRealType) _image->columns*_image->rows-
anthony805a2d42011-09-25 08:25:12 +00002651 black_point;
anthony92c93bd2012-03-19 14:02:47 +00002652 (void) LinearStretchImage(_image,black_point,white_point,_exception);
anthony805a2d42011-09-25 08:25:12 +00002653 break;
2654 }
anthonyafa3dfc2012-03-03 11:31:30 +00002655 if (LocaleCompare("liquid-rescale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002656 {
anthony92c93bd2012-03-19 14:02:47 +00002657 flags=ParseRegionGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002658 if ((flags & XValue) == 0)
2659 geometry.x=1;
2660 if ((flags & YValue) == 0)
2661 geometry.y=0;
anthony92c93bd2012-03-19 14:02:47 +00002662 new_image=LiquidRescaleImage(_image,geometry.width,
2663 geometry.height,1.0*geometry.x,1.0*geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00002664 break;
2665 }
anthonyafa3dfc2012-03-03 11:31:30 +00002666 if (LocaleCompare("lowlight-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002667 {
anthony92c93bd2012-03-19 14:02:47 +00002668 (void) SetImageArtifact(_image,option+1,arg1);
anthony805a2d42011-09-25 08:25:12 +00002669 break;
2670 }
2671 break;
2672 }
2673 case 'm':
2674 {
anthonyafa3dfc2012-03-03 11:31:30 +00002675 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002676 {
2677 Image
2678 *remap_image;
2679
anthony31f1bf72012-01-30 12:37:22 +00002680 /* DEPRECIATED use -remap */
anthony92c93bd2012-03-19 14:02:47 +00002681 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002682 if (remap_image == (Image *) NULL)
2683 break;
anthony92c93bd2012-03-19 14:02:47 +00002684 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002685 remap_image=DestroyImage(remap_image);
2686 break;
2687 }
anthonyafa3dfc2012-03-03 11:31:30 +00002688 if (LocaleCompare("mask",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002689 {
2690 Image
2691 *mask;
2692
anthonyafa3dfc2012-03-03 11:31:30 +00002693 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002694 { /* Remove a mask. */
anthony92c93bd2012-03-19 14:02:47 +00002695 (void) SetImageMask(_image,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002696 break;
2697 }
anthony5330ae02012-03-20 14:17:01 +00002698 /* Set the image mask. */
anthony92c93bd2012-03-19 14:02:47 +00002699 mask=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002700 if (mask == (Image *) NULL)
2701 break;
anthony92c93bd2012-03-19 14:02:47 +00002702 (void) SetImageMask(_image,mask,_exception);
anthony805a2d42011-09-25 08:25:12 +00002703 mask=DestroyImage(mask);
2704 break;
2705 }
anthonyafa3dfc2012-03-03 11:31:30 +00002706 if (LocaleCompare("matte",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002707 {
anthony31f1bf72012-01-30 12:37:22 +00002708 /* DEPRECIATED */
anthony92c93bd2012-03-19 14:02:47 +00002709 (void) SetImageAlphaChannel(_image,IfNormalOp ? SetAlphaChannel :
2710 DeactivateAlphaChannel, _exception);
anthony805a2d42011-09-25 08:25:12 +00002711 break;
2712 }
anthonya3ef4ed2012-03-17 06:52:53 +00002713 if (LocaleCompare("median",option+1) == 0)
2714 {
2715 /* DEPRECIATED - use -statistic Median */
2716 CLISimpleOperatorImage(cli_wand,"-statistic","Median",arg1);
2717 break;
2718 }
anthonyafa3dfc2012-03-03 11:31:30 +00002719 if (LocaleCompare("mode",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002720 {
anthonyfd706f92012-01-19 04:22:02 +00002721 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002722 if ((flags & SigmaValue) == 0)
2723 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002724 new_image=StatisticImage(_image,ModeStatistic,(size_t)
2725 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002726 break;
2727 }
anthonyafa3dfc2012-03-03 11:31:30 +00002728 if (LocaleCompare("modulate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002729 {
anthony92c93bd2012-03-19 14:02:47 +00002730 (void) ModulateImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002731 break;
2732 }
anthonyafa3dfc2012-03-03 11:31:30 +00002733 if (LocaleCompare("monitor",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002734 {
anthony92c93bd2012-03-19 14:02:47 +00002735 (void) SetImageProgressMonitor(_image, IfNormalOp ? MonitorProgress :
anthonyafa3dfc2012-03-03 11:31:30 +00002736 (MagickProgressMonitor) NULL,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002737 break;
2738 }
anthonyafa3dfc2012-03-03 11:31:30 +00002739 if (LocaleCompare("monochrome",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002740 {
anthony92c93bd2012-03-19 14:02:47 +00002741 (void) SetImageType(_image,BilevelType,_exception);
anthony805a2d42011-09-25 08:25:12 +00002742 break;
2743 }
anthonyafa3dfc2012-03-03 11:31:30 +00002744 if (LocaleCompare("morphology",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002745 {
2746 char
2747 token[MaxTextExtent];
2748
2749 const char
2750 *p;
2751
2752 KernelInfo
2753 *kernel;
2754
2755 MorphologyMethod
2756 method;
2757
2758 ssize_t
2759 iterations;
2760
anthonyfd706f92012-01-19 04:22:02 +00002761 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002762 GetMagickToken(p,&p,token);
2763 method=(MorphologyMethod) ParseCommandOption(
2764 MagickMorphologyOptions,MagickFalse,token);
2765 iterations=1L;
2766 GetMagickToken(p,&p,token);
2767 if ((*p == ':') || (*p == ','))
2768 GetMagickToken(p,&p,token);
2769 if ((*p != '\0'))
2770 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002771 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002772 if (kernel == (KernelInfo *) NULL)
2773 {
anthony92c93bd2012-03-19 14:02:47 +00002774 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00002775 OptionError,"UnabletoParseKernel","morphology");
anthony805a2d42011-09-25 08:25:12 +00002776 break;
2777 }
anthony92c93bd2012-03-19 14:02:47 +00002778 new_image=MorphologyImage(_image,method,iterations,kernel,_exception);
anthony805a2d42011-09-25 08:25:12 +00002779 kernel=DestroyKernelInfo(kernel);
2780 break;
2781 }
anthonyafa3dfc2012-03-03 11:31:30 +00002782 if (LocaleCompare("motion-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002783 {
anthonyfd706f92012-01-19 04:22:02 +00002784 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002785 if ((flags & SigmaValue) == 0)
2786 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00002787 new_image=MotionBlurImage(_image,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00002788 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
anthony92c93bd2012-03-19 14:02:47 +00002789 _exception);
anthony805a2d42011-09-25 08:25:12 +00002790 break;
2791 }
2792 break;
2793 }
2794 case 'n':
2795 {
anthonyafa3dfc2012-03-03 11:31:30 +00002796 if (LocaleCompare("negate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002797 {
anthony92c93bd2012-03-19 14:02:47 +00002798 (void) NegateImage(_image, plus_alt_op, _exception);
anthony805a2d42011-09-25 08:25:12 +00002799 break;
2800 }
anthonyafa3dfc2012-03-03 11:31:30 +00002801 if (LocaleCompare("noise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002802 {
anthonyafa3dfc2012-03-03 11:31:30 +00002803 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00002804 {
anthonyfd706f92012-01-19 04:22:02 +00002805 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002806 if ((flags & SigmaValue) == 0)
2807 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00002808 new_image=StatisticImage(_image,NonpeakStatistic,(size_t)
2809 geometry_info.rho,(size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002810 }
2811 else
2812 {
2813 NoiseType
2814 noise;
2815
anthony31f1bf72012-01-30 12:37:22 +00002816 double
2817 attenuate;
2818
2819 const char*
2820 value;
2821
anthony805a2d42011-09-25 08:25:12 +00002822 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
anthony31f1bf72012-01-30 12:37:22 +00002823 MagickFalse,arg1),
2824
anthony92c93bd2012-03-19 14:02:47 +00002825 value=GetImageOption(_image_info,"attenuate");
anthony31f1bf72012-01-30 12:37:22 +00002826 if (value != (const char *) NULL)
2827 attenuate=StringToDouble(value,(char **) NULL);
2828 else
2829 attenuate=1.0;
2830
anthony92c93bd2012-03-19 14:02:47 +00002831 new_image=AddNoiseImage(_image,noise,attenuate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002832 }
2833 break;
2834 }
anthonyafa3dfc2012-03-03 11:31:30 +00002835 if (LocaleCompare("normalize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002836 {
anthony92c93bd2012-03-19 14:02:47 +00002837 (void) NormalizeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00002838 break;
2839 }
2840 break;
2841 }
2842 case 'o':
2843 {
anthonyafa3dfc2012-03-03 11:31:30 +00002844 if (LocaleCompare("opaque",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002845 {
2846 PixelInfo
2847 target;
2848
anthony92c93bd2012-03-19 14:02:47 +00002849 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
2850 (void) OpaquePaintImage(_image,&target,&_draw_info->fill,plus_alt_op,
2851 _exception);
anthony805a2d42011-09-25 08:25:12 +00002852 break;
2853 }
anthonyafa3dfc2012-03-03 11:31:30 +00002854 if (LocaleCompare("ordered-dither",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002855 {
anthony92c93bd2012-03-19 14:02:47 +00002856 (void) OrderedPosterizeImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002857 break;
2858 }
2859 break;
2860 }
2861 case 'p':
2862 {
anthonyafa3dfc2012-03-03 11:31:30 +00002863 if (LocaleCompare("paint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002864 {
anthonyfd706f92012-01-19 04:22:02 +00002865 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002866 new_image=OilPaintImage(_image,geometry_info.rho,geometry_info.sigma,
2867 _exception);
anthony805a2d42011-09-25 08:25:12 +00002868 break;
2869 }
anthonyafa3dfc2012-03-03 11:31:30 +00002870 if (LocaleCompare("polaroid",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002871 {
cristye9e3d382011-12-14 01:50:13 +00002872 const char
2873 *caption;
2874
anthony805a2d42011-09-25 08:25:12 +00002875 double
2876 angle;
2877
anthonyafa3dfc2012-03-03 11:31:30 +00002878 if (IfPlusOp)
anthony31f1bf72012-01-30 12:37:22 +00002879 {
2880 RandomInfo
2881 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002882
anthony31f1bf72012-01-30 12:37:22 +00002883 random_info=AcquireRandomInfo();
2884 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2885 random_info=DestroyRandomInfo(random_info);
2886 }
2887 else
anthony805a2d42011-09-25 08:25:12 +00002888 {
2889 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00002890 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002891 angle=geometry_info.rho;
2892 }
anthony92c93bd2012-03-19 14:02:47 +00002893 caption=GetImageProperty(_image,"caption",_exception);
2894 new_image=PolaroidImage(_image,_draw_info,caption,angle,
2895 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00002896 break;
2897 }
anthonyafa3dfc2012-03-03 11:31:30 +00002898 if (LocaleCompare("posterize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002899 {
anthony31f1bf72012-01-30 12:37:22 +00002900 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002901 (void) PosterizeImage(_image,(size_t) geometry_info.rho,
2902 _quantize_info->dither,_exception);
anthony805a2d42011-09-25 08:25:12 +00002903 break;
2904 }
anthonyafa3dfc2012-03-03 11:31:30 +00002905 if (LocaleCompare("preview",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002906 {
2907 PreviewType
cristy947cb4c2011-10-20 18:41:46 +00002908 preview_type;
anthony170fce92011-10-20 11:50:23 +00002909
anthony31f1bf72012-01-30 12:37:22 +00002910 /* FUTURE: should be a 'Genesis' option?
2911 Option however is also in WandSettingOptionInfo()
cristy947cb4c2011-10-20 18:41:46 +00002912 */
anthony31f1bf72012-01-30 12:37:22 +00002913 preview_type=UndefinedPreview;
anthonyafa3dfc2012-03-03 11:31:30 +00002914 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00002915 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2916 MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00002917 new_image=PreviewImage(_image,preview_type,_exception);
anthony805a2d42011-09-25 08:25:12 +00002918 break;
2919 }
anthonyafa3dfc2012-03-03 11:31:30 +00002920 if (LocaleCompare("profile",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002921 {
2922 const char
2923 *name;
2924
2925 const StringInfo
2926 *profile;
2927
2928 Image
2929 *profile_image;
2930
2931 ImageInfo
2932 *profile_info;
2933
anthonyafa3dfc2012-03-03 11:31:30 +00002934 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00002935 { /* Remove a profile from the _image. */
2936 (void) ProfileImage(_image,arg1,(const unsigned char *)
2937 NULL,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00002938 break;
2939 }
anthony92c93bd2012-03-19 14:02:47 +00002940 /* Associate a profile with the _image. */
2941 profile_info=CloneImageInfo(_image_info);
2942 profile=GetImageProfile(_image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002943 if (profile != (StringInfo *) NULL)
2944 profile_info->profile=(void *) CloneStringInfo(profile);
anthony92c93bd2012-03-19 14:02:47 +00002945 profile_image=GetImageCache(profile_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00002946 profile_info=DestroyImageInfo(profile_info);
2947 if (profile_image == (Image *) NULL)
2948 {
2949 StringInfo
2950 *profile;
2951
anthony92c93bd2012-03-19 14:02:47 +00002952 profile_info=CloneImageInfo(_image_info);
anthonyfd706f92012-01-19 04:22:02 +00002953 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002954 MaxTextExtent);
anthony92c93bd2012-03-19 14:02:47 +00002955 profile=FileToStringInfo(profile_info->filename,~0UL,_exception);
anthony805a2d42011-09-25 08:25:12 +00002956 if (profile != (StringInfo *) NULL)
2957 {
anthony92c93bd2012-03-19 14:02:47 +00002958 (void) ProfileImage(_image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002959 GetStringInfoDatum(profile),(size_t)
anthony92c93bd2012-03-19 14:02:47 +00002960 GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002961 profile=DestroyStringInfo(profile);
2962 }
2963 profile_info=DestroyImageInfo(profile_info);
2964 break;
2965 }
2966 ResetImageProfileIterator(profile_image);
2967 name=GetNextImageProfile(profile_image);
2968 while (name != (const char *) NULL)
2969 {
2970 profile=GetImageProfile(profile_image,name);
2971 if (profile != (StringInfo *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00002972 (void) ProfileImage(_image,name,GetStringInfoDatum(profile),
2973 (size_t) GetStringInfoLength(profile),_exception);
anthony805a2d42011-09-25 08:25:12 +00002974 name=GetNextImageProfile(profile_image);
2975 }
2976 profile_image=DestroyImage(profile_image);
2977 break;
2978 }
2979 break;
2980 }
anthony805a2d42011-09-25 08:25:12 +00002981 case 'r':
2982 {
anthonyafa3dfc2012-03-03 11:31:30 +00002983 if (LocaleCompare("radial-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002984 {
anthonyfd706f92012-01-19 04:22:02 +00002985 flags=ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00002986 new_image=RadialBlurImage(_image,geometry_info.rho,
2987 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00002988 break;
2989 }
anthonyafa3dfc2012-03-03 11:31:30 +00002990 if (LocaleCompare("raise",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002991 {
anthony92c93bd2012-03-19 14:02:47 +00002992 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00002993 if ((flags & SigmaValue) == 0)
2994 geometry.height=geometry.width;
anthony92c93bd2012-03-19 14:02:47 +00002995 (void) RaiseImage(_image,&geometry,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00002996 break;
2997 }
anthonyafa3dfc2012-03-03 11:31:30 +00002998 if (LocaleCompare("random-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00002999 {
anthony92c93bd2012-03-19 14:02:47 +00003000 (void) RandomThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003001 break;
3002 }
anthonyafa3dfc2012-03-03 11:31:30 +00003003 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003004 {
3005 Image
3006 *remap_image;
3007
anthony92c93bd2012-03-19 14:02:47 +00003008 remap_image=GetImageCache(_image_info,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003009 if (remap_image == (Image *) NULL)
3010 break;
anthony92c93bd2012-03-19 14:02:47 +00003011 (void) RemapImage(_quantize_info,_image,remap_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003012 remap_image=DestroyImage(remap_image);
3013 break;
3014 }
anthonyafa3dfc2012-03-03 11:31:30 +00003015 if (LocaleCompare("repage",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003016 {
anthonyafa3dfc2012-03-03 11:31:30 +00003017 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003018 (void) ResetImagePage(_image,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003019 else
anthony92c93bd2012-03-19 14:02:47 +00003020 (void) ParseAbsoluteGeometry("0x0+0+0",&_image->page);
anthony805a2d42011-09-25 08:25:12 +00003021 break;
3022 }
anthonyafa3dfc2012-03-03 11:31:30 +00003023 if (LocaleCompare("resample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003024 {
anthony31f1bf72012-01-30 12:37:22 +00003025 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00003026 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003027 if ((flags & SigmaValue) == 0)
3028 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003029 new_image=ResampleImage(_image,geometry_info.rho,
3030 geometry_info.sigma,_image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003031 break;
3032 }
anthonyafa3dfc2012-03-03 11:31:30 +00003033 if (LocaleCompare("resize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003034 {
anthonyafbaed72011-10-26 12:05:04 +00003035 /* FUTURE: remove blur argument - no longer used */
anthony92c93bd2012-03-19 14:02:47 +00003036 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3037 new_image=ResizeImage(_image,geometry.width,geometry.height,
3038 _image->filter,_image->blur,_exception);
anthony805a2d42011-09-25 08:25:12 +00003039 break;
3040 }
anthonyafa3dfc2012-03-03 11:31:30 +00003041 if (LocaleCompare("roll",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003042 {
anthony92c93bd2012-03-19 14:02:47 +00003043 (void) ParsePageGeometry(_image,arg1,&geometry,_exception);
3044 new_image=RollImage(_image,geometry.x,geometry.y,_exception);
anthony805a2d42011-09-25 08:25:12 +00003045 break;
3046 }
anthonyafa3dfc2012-03-03 11:31:30 +00003047 if (LocaleCompare("rotate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003048 {
anthonyfd706f92012-01-19 04:22:02 +00003049 if (strchr(arg1,'>') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003050 if (_image->columns <= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003051 break;
anthonyfd706f92012-01-19 04:22:02 +00003052 if (strchr(arg1,'<') != (char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003053 if (_image->columns >= _image->rows)
anthony805a2d42011-09-25 08:25:12 +00003054 break;
anthonyafbaed72011-10-26 12:05:04 +00003055
anthonyfd706f92012-01-19 04:22:02 +00003056 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003057 new_image=RotateImage(_image,geometry_info.rho,_exception);
anthony805a2d42011-09-25 08:25:12 +00003058 break;
3059 }
3060 break;
3061 }
3062 case 's':
3063 {
anthonyafa3dfc2012-03-03 11:31:30 +00003064 if (LocaleCompare("sample",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003065 {
anthony92c93bd2012-03-19 14:02:47 +00003066 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3067 new_image=SampleImage(_image,geometry.width,geometry.height,
3068 _exception);
anthony805a2d42011-09-25 08:25:12 +00003069 break;
3070 }
anthonyafa3dfc2012-03-03 11:31:30 +00003071 if (LocaleCompare("scale",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003072 {
anthony92c93bd2012-03-19 14:02:47 +00003073 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3074 new_image=ScaleImage(_image,geometry.width,geometry.height,
3075 _exception);
anthony805a2d42011-09-25 08:25:12 +00003076 break;
3077 }
anthonyafa3dfc2012-03-03 11:31:30 +00003078 if (LocaleCompare("selective-blur",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003079 {
anthonyfd706f92012-01-19 04:22:02 +00003080 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003081 if ((flags & PercentValue) != 0)
3082 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony92c93bd2012-03-19 14:02:47 +00003083 new_image=SelectiveBlurImage(_image,geometry_info.rho,
3084 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003085 break;
3086 }
anthonyafa3dfc2012-03-03 11:31:30 +00003087 if (LocaleCompare("separate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003088 {
anthony31f1bf72012-01-30 12:37:22 +00003089 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003090 /* FUTURE - this may be replaced by a "-channel" method */
cristydfdb19e2012-03-21 22:22:24 +00003091 new_image=SeparateImages(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003092 break;
3093 }
anthonyafa3dfc2012-03-03 11:31:30 +00003094 if (LocaleCompare("sepia-tone",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003095 {
3096 double
3097 threshold;
3098
anthonyfd706f92012-01-19 04:22:02 +00003099 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003100 new_image=SepiaToneImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003101 break;
3102 }
anthonyafa3dfc2012-03-03 11:31:30 +00003103 if (LocaleCompare("segment",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003104 {
anthonyfd706f92012-01-19 04:22:02 +00003105 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003106 if ((flags & SigmaValue) == 0)
3107 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003108 (void) SegmentImage(_image,_image->colorspace,
3109 _image_info->verbose,geometry_info.rho,geometry_info.sigma,
3110 _exception);
anthony805a2d42011-09-25 08:25:12 +00003111 break;
3112 }
anthonyafa3dfc2012-03-03 11:31:30 +00003113 if (LocaleCompare("set",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003114 {
3115 char
3116 *value;
3117
anthonyafa3dfc2012-03-03 11:31:30 +00003118 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00003119 {
anthonyfd706f92012-01-19 04:22:02 +00003120 if (LocaleNCompare(arg1,"registry:",9) == 0)
3121 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003122 else
anthony31f1bf72012-01-30 12:37:22 +00003123 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003124 {
anthony92c93bd2012-03-19 14:02:47 +00003125 (void) DeleteImageOption(_image_info,arg1+7);
3126 (void) DeleteImageArtifact(_image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003127 }
3128 else
anthony92c93bd2012-03-19 14:02:47 +00003129 (void) DeleteImageProperty(_image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003130 break;
3131 }
anthony92c93bd2012-03-19 14:02:47 +00003132 value=InterpretImageProperties(_image_info,_image,arg2,
3133 _exception);
anthony805a2d42011-09-25 08:25:12 +00003134 if (value == (char *) NULL)
3135 break;
anthonyfd706f92012-01-19 04:22:02 +00003136 if (LocaleNCompare(arg1,"registry:",9) == 0)
3137 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony92c93bd2012-03-19 14:02:47 +00003138 _exception);
anthony805a2d42011-09-25 08:25:12 +00003139 else
anthonyfd706f92012-01-19 04:22:02 +00003140 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003141 {
anthony92c93bd2012-03-19 14:02:47 +00003142 (void) SetImageOption(_image_info,arg1+7,value);
3143 (void) SetImageArtifact(_image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003144 }
3145 else
anthony92c93bd2012-03-19 14:02:47 +00003146 (void) SetImageProperty(_image,arg1,value,_exception);
anthony805a2d42011-09-25 08:25:12 +00003147 value=DestroyString(value);
3148 break;
3149 }
anthonyafa3dfc2012-03-03 11:31:30 +00003150 if (LocaleCompare("shade",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003151 {
anthonyfd706f92012-01-19 04:22:02 +00003152 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003153 if ((flags & SigmaValue) == 0)
3154 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003155 new_image=ShadeImage(_image,normal_op,geometry_info.rho,
3156 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003157 break;
3158 }
anthonyafa3dfc2012-03-03 11:31:30 +00003159 if (LocaleCompare("shadow",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003160 {
anthonyfd706f92012-01-19 04:22:02 +00003161 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003162 if ((flags & SigmaValue) == 0)
3163 geometry_info.sigma=1.0;
3164 if ((flags & XiValue) == 0)
3165 geometry_info.xi=4.0;
3166 if ((flags & PsiValue) == 0)
3167 geometry_info.psi=4.0;
anthony92c93bd2012-03-19 14:02:47 +00003168 new_image=ShadowImage(_image,geometry_info.rho,
3169 geometry_info.sigma,_image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003170 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
anthony92c93bd2012-03-19 14:02:47 +00003171 _exception);
anthony805a2d42011-09-25 08:25:12 +00003172 break;
3173 }
anthonyafa3dfc2012-03-03 11:31:30 +00003174 if (LocaleCompare("sharpen",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003175 {
anthonyfd706f92012-01-19 04:22:02 +00003176 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003177 if ((flags & SigmaValue) == 0)
3178 geometry_info.sigma=1.0;
3179 if ((flags & XiValue) == 0)
3180 geometry_info.xi=0.0;
anthony92c93bd2012-03-19 14:02:47 +00003181 new_image=SharpenImage(_image,geometry_info.rho,
3182 geometry_info.sigma,geometry_info.xi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003183 break;
3184 }
anthonyafa3dfc2012-03-03 11:31:30 +00003185 if (LocaleCompare("shave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003186 {
anthony92c93bd2012-03-19 14:02:47 +00003187 flags=ParsePageGeometry(_image,arg1,&geometry,_exception);
3188 new_image=ShaveImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003189 break;
3190 }
anthonyafa3dfc2012-03-03 11:31:30 +00003191 if (LocaleCompare("shear",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003192 {
anthonyfd706f92012-01-19 04:22:02 +00003193 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003194 if ((flags & SigmaValue) == 0)
3195 geometry_info.sigma=geometry_info.rho;
anthony92c93bd2012-03-19 14:02:47 +00003196 new_image=ShearImage(_image,geometry_info.rho,
3197 geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003198 break;
3199 }
anthonyafa3dfc2012-03-03 11:31:30 +00003200 if (LocaleCompare("sigmoidal-contrast",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003201 {
anthonyfd706f92012-01-19 04:22:02 +00003202 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003203 if ((flags & SigmaValue) == 0)
3204 geometry_info.sigma=(double) QuantumRange/2.0;
3205 if ((flags & PercentValue) != 0)
3206 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3207 100.0;
anthony92c93bd2012-03-19 14:02:47 +00003208 (void) SigmoidalContrastImage(_image,normal_op,geometry_info.rho,
anthony31f1bf72012-01-30 12:37:22 +00003209 geometry_info.sigma,
anthony92c93bd2012-03-19 14:02:47 +00003210 _exception);
anthony805a2d42011-09-25 08:25:12 +00003211 break;
3212 }
anthonyafa3dfc2012-03-03 11:31:30 +00003213 if (LocaleCompare("sketch",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003214 {
anthonyfd706f92012-01-19 04:22:02 +00003215 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003216 if ((flags & SigmaValue) == 0)
3217 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003218 new_image=SketchImage(_image,geometry_info.rho,
3219 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003220 break;
3221 }
anthonyafa3dfc2012-03-03 11:31:30 +00003222 if (LocaleCompare("solarize",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003223 {
anthony92c93bd2012-03-19 14:02:47 +00003224 (void) SolarizeImage(_image,StringToDoubleInterval(arg1,(double)
3225 QuantumRange+1.0),_exception);
anthony805a2d42011-09-25 08:25:12 +00003226 break;
3227 }
anthonyafa3dfc2012-03-03 11:31:30 +00003228 if (LocaleCompare("sparse-color",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003229 {
3230 SparseColorMethod
3231 method;
3232
3233 char
3234 *arguments;
3235
anthony805a2d42011-09-25 08:25:12 +00003236 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003237 MagickSparseColorOptions,MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003238 arguments=InterpretImageProperties(_image_info,_image,arg2,_exception);
anthony805a2d42011-09-25 08:25:12 +00003239 if (arguments == (char *) NULL)
3240 break;
anthony92c93bd2012-03-19 14:02:47 +00003241 new_image=SparseColorOption(_image,method,arguments,_exception);
anthony805a2d42011-09-25 08:25:12 +00003242 arguments=DestroyString(arguments);
3243 break;
3244 }
anthonyafa3dfc2012-03-03 11:31:30 +00003245 if (LocaleCompare("splice",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003246 {
anthony92c93bd2012-03-19 14:02:47 +00003247 (void) ParseGravityGeometry(_image,arg1,&geometry,_exception);
3248 new_image=SpliceImage(_image,&geometry,_exception);
anthony805a2d42011-09-25 08:25:12 +00003249 break;
3250 }
anthonyafa3dfc2012-03-03 11:31:30 +00003251 if (LocaleCompare("spread",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003252 {
anthonyfd706f92012-01-19 04:22:02 +00003253 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003254 new_image=SpreadImage(_image,geometry_info.rho,_image->interpolate,
3255 _exception);
anthony805a2d42011-09-25 08:25:12 +00003256 break;
3257 }
anthonyafa3dfc2012-03-03 11:31:30 +00003258 if (LocaleCompare("statistic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003259 {
3260 StatisticType
3261 type;
3262
anthony805a2d42011-09-25 08:25:12 +00003263 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
anthonyfd706f92012-01-19 04:22:02 +00003264 MagickFalse,arg1);
3265 (void) ParseGeometry(arg2,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003266 new_image=StatisticImage(_image,type,(size_t) geometry_info.rho,
3267 (size_t) geometry_info.sigma,_exception);
anthony805a2d42011-09-25 08:25:12 +00003268 break;
3269 }
anthonyafa3dfc2012-03-03 11:31:30 +00003270 if (LocaleCompare("strip",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003271 {
anthony92c93bd2012-03-19 14:02:47 +00003272 (void) StripImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003273 break;
3274 }
anthonyafa3dfc2012-03-03 11:31:30 +00003275 if (LocaleCompare("swirl",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003276 {
anthonyfd706f92012-01-19 04:22:02 +00003277 (void) ParseGeometry(arg1,&geometry_info);
anthony92c93bd2012-03-19 14:02:47 +00003278 new_image=SwirlImage(_image,geometry_info.rho,
3279 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003280 break;
3281 }
3282 break;
3283 }
3284 case 't':
3285 {
anthonyafa3dfc2012-03-03 11:31:30 +00003286 if (LocaleCompare("threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003287 {
3288 double
3289 threshold;
3290
anthonyafa3dfc2012-03-03 11:31:30 +00003291 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003292 threshold=(double) QuantumRange/2;
3293 else
anthonyfd706f92012-01-19 04:22:02 +00003294 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony92c93bd2012-03-19 14:02:47 +00003295 (void) BilevelImage(_image,threshold,_exception);
anthony805a2d42011-09-25 08:25:12 +00003296 break;
3297 }
anthonyafa3dfc2012-03-03 11:31:30 +00003298 if (LocaleCompare("thumbnail",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003299 {
anthony92c93bd2012-03-19 14:02:47 +00003300 (void) ParseRegionGeometry(_image,arg1,&geometry,_exception);
3301 new_image=ThumbnailImage(_image,geometry.width,geometry.height,
3302 _exception);
anthony805a2d42011-09-25 08:25:12 +00003303 break;
3304 }
anthonyafa3dfc2012-03-03 11:31:30 +00003305 if (LocaleCompare("tint",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003306 {
anthony92c93bd2012-03-19 14:02:47 +00003307 new_image=TintImage(_image,arg1,&_draw_info->fill,_exception);
anthony805a2d42011-09-25 08:25:12 +00003308 break;
3309 }
anthonyafa3dfc2012-03-03 11:31:30 +00003310 if (LocaleCompare("transform",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003311 {
anthonya3ef4ed2012-03-17 06:52:53 +00003312 /* DEPRECIATED -- should really use Distort AffineProjection */
anthony92c93bd2012-03-19 14:02:47 +00003313 new_image=AffineTransformImage(_image,&_draw_info->affine,
3314 _exception);
anthony805a2d42011-09-25 08:25:12 +00003315 break;
3316 }
anthonyafa3dfc2012-03-03 11:31:30 +00003317 if (LocaleCompare("transparent",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003318 {
3319 PixelInfo
3320 target;
3321
anthony92c93bd2012-03-19 14:02:47 +00003322 (void) QueryColorCompliance(arg1,AllCompliance,&target,_exception);
3323 (void) TransparentPaintImage(_image,&target,(Quantum)
3324 TransparentAlpha,plus_alt_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003325 break;
3326 }
anthonyafa3dfc2012-03-03 11:31:30 +00003327 if (LocaleCompare("transpose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003328 {
anthony92c93bd2012-03-19 14:02:47 +00003329 new_image=TransposeImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003330 break;
3331 }
anthonyafa3dfc2012-03-03 11:31:30 +00003332 if (LocaleCompare("transverse",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003333 {
anthony92c93bd2012-03-19 14:02:47 +00003334 new_image=TransverseImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003335 break;
3336 }
anthonyafa3dfc2012-03-03 11:31:30 +00003337 if (LocaleCompare("trim",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003338 {
anthony92c93bd2012-03-19 14:02:47 +00003339 new_image=TrimImage(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003340 break;
3341 }
anthonyafa3dfc2012-03-03 11:31:30 +00003342 if (LocaleCompare("type",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003343 {
anthonyab3a50c2011-10-27 11:48:57 +00003344 /* Note that "type" setting should have already been defined */
anthony92c93bd2012-03-19 14:02:47 +00003345 (void) SetImageType(_image,_image_info->type,_exception);
anthony805a2d42011-09-25 08:25:12 +00003346 break;
3347 }
3348 break;
3349 }
3350 case 'u':
3351 {
anthonyafa3dfc2012-03-03 11:31:30 +00003352 if (LocaleCompare("unique",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003353 {
anthony31f1bf72012-01-30 12:37:22 +00003354 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
anthony24aa8822012-03-11 00:56:06 +00003355 /* FUTURE: This option is not documented!!!!! */
anthonyafa3dfc2012-03-03 11:31:30 +00003356 if (!normal_op)
anthony805a2d42011-09-25 08:25:12 +00003357 {
anthony92c93bd2012-03-19 14:02:47 +00003358 (void) DeleteImageArtifact(_image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003359 break;
3360 }
anthony92c93bd2012-03-19 14:02:47 +00003361 (void) SetImageArtifact(_image,"identify:unique-colors","true");
3362 (void) SetImageArtifact(_image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003363 break;
3364 }
anthonyafa3dfc2012-03-03 11:31:30 +00003365 if (LocaleCompare("unique-colors",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003366 {
anthony92c93bd2012-03-19 14:02:47 +00003367 new_image=UniqueImageColors(_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003368 break;
3369 }
anthonyafa3dfc2012-03-03 11:31:30 +00003370 if (LocaleCompare("unsharp",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003371 {
anthonyfd706f92012-01-19 04:22:02 +00003372 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003373 if ((flags & SigmaValue) == 0)
3374 geometry_info.sigma=1.0;
3375 if ((flags & XiValue) == 0)
3376 geometry_info.xi=1.0;
3377 if ((flags & PsiValue) == 0)
3378 geometry_info.psi=0.05;
anthony92c93bd2012-03-19 14:02:47 +00003379 new_image=UnsharpMaskImage(_image,geometry_info.rho,
3380 geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
anthony805a2d42011-09-25 08:25:12 +00003381 break;
3382 }
3383 break;
3384 }
3385 case 'v':
3386 {
anthonyafa3dfc2012-03-03 11:31:30 +00003387 if (LocaleCompare("verbose",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003388 {
anthonyafa3dfc2012-03-03 11:31:30 +00003389 /* FUTURE: move to SyncImageSettings() and AcquireImage()???
anthony92c93bd2012-03-19 14:02:47 +00003390 three places! ImageArtifact ImageOption _image_info->verbose
anthony5330ae02012-03-20 14:17:01 +00003391 Some how new images also get this artifact!
anthony31f1bf72012-01-30 12:37:22 +00003392 */
anthony92c93bd2012-03-19 14:02:47 +00003393 (void) SetImageArtifact(_image,option+1,
anthonyafa3dfc2012-03-03 11:31:30 +00003394 IfNormalOp ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +00003395 break;
3396 }
anthonyafa3dfc2012-03-03 11:31:30 +00003397 if (LocaleCompare("vignette",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003398 {
anthonyfd706f92012-01-19 04:22:02 +00003399 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003400 if ((flags & SigmaValue) == 0)
3401 geometry_info.sigma=1.0;
3402 if ((flags & XiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003403 geometry_info.xi=0.1*_image->columns;
anthony805a2d42011-09-25 08:25:12 +00003404 if ((flags & PsiValue) == 0)
anthony92c93bd2012-03-19 14:02:47 +00003405 geometry_info.psi=0.1*_image->rows;
3406 new_image=VignetteImage(_image,geometry_info.rho,geometry_info.sigma,
3407 _image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3408 (ssize_t) ceil(geometry_info.psi-0.5),_exception);
anthony805a2d42011-09-25 08:25:12 +00003409 break;
3410 }
anthony805a2d42011-09-25 08:25:12 +00003411 break;
3412 }
3413 case 'w':
3414 {
anthonyafa3dfc2012-03-03 11:31:30 +00003415 if (LocaleCompare("wave",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003416 {
anthonyfd706f92012-01-19 04:22:02 +00003417 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003418 if ((flags & SigmaValue) == 0)
3419 geometry_info.sigma=1.0;
anthony92c93bd2012-03-19 14:02:47 +00003420 new_image=WaveImage(_image,geometry_info.rho,geometry_info.sigma,
3421 _image->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003422 break;
3423 }
anthonyafa3dfc2012-03-03 11:31:30 +00003424 if (LocaleCompare("white-threshold",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003425 {
anthony92c93bd2012-03-19 14:02:47 +00003426 (void) WhiteThresholdImage(_image,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003427 break;
3428 }
3429 break;
3430 }
3431 default:
3432 break;
3433 }
3434 /*
3435 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003436 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003437 */
3438 if (new_image != (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003439 ReplaceImageInListReturnLast(&_image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003440
anthony31f1bf72012-01-30 12:37:22 +00003441 return;
anthony92c93bd2012-03-19 14:02:47 +00003442#undef _image_info
3443#undef _draw_info
3444#undef _quantize_info
3445#undef _image
3446#undef _exception
anthonyafa3dfc2012-03-03 11:31:30 +00003447#undef IfNormalOp
3448#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00003449#undef normal_op
anthonyafa3dfc2012-03-03 11:31:30 +00003450#undef plus_alt_op
anthony31f1bf72012-01-30 12:37:22 +00003451}
anthonyfd706f92012-01-19 04:22:02 +00003452
anthony43f425d2012-02-26 12:58:58 +00003453WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003454 const char *option, const char *arg1, const char *arg2)
anthony31f1bf72012-01-30 12:37:22 +00003455{
3456 size_t
anthony43f425d2012-02-26 12:58:58 +00003457 n,
anthony31f1bf72012-01-30 12:37:22 +00003458 i;
3459
anthony43f425d2012-02-26 12:58:58 +00003460 assert(cli_wand != (MagickCLI *) NULL);
3461 assert(cli_wand->signature == WandSignature);
3462 assert(cli_wand->wand.signature == WandSignature);
3463 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3464 if (cli_wand->wand.debug != MagickFalse)
3465 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003466
anthonyafa3dfc2012-03-03 11:31:30 +00003467#if !USE_WAND_METHODS
3468 /* FUTURE add appropriate tracing */
anthony31f1bf72012-01-30 12:37:22 +00003469 i=0;
anthony43f425d2012-02-26 12:58:58 +00003470 n=GetImageListLength(cli_wand->wand.images);
3471 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003472 while (1) {
anthony31f1bf72012-01-30 12:37:22 +00003473 i++;
anthonyafa3dfc2012-03-03 11:31:30 +00003474 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
anthony43f425d2012-02-26 12:58:58 +00003475 if ( cli_wand->wand.images->next == (Image *) NULL )
3476 break;
3477 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003478 }
anthony43f425d2012-02-26 12:58:58 +00003479 assert( i == n );
3480 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthonyafa3dfc2012-03-03 11:31:30 +00003481#else
3482 MagickResetIterator(&cli_wand->wand);
3483 while ( MagickNextImage(&cli_wand->wand) != MagickFalse )
3484 CLISimpleOperatorImage(cli_wand, option, arg1, arg2);
3485 MagickResetIterator(&cli_wand->wand);
3486#endif
anthony31f1bf72012-01-30 12:37:22 +00003487 return;
anthony805a2d42011-09-25 08:25:12 +00003488}
3489
3490/*
3491%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3492% %
3493% %
3494% %
anthony43f425d2012-02-26 12:58:58 +00003495+ 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 +00003496% %
3497% %
3498% %
3499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3500%
anthony43f425d2012-02-26 12:58:58 +00003501% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003502% entire image list as a whole. The result is often a complete replacment
3503% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003504%
3505% The format of the MogrifyImage method is:
3506%
anthony43f425d2012-02-26 12:58:58 +00003507% void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003508% const char *option, const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003509%
3510% A description of each parameter follows:
3511%
anthony43f425d2012-02-26 12:58:58 +00003512% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003513%
anthony36a8c2c2012-02-10 00:08:44 +00003514% o option: The option string for the operation
3515%
anthony31f1bf72012-01-30 12:37:22 +00003516% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003517%
anthony8b10b462012-02-08 12:32:44 +00003518% NOTE: only "limit" currently uses two arguments.
3519%
3520% Example usage...
3521%
anthonyafa3dfc2012-03-03 11:31:30 +00003522% CLIListOperatorImages(cli_wand,MagickFalse,"-duplicate", "3", NULL);
3523% CLIListOperatorImages(cli_wand,MagickTrue, "+append", NULL, NULL);
anthony8b10b462012-02-08 12:32:44 +00003524%
anthony24aa8822012-03-11 00:56:06 +00003525% Or for handling command line arguments EG: +/-option ["arg1"]
anthony8b10b462012-02-08 12:32:44 +00003526%
anthony43f425d2012-02-26 12:58:58 +00003527% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003528% argc,argv
3529% i=index in argv
3530%
anthony2052d272012-02-28 12:48:29 +00003531% option_info = GetCommandOptionInfo(argv[i]);
3532% count=option_info->type;
3533% option_type=option_info->flags;
3534%
3535% if ( (option_type & ListOperatorOptionFlag) != 0 )
anthonyafa3dfc2012-03-03 11:31:30 +00003536% CLIListOperatorImages(cli_wand,argv[i],
anthony8b10b462012-02-08 12:32:44 +00003537% count>=1 ? argv[i+1] : (char *)NULL,
3538% count>=2 ? argv[i+2] : (char *)NULL );
3539% i += count+1;
3540%
anthony805a2d42011-09-25 08:25:12 +00003541*/
anthony43f425d2012-02-26 12:58:58 +00003542WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthonyafa3dfc2012-03-03 11:31:30 +00003543 const char *option,const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003544{
anthony31f1bf72012-01-30 12:37:22 +00003545 Image
3546 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003547
anthony92c93bd2012-03-19 14:02:47 +00003548#define _image_info (cli_wand->wand.image_info)
3549#define _images (cli_wand->wand.images)
3550#define _exception (cli_wand->wand.exception)
3551#define _draw_info (cli_wand->draw_info)
3552#define _quantize_info (cli_wand->quantize_info)
anthonyafa3dfc2012-03-03 11:31:30 +00003553#define IfNormalOp (*option=='-')
3554#define IfPlusOp (*option!='-')
3555#define normal_op (IfNormalOp?MagickTrue:MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003556
anthony43f425d2012-02-26 12:58:58 +00003557 assert(cli_wand != (MagickCLI *) NULL);
3558 assert(cli_wand->signature == WandSignature);
3559 assert(cli_wand->wand.signature == WandSignature);
anthony92c93bd2012-03-19 14:02:47 +00003560 assert(_images != (Image *) NULL); /* _images must be present */
anthony43f425d2012-02-26 12:58:58 +00003561 if (cli_wand->wand.debug != MagickFalse)
3562 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003563
anthony92c93bd2012-03-19 14:02:47 +00003564 (void) SyncImagesSettings(_image_info,_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003565
3566 new_images=NewImageList();
3567
anthonyafa3dfc2012-03-03 11:31:30 +00003568 switch (*(option+1))
anthony805a2d42011-09-25 08:25:12 +00003569 {
3570 case 'a':
3571 {
anthonyafa3dfc2012-03-03 11:31:30 +00003572 if (LocaleCompare("append",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003573 {
anthony92c93bd2012-03-19 14:02:47 +00003574 new_images=AppendImages(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003575 break;
3576 }
anthonyafa3dfc2012-03-03 11:31:30 +00003577 if (LocaleCompare("average",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003578 {
anthony31f1bf72012-01-30 12:37:22 +00003579 /* DEPRECIATED - use -evaluate-sequence Mean */
anthonyafa3dfc2012-03-03 11:31:30 +00003580 CLIListOperatorImages(cli_wand,"-evaluate-sequence","Mean",NULL);
anthony805a2d42011-09-25 08:25:12 +00003581 break;
3582 }
3583 break;
3584 }
3585 case 'c':
3586 {
cristy5f257b22012-03-07 00:27:29 +00003587 if (LocaleCompare("channel-fx",option+1) == 0)
cristy87c02f42012-02-24 00:19:10 +00003588 {
anthony92c93bd2012-03-19 14:02:47 +00003589 new_images=ChannelFxImage(_images,arg1,_exception);
cristy87c02f42012-02-24 00:19:10 +00003590 break;
3591 }
anthonyafa3dfc2012-03-03 11:31:30 +00003592 if (LocaleCompare("clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003593 {
anthony805a2d42011-09-25 08:25:12 +00003594 Image
anthony31f1bf72012-01-30 12:37:22 +00003595 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003596
anthonyafa3dfc2012-03-03 11:31:30 +00003597 /* FUTURE - make this a compose option, and thus can be used
3598 with layers compose or even compose last image over all other
anthony92c93bd2012-03-19 14:02:47 +00003599 _images.
cristy87c02f42012-02-24 00:19:10 +00003600 */
anthony92c93bd2012-03-19 14:02:47 +00003601 new_images=RemoveFirstImageFromList(&_images);
3602 clut_image=RemoveLastImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003603 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003604 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003605 break;
anthony92c93bd2012-03-19 14:02:47 +00003606 (void) ClutImage(new_images,clut_image,_images->interpolate,_exception);
anthony805a2d42011-09-25 08:25:12 +00003607 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003608 break;
3609 }
anthonyafa3dfc2012-03-03 11:31:30 +00003610 if (LocaleCompare("coalesce",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003611 {
anthony92c93bd2012-03-19 14:02:47 +00003612 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003613 break;
3614 }
anthonyafa3dfc2012-03-03 11:31:30 +00003615 if (LocaleCompare("combine",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003616 {
anthony43f425d2012-02-26 12:58:58 +00003617 /* FUTURE - this may be replaced by a 'channel' method */
anthony92c93bd2012-03-19 14:02:47 +00003618 new_images=CombineImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003619 break;
3620 }
anthonyafa3dfc2012-03-03 11:31:30 +00003621 if (LocaleCompare("composite",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003622 {
3623 Image
3624 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003625 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003626
3627 RectangleInfo
3628 geometry;
3629
anthony31f1bf72012-01-30 12:37:22 +00003630 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003631 compose;
3632
3633 const char*
3634 value;
3635
anthony92c93bd2012-03-19 14:02:47 +00003636 value=GetImageOption(_image_info,"compose");
anthony5f867ae2011-10-09 10:28:34 +00003637 if (value != (const char *) NULL)
3638 compose=(CompositeOperator) ParseCommandOption(
3639 MagickComposeOptions,MagickFalse,value);
3640 else
anthony31f1bf72012-01-30 12:37:22 +00003641 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003642
anthony92c93bd2012-03-19 14:02:47 +00003643 new_images=RemoveFirstImageFromList(&_images);
3644 source_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003645 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003646 if (source_image == (Image *) NULL)
3647 break;
anthonye8f56492012-02-12 12:39:02 +00003648
anthony31f1bf72012-01-30 12:37:22 +00003649 /* FUTURE - this should not be here! - should be part of -geometry */
3650 (void) TransformImage(&source_image,(char *) NULL,
anthony92c93bd2012-03-19 14:02:47 +00003651 source_image->geometry,_exception);
anthony5f867ae2011-10-09 10:28:34 +00003652
anthony31f1bf72012-01-30 12:37:22 +00003653 SetGeometry(source_image,&geometry);
3654 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3655 GravityAdjustGeometry(new_images->columns,new_images->rows,
3656 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003657
anthony92c93bd2012-03-19 14:02:47 +00003658 mask_image=RemoveFirstImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003659 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003660 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003661 if ((compose == DisplaceCompositeOp) ||
3662 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003663 { /* Merge Y displacement into X displace/distort map. */
3664 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony92c93bd2012-03-19 14:02:47 +00003665 mask_image,0,0,_exception);
anthony805a2d42011-09-25 08:25:12 +00003666 mask_image=DestroyImage(mask_image);
3667 }
3668 else
3669 {
3670 /*
3671 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003672 */
anthony92c93bd2012-03-19 14:02:47 +00003673 (void) NegateImage(mask_image,MagickFalse,_exception);
3674 (void) SetImageMask(new_images,mask_image,_exception);
cristy1539afd2012-01-30 01:32:59 +00003675 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003676 }
3677 }
anthony31f1bf72012-01-30 12:37:22 +00003678 (void) CompositeImage(new_images,compose,source_image,geometry.x,
anthony92c93bd2012-03-19 14:02:47 +00003679 geometry.y,_exception);
3680 (void) SetImageMask(new_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003681 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003682 break;
3683 }
3684 break;
3685 }
3686 case 'd':
3687 {
anthonyafa3dfc2012-03-03 11:31:30 +00003688 if (LocaleCompare("deconstruct",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003689 {
anthony31f1bf72012-01-30 12:37:22 +00003690 /* DEPRECIATED - use -layers CompareAny */
anthonyafa3dfc2012-03-03 11:31:30 +00003691 CLIListOperatorImages(cli_wand,"-layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003692 break;
3693 }
anthonyafa3dfc2012-03-03 11:31:30 +00003694 if (LocaleCompare("delete",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003695 {
anthonyafa3dfc2012-03-03 11:31:30 +00003696 if (IfNormalOp)
anthony92c93bd2012-03-19 14:02:47 +00003697 DeleteImages(&_images,arg1,_exception);
anthonyafa3dfc2012-03-03 11:31:30 +00003698 else
anthony92c93bd2012-03-19 14:02:47 +00003699 DeleteImages(&_images,"-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003700 break;
3701 }
anthonyafa3dfc2012-03-03 11:31:30 +00003702 if (LocaleCompare("duplicate",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003703 {
anthonyafa3dfc2012-03-03 11:31:30 +00003704 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00003705 {
3706 const char
3707 *p;
3708
3709 size_t
3710 number_duplicates;
3711
anthony31f1bf72012-01-30 12:37:22 +00003712 number_duplicates=(size_t) StringToLong(arg1);
3713 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003714 if (p == (const char *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00003715 new_images=DuplicateImages(_images,number_duplicates,
3716 "-1",_exception);
anthony805a2d42011-09-25 08:25:12 +00003717 else
anthony92c93bd2012-03-19 14:02:47 +00003718 new_images=DuplicateImages(_images,number_duplicates,p,
3719 _exception);
anthony805a2d42011-09-25 08:25:12 +00003720 }
anthonyafa3dfc2012-03-03 11:31:30 +00003721 else
anthony92c93bd2012-03-19 14:02:47 +00003722 new_images=DuplicateImages(_images,1,"-1",_exception);
3723 AppendImageToList(&_images, new_images);
anthony36a8c2c2012-02-10 00:08:44 +00003724 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003725 break;
3726 }
3727 break;
3728 }
3729 case 'e':
3730 {
anthonyafa3dfc2012-03-03 11:31:30 +00003731 if (LocaleCompare("evaluate-sequence",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003732 {
anthony805a2d42011-09-25 08:25:12 +00003733 MagickEvaluateOperator
anthony31f1bf72012-01-30 12:37:22 +00003734 method;
anthony805a2d42011-09-25 08:25:12 +00003735
anthony31f1bf72012-01-30 12:37:22 +00003736 method=(MagickEvaluateOperator) ParseCommandOption(
3737 MagickEvaluateOptions,MagickFalse,arg1);
anthony92c93bd2012-03-19 14:02:47 +00003738 new_images=EvaluateImages(_images,method,_exception);
anthony805a2d42011-09-25 08:25:12 +00003739 break;
3740 }
3741 break;
3742 }
3743 case 'f':
3744 {
anthonyafa3dfc2012-03-03 11:31:30 +00003745 if (LocaleCompare("fft",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003746 {
anthony92c93bd2012-03-19 14:02:47 +00003747 new_images=ForwardFourierTransformImage(_images,normal_op,_exception);
anthony805a2d42011-09-25 08:25:12 +00003748 break;
3749 }
anthonyafa3dfc2012-03-03 11:31:30 +00003750 if (LocaleCompare("flatten",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003751 {
anthony319dac62012-03-06 04:12:44 +00003752 /* REDIRECTED to use -layers flatten instead */
anthonyafa3dfc2012-03-03 11:31:30 +00003753 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00003754 break;
3755 }
anthonyafa3dfc2012-03-03 11:31:30 +00003756 if (LocaleCompare("fx",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003757 {
anthony92c93bd2012-03-19 14:02:47 +00003758 new_images=FxImage(_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00003759 break;
3760 }
3761 break;
3762 }
3763 case 'h':
3764 {
anthonyafa3dfc2012-03-03 11:31:30 +00003765 if (LocaleCompare("hald-clut",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003766 {
anthony31f1bf72012-01-30 12:37:22 +00003767 /* FUTURE - make this a compose option (and thus layers compose )
anthony92c93bd2012-03-19 14:02:47 +00003768 or perhaps compose last image over all other _images.
anthony31f1bf72012-01-30 12:37:22 +00003769 */
anthony805a2d42011-09-25 08:25:12 +00003770 Image
anthony31f1bf72012-01-30 12:37:22 +00003771 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003772
anthony92c93bd2012-03-19 14:02:47 +00003773 new_images=RemoveFirstImageFromList(&_images);
3774 hald_image=RemoveLastImageFromList(&_images);
anthony805a2d42011-09-25 08:25:12 +00003775 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003776 break;
anthony92c93bd2012-03-19 14:02:47 +00003777 (void) HaldClutImage(new_images,hald_image,_exception);
anthony805a2d42011-09-25 08:25:12 +00003778 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003779 break;
3780 }
3781 break;
3782 }
3783 case 'i':
3784 {
anthonyafa3dfc2012-03-03 11:31:30 +00003785 if (LocaleCompare("ift",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003786 {
3787 Image
anthony805a2d42011-09-25 08:25:12 +00003788 *magnitude_image,
3789 *phase_image;
3790
anthony92c93bd2012-03-19 14:02:47 +00003791 magnitude_image=RemoveFirstImageFromList(&_images);
3792 phase_image=RemoveFirstImageFromList(&_images);
anthonye8f56492012-02-12 12:39:02 +00003793 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003794 if (phase_image == (Image *) NULL)
3795 break;
3796 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
anthony92c93bd2012-03-19 14:02:47 +00003797 normal_op,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003798 magnitude_image=DestroyImage(magnitude_image);
3799 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003800 break;
3801 }
anthonyafa3dfc2012-03-03 11:31:30 +00003802 if (LocaleCompare("insert",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003803 {
3804 Image
anthony31f1bf72012-01-30 12:37:22 +00003805 *insert_image,
3806 *index_image;
3807
3808 ssize_t
3809 index;
anthony805a2d42011-09-25 08:25:12 +00003810
3811 index=0;
anthony92c93bd2012-03-19 14:02:47 +00003812 insert_image=RemoveLastImageFromList(&_images);
anthonyafa3dfc2012-03-03 11:31:30 +00003813 if (IfNormalOp)
anthony31f1bf72012-01-30 12:37:22 +00003814 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003815 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003816 if (index == 0)
anthony92c93bd2012-03-19 14:02:47 +00003817 PrependImageToList(&_images,insert_image);
3818 else if (index == (ssize_t) GetImageListLength(_images))
3819 AppendImageToList(&_images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003820 else
anthony43f425d2012-02-26 12:58:58 +00003821 {
anthony92c93bd2012-03-19 14:02:47 +00003822 index_image=GetImageFromList(_images,index-1);
anthony43f425d2012-02-26 12:58:58 +00003823 if (index_image == (Image *) NULL)
3824 {
anthony92c93bd2012-03-19 14:02:47 +00003825 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +00003826 OptionError,"NoSuchImage","'%s'",arg1);
3827 break;
3828 }
3829 InsertImageInList(&index_image,insert_image);
3830 }
anthony92c93bd2012-03-19 14:02:47 +00003831 _images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003832 break;
3833 }
anthony805a2d42011-09-25 08:25:12 +00003834 break;
3835 }
3836 case 'l':
3837 {
anthonyafa3dfc2012-03-03 11:31:30 +00003838 if (LocaleCompare("layers",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00003839 {
anthony805a2d42011-09-25 08:25:12 +00003840 ImageLayerMethod
3841 method;
3842
anthony805a2d42011-09-25 08:25:12 +00003843 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
anthony31f1bf72012-01-30 12:37:22 +00003844 MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00003845 switch (method)
3846 {
3847 case CoalesceLayer:
3848 {
anthony92c93bd2012-03-19 14:02:47 +00003849 new_images=CoalesceImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003850 break;
3851 }
3852 case CompareAnyLayer:
3853 case CompareClearLayer:
3854 case CompareOverlayLayer:
3855 default:
3856 {
anthony92c93bd2012-03-19 14:02:47 +00003857 new_images=CompareImagesLayers(_images,method,_exception);
anthony805a2d42011-09-25 08:25:12 +00003858 break;
3859 }
3860 case MergeLayer:
3861 case FlattenLayer:
3862 case MosaicLayer:
3863 case TrimBoundsLayer:
3864 {
anthony92c93bd2012-03-19 14:02:47 +00003865 new_images=MergeImageLayers(_images,method,_exception);
anthony805a2d42011-09-25 08:25:12 +00003866 break;
3867 }
3868 case DisposeLayer:
3869 {
anthony92c93bd2012-03-19 14:02:47 +00003870 new_images=DisposeImages(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003871 break;
3872 }
3873 case OptimizeImageLayer:
3874 {
anthony92c93bd2012-03-19 14:02:47 +00003875 new_images=OptimizeImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003876 break;
3877 }
3878 case OptimizePlusLayer:
3879 {
anthony92c93bd2012-03-19 14:02:47 +00003880 new_images=OptimizePlusImageLayers(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003881 break;
3882 }
3883 case OptimizeTransLayer:
3884 {
anthony92c93bd2012-03-19 14:02:47 +00003885 OptimizeImageTransparency(_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003886 break;
3887 }
3888 case RemoveDupsLayer:
3889 {
anthony92c93bd2012-03-19 14:02:47 +00003890 RemoveDuplicateLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003891 break;
3892 }
3893 case RemoveZeroLayer:
3894 {
anthony92c93bd2012-03-19 14:02:47 +00003895 RemoveZeroDelayLayers(&_images,_exception);
anthony805a2d42011-09-25 08:25:12 +00003896 break;
3897 }
3898 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003899 { /* General Purpose, GIF Animation Optimizer. */
anthony92c93bd2012-03-19 14:02:47 +00003900 new_images=CoalesceImages(_images,_exception);
anthony31f1bf72012-01-30 12:37:22 +00003901 if (new_images == (Image *) NULL)
3902 break;
anthony92c93bd2012-03-19 14:02:47 +00003903 _images=DestroyImageList(_images);
3904 _images=OptimizeImageLayers(new_images,_exception);
3905 if (_images == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003906 break;
3907 new_images=DestroyImageList(new_images);
anthony92c93bd2012-03-19 14:02:47 +00003908 OptimizeImageTransparency(_images,_exception);
3909 (void) RemapImages(_quantize_info,_images,(Image *) NULL,
3910 _exception);
anthony805a2d42011-09-25 08:25:12 +00003911 break;
3912 }
3913 case CompositeLayer:
3914 {
anthony805a2d42011-09-25 08:25:12 +00003915 Image
3916 *source;
3917
3918 RectangleInfo
3919 geometry;
3920
anthony31f1bf72012-01-30 12:37:22 +00003921 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003922 compose;
3923
3924 const char*
3925 value;
3926
anthony92c93bd2012-03-19 14:02:47 +00003927 value=GetImageOption(_image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003928 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003929 if (value != (const char *) NULL)
3930 compose=(CompositeOperator) ParseCommandOption(
3931 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003932
anthony31f1bf72012-01-30 12:37:22 +00003933 /* Split image sequence at the first 'NULL:' image. */
anthony92c93bd2012-03-19 14:02:47 +00003934 source=_images;
anthony805a2d42011-09-25 08:25:12 +00003935 while (source != (Image *) NULL)
3936 {
3937 source=GetNextImageInList(source);
3938 if ((source != (Image *) NULL) &&
3939 (LocaleCompare(source->magick,"NULL") == 0))
3940 break;
3941 }
3942 if (source != (Image *) NULL)
3943 {
3944 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3945 (GetNextImageInList(source) == (Image *) NULL))
3946 source=(Image *) NULL;
3947 else
anthony31f1bf72012-01-30 12:37:22 +00003948 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003949 source=SplitImageList(source->previous);
3950 DeleteImageFromList(&source);
3951 }
3952 }
3953 if (source == (Image *) NULL)
3954 {
anthony92c93bd2012-03-19 14:02:47 +00003955 (void) ThrowMagickException(_exception,GetMagickModule(),
anthony805a2d42011-09-25 08:25:12 +00003956 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003957 break;
3958 }
anthony31f1bf72012-01-30 12:37:22 +00003959 /* Adjust offset with gravity and virtual canvas. */
anthony92c93bd2012-03-19 14:02:47 +00003960 SetGeometry(_images,&geometry);
3961 (void) ParseAbsoluteGeometry(_images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003962 geometry.width=source->page.width != 0 ?
3963 source->page.width : source->columns;
3964 geometry.height=source->page.height != 0 ?
3965 source->page.height : source->rows;
anthony92c93bd2012-03-19 14:02:47 +00003966 GravityAdjustGeometry(_images->page.width != 0 ?
3967 _images->page.width : _images->columns,
3968 _images->page.height != 0 ? _images->page.height :
3969 _images->rows,_images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003970
anthony31f1bf72012-01-30 12:37:22 +00003971 /* Compose the two image sequences together */
anthony92c93bd2012-03-19 14:02:47 +00003972 CompositeLayers(_images,compose,source,geometry.x,geometry.y,
3973 _exception);
anthony805a2d42011-09-25 08:25:12 +00003974 source=DestroyImageList(source);
3975 break;
3976 }
3977 }
anthony805a2d42011-09-25 08:25:12 +00003978 break;
3979 }
anthonyafa3dfc2012-03-03 11:31:30 +00003980 if (LocaleCompare("limit",option+1) == 0)
anthony72feaa62012-01-17 06:46:23 +00003981 {
3982 MagickSizeType
3983 limit;
3984
3985 ResourceType
3986 type;
3987
anthony72feaa62012-01-17 06:46:23 +00003988 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
anthony31f1bf72012-01-30 12:37:22 +00003989 MagickFalse,arg1);
anthony72feaa62012-01-17 06:46:23 +00003990 limit=MagickResourceInfinity;
anthony31f1bf72012-01-30 12:37:22 +00003991 if (LocaleCompare("unlimited",arg2) != 0)
3992 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthony72feaa62012-01-17 06:46:23 +00003993 (void) SetMagickResourceLimit(type,limit);
3994 break;
3995 }
anthony805a2d42011-09-25 08:25:12 +00003996 break;
3997 }
3998 case 'm':
3999 {
anthonyafa3dfc2012-03-03 11:31:30 +00004000 if (LocaleCompare("map",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004001 {
anthony31f1bf72012-01-30 12:37:22 +00004002 /* DEPRECIATED use +remap */
anthony92c93bd2012-03-19 14:02:47 +00004003 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony805a2d42011-09-25 08:25:12 +00004004 break;
4005 }
anthonyafa3dfc2012-03-03 11:31:30 +00004006 if (LocaleCompare("morph",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004007 {
4008 Image
4009 *morph_image;
4010
anthony92c93bd2012-03-19 14:02:47 +00004011 morph_image=MorphImages(_images,StringToUnsignedLong(arg1),
4012 _exception);
anthony805a2d42011-09-25 08:25:12 +00004013 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004014 break;
anthony92c93bd2012-03-19 14:02:47 +00004015 _images=DestroyImageList(_images);
4016 _images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00004017 break;
4018 }
anthonyafa3dfc2012-03-03 11:31:30 +00004019 if (LocaleCompare("mosaic",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004020 {
anthony319dac62012-03-06 04:12:44 +00004021 /* REDIRECTED to use -layers mosaic instead */
anthonyafa3dfc2012-03-03 11:31:30 +00004022 CLIListOperatorImages(cli_wand,"-layer",option+1,NULL);
anthony805a2d42011-09-25 08:25:12 +00004023 break;
4024 }
4025 break;
4026 }
4027 case 'p':
4028 {
anthonyafa3dfc2012-03-03 11:31:30 +00004029 if (LocaleCompare("print",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004030 {
4031 char
4032 *string;
4033
anthony92c93bd2012-03-19 14:02:47 +00004034 string=InterpretImageProperties(_image_info,_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004035 if (string == (char *) NULL)
4036 break;
4037 (void) FormatLocaleFile(stdout,"%s",string);
4038 string=DestroyString(string);
anthony24aa8822012-03-11 00:56:06 +00004039 break;
anthony805a2d42011-09-25 08:25:12 +00004040 }
anthonyafa3dfc2012-03-03 11:31:30 +00004041 if (LocaleCompare("process",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004042 {
4043 char
4044 **arguments;
4045
4046 int
4047 j,
4048 number_arguments;
4049
anthony31f1bf72012-01-30 12:37:22 +00004050 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00004051 if (arguments == (char **) NULL)
4052 break;
anthony31f1bf72012-01-30 12:37:22 +00004053 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00004054 {
4055 char
4056 breaker,
4057 quote,
4058 *token;
4059
4060 const char
4061 *arguments;
4062
4063 int
4064 next,
4065 status;
4066
4067 size_t
4068 length;
4069
4070 TokenInfo
4071 *token_info;
4072
4073 /*
anthony24aa8822012-03-11 00:56:06 +00004074 Support old style syntax, filter="-option arg1".
anthony805a2d42011-09-25 08:25:12 +00004075 */
anthony31f1bf72012-01-30 12:37:22 +00004076 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00004077 token=(char *) NULL;
4078 if (~length >= (MaxTextExtent-1))
4079 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4080 sizeof(*token));
4081 if (token == (char *) NULL)
4082 break;
4083 next=0;
anthony31f1bf72012-01-30 12:37:22 +00004084 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00004085 token_info=AcquireTokenInfo();
4086 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4087 "\"",'\0',&breaker,&next,&quote);
4088 token_info=DestroyTokenInfo(token_info);
4089 if (status == 0)
4090 {
4091 const char
4092 *argv;
4093
4094 argv=(&(arguments[next]));
anthony92c93bd2012-03-19 14:02:47 +00004095 (void) InvokeDynamicImageFilter(token,&_images,1,&argv,
4096 _exception);
anthony805a2d42011-09-25 08:25:12 +00004097 }
4098 token=DestroyString(token);
4099 break;
4100 }
4101 (void) SubstituteString(&arguments[1],"-","");
anthony92c93bd2012-03-19 14:02:47 +00004102 (void) InvokeDynamicImageFilter(arguments[1],&_images,
4103 number_arguments-2,(const char **) arguments+2,_exception);
anthony805a2d42011-09-25 08:25:12 +00004104 for (j=0; j < number_arguments; j++)
4105 arguments[j]=DestroyString(arguments[j]);
4106 arguments=(char **) RelinquishMagickMemory(arguments);
4107 break;
4108 }
4109 break;
4110 }
4111 case 'r':
4112 {
anthonyafa3dfc2012-03-03 11:31:30 +00004113 if (LocaleCompare("remap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004114 {
anthony92c93bd2012-03-19 14:02:47 +00004115 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
4116 (void) RemapImages(_quantize_info,_images,(Image *) NULL,_exception);
anthony31f1bf72012-01-30 12:37:22 +00004117 break;
4118 }
anthonyafa3dfc2012-03-03 11:31:30 +00004119 if (LocaleCompare("reverse",option+1) == 0)
anthony31f1bf72012-01-30 12:37:22 +00004120 {
anthony92c93bd2012-03-19 14:02:47 +00004121 ReverseImageList(&_images);
anthony805a2d42011-09-25 08:25:12 +00004122 break;
4123 }
4124 break;
4125 }
4126 case 's':
4127 {
anthonyafa3dfc2012-03-03 11:31:30 +00004128 if (LocaleCompare("smush",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004129 {
4130 Image
4131 *smush_image;
4132
4133 ssize_t
4134 offset;
4135
anthony31f1bf72012-01-30 12:37:22 +00004136 offset=(ssize_t) StringToLong(arg1);
anthony92c93bd2012-03-19 14:02:47 +00004137 smush_image=SmushImages(_images,normal_op,offset,_exception);
anthony805a2d42011-09-25 08:25:12 +00004138 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004139 break;
anthony92c93bd2012-03-19 14:02:47 +00004140 _images=DestroyImageList(_images);
4141 _images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004142 break;
4143 }
anthonyafa3dfc2012-03-03 11:31:30 +00004144 if (LocaleCompare("swap",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004145 {
4146 Image
4147 *p,
4148 *q,
4149 *swap;
4150
4151 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004152 index,
anthony805a2d42011-09-25 08:25:12 +00004153 swap_index;
4154
anthony31f1bf72012-01-30 12:37:22 +00004155 index=-1;
4156 swap_index=-2;
anthonyafa3dfc2012-03-03 11:31:30 +00004157 if (IfNormalOp)
anthony805a2d42011-09-25 08:25:12 +00004158 {
4159 GeometryInfo
4160 geometry_info;
4161
4162 MagickStatusType
4163 flags;
4164
4165 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004166 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004167 index=(ssize_t) geometry_info.rho;
4168 if ((flags & SigmaValue) != 0)
4169 swap_index=(ssize_t) geometry_info.sigma;
4170 }
anthony92c93bd2012-03-19 14:02:47 +00004171 p=GetImageFromList(_images,index);
4172 q=GetImageFromList(_images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004173 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4174 {
anthony92c93bd2012-03-19 14:02:47 +00004175 (void) ThrowMagickException(_exception,GetMagickModule(),
4176 OptionError,"NoSuchImage","'%s'",_images->filename);
anthony805a2d42011-09-25 08:25:12 +00004177 break;
4178 }
4179 if (p == q)
4180 break;
anthony92c93bd2012-03-19 14:02:47 +00004181 swap=CloneImage(p,0,0,MagickTrue,_exception);
4182 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,_exception));
anthony805a2d42011-09-25 08:25:12 +00004183 ReplaceImageInList(&q,swap);
anthony92c93bd2012-03-19 14:02:47 +00004184 _images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004185 break;
4186 }
4187 break;
4188 }
4189 case 'w':
4190 {
anthonyafa3dfc2012-03-03 11:31:30 +00004191 if (LocaleCompare("write",option+1) == 0)
anthony805a2d42011-09-25 08:25:12 +00004192 {
4193 char
4194 key[MaxTextExtent];
4195
4196 Image
4197 *write_images;
4198
4199 ImageInfo
4200 *write_info;
4201
anthony31f1bf72012-01-30 12:37:22 +00004202 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004203 (void) DeleteImageRegistry(key);
anthony92c93bd2012-03-19 14:02:47 +00004204 write_images=_images;
anthonyafa3dfc2012-03-03 11:31:30 +00004205 if (IfPlusOp)
anthony92c93bd2012-03-19 14:02:47 +00004206 write_images=CloneImageList(_images,_exception);
4207 write_info=CloneImageInfo(_image_info);
4208 (void) WriteImages(write_info,write_images,arg1,_exception);
anthony805a2d42011-09-25 08:25:12 +00004209 write_info=DestroyImageInfo(write_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004210 if (IfPlusOp)
anthony805a2d42011-09-25 08:25:12 +00004211 write_images=DestroyImageList(write_images);
4212 break;
4213 }
4214 break;
4215 }
4216 default:
4217 break;
4218 }
anthony31f1bf72012-01-30 12:37:22 +00004219 if (new_images == (Image *) NULL)
4220 return;
anthony805a2d42011-09-25 08:25:12 +00004221
anthony92c93bd2012-03-19 14:02:47 +00004222 if (_images != (Image *) NULL)
4223 _images=DestroyImageList(_images);
4224 _images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004225 return;
4226
anthony92c93bd2012-03-19 14:02:47 +00004227#undef _image_info
4228#undef _images
4229#undef _exception
4230#undef _draw_info
4231#undef _quantize_info
anthonyafa3dfc2012-03-03 11:31:30 +00004232#undef IfNormalOp
4233#undef IfPlusOp
anthony31f1bf72012-01-30 12:37:22 +00004234#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004235}
anthony43f425d2012-02-26 12:58:58 +00004236
4237/*
4238%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4239% %
4240% %
4241% %
4242+ C L I S p e c i a l O p e r a t i o n s %
4243% %
4244% %
4245% %
4246%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4247%
4248% CLISpecialOption() Applies operations that may involve empty image lists
4249% and or stacks of image lists or image_info settings.
4250%
anthonyafa3dfc2012-03-03 11:31:30 +00004251% The classic operators of this type is -read, and image stack operators,
4252% which can be applied to empty image lists.
4253%
4254% Note: unlike other Operators, these may involve other special 'option'
4255% character prefixes, other than simply '-' or '+'.
anthony43f425d2012-02-26 12:58:58 +00004256%
4257% The format of the CLISpecialOption method is:
4258%
4259% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
anthony24aa8822012-03-11 00:56:06 +00004260% const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004261%
4262% A description of each parameter follows:
4263%
4264% o cli_wand: the main CLI Wand to use.
4265%
4266% o option: The special option (with any switch char) to process
4267%
anthony24aa8822012-03-11 00:56:06 +00004268% o arg1: Argument for option, if required
anthonyafa3dfc2012-03-03 11:31:30 +00004269%
anthony2052d272012-02-28 12:48:29 +00004270% Example Usage...
4271%
anthonyce8dcb32012-03-21 13:20:31 +00004272% CLISpecialOperator(cli_wand,"-read","rose:");
anthony2052d272012-02-28 12:48:29 +00004273%
anthony24aa8822012-03-11 00:56:06 +00004274% Or for handling command line arguments EG: +/-option ["arg1"]
anthony2052d272012-02-28 12:48:29 +00004275%
4276% cli_wand
4277% argc,argv
4278% i=index in argv
4279%
4280% option_info = GetCommandOptionInfo(argv[i]);
4281% count=option_info->type;
4282% option_type=option_info->flags;
4283%
4284% if ( (option_type & SpecialOptionFlag) != 0 )
4285% CLISpecialOperator(cli_wand,argv[i],
4286% count>=1 ? argv[i+1] : (char *)NULL);
4287% i += count+1;
anthony43f425d2012-02-26 12:58:58 +00004288%
4289*/
4290
anthony43f425d2012-02-26 12:58:58 +00004291WandExport void CLISpecialOperator(MagickCLI *cli_wand,
anthony24aa8822012-03-11 00:56:06 +00004292 const char *option, const char *arg1)
anthony43f425d2012-02-26 12:58:58 +00004293{
anthony92c93bd2012-03-19 14:02:47 +00004294#define _exception (cli_wand->wand.exception)
anthony43f425d2012-02-26 12:58:58 +00004295
4296 assert(cli_wand != (MagickCLI *) NULL);
4297 assert(cli_wand->signature == WandSignature);
4298 assert(cli_wand->wand.signature == WandSignature);
4299 if (cli_wand->wand.debug != MagickFalse)
4300 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4301
anthony24aa8822012-03-11 00:56:06 +00004302 if(cli_wand->wand.images != (Image *)NULL)
4303 (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
anthony92c93bd2012-03-19 14:02:47 +00004304 _exception);
anthony24aa8822012-03-11 00:56:06 +00004305
anthonyce8dcb32012-03-21 13:20:31 +00004306 if (LocaleCompare("respect-parenthesis",option+1) == 0) {
4307 /* image-setting stack linkage */
4308 (void) SetImageOption(cli_wand->wand.image_info,option+1,
4309 *option == '-' ? "true" : (char *) NULL);
4310 return;
4311 }
4312 if (LocaleCompare("(",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004313 /* stack 'push' images */
4314 Stack
4315 *node;
4316
4317 size_t
4318 size;
4319
anthony43f425d2012-02-26 12:58:58 +00004320 size=0;
4321 node=cli_wand->image_list_stack;
4322 for ( ; node != (Stack *)NULL; node=node->next)
4323 size++;
anthonyafa3dfc2012-03-03 11:31:30 +00004324 if ( size >= MAX_STACK_DEPTH )
anthony92c93bd2012-03-19 14:02:47 +00004325 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004326 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4327 if (node == (Stack *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004328 CLIWandExceptionReturn(ResourceLimitFatalError,
4329 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004330 node->data = (void *)cli_wand->wand.images;
4331 cli_wand->wand.images = NewImageList();
4332 node->next = cli_wand->image_list_stack;
4333 cli_wand->image_list_stack = node;
4334
4335 /* handle respect-parenthesis */
anthonyce8dcb32012-03-21 13:20:31 +00004336 if ( IsMagickTrue(GetImageOption(cli_wand->wand.image_info,
4337 "respect-parenthesis")) != MagickFalse )
anthony43f425d2012-02-26 12:58:58 +00004338 option="{";
4339 else
4340 return;
4341 }
anthonyce8dcb32012-03-21 13:20:31 +00004342 if (LocaleCompare("{",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004343 /* stack 'push' of image_info settings */
4344 Stack
4345 *node;
4346
4347 size_t
4348 size;
4349
4350 size=0;
4351 node=cli_wand->image_info_stack;
4352 for ( ; node != (Stack *)NULL; node=node->next)
4353 size++;
anthony92c93bd2012-03-19 14:02:47 +00004354 if ( size >= MAX_STACK_DEPTH )
4355 CLIWandExceptionReturn(OptionError,"ParenthesisNestedTooDeeply",option);
anthony43f425d2012-02-26 12:58:58 +00004356 node=(Stack *) AcquireMagickMemory(sizeof(*node));
anthony92c93bd2012-03-19 14:02:47 +00004357 if (node == (Stack *) NULL)
4358 CLIWandExceptionReturn(ResourceLimitFatalError,
4359 "MemoryAllocationFailed",option);
anthony43f425d2012-02-26 12:58:58 +00004360
4361 node->data = (void *)cli_wand->wand.image_info;
4362 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
anthonyafa3dfc2012-03-03 11:31:30 +00004363 if (cli_wand->wand.image_info == (ImageInfo *)NULL) {
anthony92c93bd2012-03-19 14:02:47 +00004364 CLIWandException(ResourceLimitFatalError,"MemoryAllocationFailed",
4365 option);
anthonyafa3dfc2012-03-03 11:31:30 +00004366 cli_wand->wand.image_info = (ImageInfo *)node->data;
4367 node = (Stack *)RelinquishMagickMemory(node);
4368 return;
4369 }
anthony43f425d2012-02-26 12:58:58 +00004370
4371 node->next = cli_wand->image_info_stack;
4372 cli_wand->image_info_stack = node;
4373
4374 return;
4375 }
anthonyce8dcb32012-03-21 13:20:31 +00004376 if (LocaleCompare(")",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004377 /* pop images from stack */
4378 Stack
4379 *node;
4380
anthony43f425d2012-02-26 12:58:58 +00004381 node = (void *)cli_wand->image_list_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_list_stack = node->next;
4385
4386 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4387 cli_wand->wand.images= (Image *)node->data;
4388 node = (Stack *)RelinquishMagickMemory(node);
4389
4390 /* handle respect-parenthesis - of the previous 'push' settings */
4391 node = cli_wand->image_info_stack;
4392 if ( node != (Stack *)NULL)
4393 {
anthonyce8dcb32012-03-21 13:20:31 +00004394 if (IsMagickTrue(GetImageOption((ImageInfo *)node->data,
4395 "respect-parenthesis")) != MagickFalse )
4396 { option="}"; fprintf(stderr, "close\n"); }
anthony43f425d2012-02-26 12:58:58 +00004397 else
4398 return;
4399 }
4400 else
4401 return;
4402 }
anthonyce8dcb32012-03-21 13:20:31 +00004403 if (LocaleCompare("}",option) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004404 /* pop image_info settings from stack */
4405 Stack
4406 *node;
4407
4408 node = (void *)cli_wand->image_info_stack;
4409 if ( node == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004410 CLIWandExceptionReturn(OptionError,"UnbalancedParenthesis",option);
anthony43f425d2012-02-26 12:58:58 +00004411 cli_wand->image_info_stack = node->next;
4412
4413 (void) DestroyImageInfo(cli_wand->wand.image_info);
4414 cli_wand->wand.image_info = (ImageInfo *)node->data;
4415 node = (Stack *)RelinquishMagickMemory(node);
4416
4417 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4418 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4419 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4420
4421 return;
4422 }
anthonyce8dcb32012-03-21 13:20:31 +00004423 if (LocaleCompare("clone",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004424 Image
4425 *new_images;
4426
4427 if (*option == '+')
anthony24aa8822012-03-11 00:56:06 +00004428 arg1="-1";
4429 if (IsSceneGeometry(arg1,MagickFalse) == MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004430 CLIWandExceptionReturn(OptionError,"InvalidArgument",option);
anthony43f425d2012-02-26 12:58:58 +00004431 if ( cli_wand->image_list_stack == (Stack *)NULL)
anthony92c93bd2012-03-19 14:02:47 +00004432 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
anthony43f425d2012-02-26 12:58:58 +00004433 new_images = (Image *)cli_wand->image_list_stack->data;
4434 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004435 CLIWandExceptionReturn(OptionError,"UnableToCloneImage",option);
4436 new_images=CloneImages(new_images,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004437 if (new_images == (Image *) NULL)
anthony92c93bd2012-03-19 14:02:47 +00004438 CLIWandExceptionReturn(OptionError,"NoSuchImage",option);
anthony43f425d2012-02-26 12:58:58 +00004439 AppendImageToList(&cli_wand->wand.images,new_images);
4440 return;
4441 }
anthony319dac62012-03-06 04:12:44 +00004442 if ( ( LocaleCompare("read",option+1) == 0 ) ||
anthonyce8dcb32012-03-21 13:20:31 +00004443 ( LocaleCompare("--",option) == 0 ) ) {
anthonyafa3dfc2012-03-03 11:31:30 +00004444#if !USE_WAND_METHODS
anthony43f425d2012-02-26 12:58:58 +00004445 Image *
4446 new_images;
4447
anthony43f425d2012-02-26 12:58:58 +00004448 if (cli_wand->wand.image_info->ping != MagickFalse)
anthony92c93bd2012-03-19 14:02:47 +00004449 new_images=PingImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004450 else
anthony92c93bd2012-03-19 14:02:47 +00004451 new_images=ReadImages(cli_wand->wand.image_info,arg1,_exception);
anthony43f425d2012-02-26 12:58:58 +00004452 AppendImageToList(&cli_wand->wand.images, new_images);
4453#else
4454 /* read images using MagickWand method - no ping */
4455 /* This is not working! - it locks up in a CPU loop! */
4456 MagickSetLastIterator(&cli_wand->wand);
anthony24aa8822012-03-11 00:56:06 +00004457 MagickReadImage(&cli_wand->wand,arg1);
anthony43f425d2012-02-26 12:58:58 +00004458 MagickSetFirstIterator(&cli_wand->wand);
4459#endif
4460 return;
4461 }
anthonyafa3dfc2012-03-03 11:31:30 +00004462 /* No-op options */
4463 if (LocaleCompare("noop",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004464 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004465 if (LocaleCompare("sans",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004466 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004467 if (LocaleCompare("sans0",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004468 return;
anthonyafa3dfc2012-03-03 11:31:30 +00004469 if (LocaleCompare("sans2",option+1) == 0)
anthony43f425d2012-02-26 12:58:58 +00004470 return;
anthonyce8dcb32012-03-21 13:20:31 +00004471 if (LocaleCompare("list",option+1) == 0) {
anthony43f425d2012-02-26 12:58:58 +00004472 /* FUTURE: This should really be built into the MagickCore
4473 It does not actually require any wand or images at all!
4474 */
4475 ssize_t
4476 list;
4477
anthony24aa8822012-03-11 00:56:06 +00004478 list=ParseCommandOption(MagickListOptions,MagickFalse, arg1);
anthony43f425d2012-02-26 12:58:58 +00004479 switch (list)
4480 {
4481 case MagickCoderOptions:
4482 {
anthony92c93bd2012-03-19 14:02:47 +00004483 (void) ListCoderInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004484 break;
4485 }
4486 case MagickColorOptions:
4487 {
anthony92c93bd2012-03-19 14:02:47 +00004488 (void) ListColorInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004489 break;
4490 }
4491 case MagickConfigureOptions:
4492 {
anthony92c93bd2012-03-19 14:02:47 +00004493 (void) ListConfigureInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004494 break;
4495 }
4496 case MagickDelegateOptions:
4497 {
anthony92c93bd2012-03-19 14:02:47 +00004498 (void) ListDelegateInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004499 break;
4500 }
4501 case MagickFontOptions:
4502 {
anthony92c93bd2012-03-19 14:02:47 +00004503 (void) ListTypeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004504 break;
4505 }
4506 case MagickFormatOptions:
anthony92c93bd2012-03-19 14:02:47 +00004507 (void) ListMagickInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004508 break;
4509 case MagickLocaleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004510 (void) ListLocaleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004511 break;
4512 case MagickLogOptions:
anthony92c93bd2012-03-19 14:02:47 +00004513 (void) ListLogInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004514 break;
4515 case MagickMagicOptions:
anthony92c93bd2012-03-19 14:02:47 +00004516 (void) ListMagicInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004517 break;
4518 case MagickMimeOptions:
anthony92c93bd2012-03-19 14:02:47 +00004519 (void) ListMimeInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004520 break;
4521 case MagickModuleOptions:
anthony92c93bd2012-03-19 14:02:47 +00004522 (void) ListModuleInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004523 break;
4524 case MagickPolicyOptions:
anthony92c93bd2012-03-19 14:02:47 +00004525 (void) ListPolicyInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004526 break;
4527 case MagickResourceOptions:
anthony92c93bd2012-03-19 14:02:47 +00004528 (void) ListMagickResourceInfo((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004529 break;
4530 case MagickThresholdOptions:
anthony92c93bd2012-03-19 14:02:47 +00004531 (void) ListThresholdMaps((FILE *) NULL,_exception);
anthony43f425d2012-02-26 12:58:58 +00004532 break;
4533 default:
4534 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
anthony92c93bd2012-03-19 14:02:47 +00004535 _exception);
anthony43f425d2012-02-26 12:58:58 +00004536 break;
4537 }
4538 return;
4539 }
4540
4541#if 0
4542 // adjust stack handling
4543 // Other 'special' options this should handle
4544 // "region" "list" "version"
4545 // It does not do "exit" however as due to its side-effect requirements
4546#endif
4547#if 0
4548 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
4549 MagickExceptionReturn(OptionError,"InvalidUseOfOption",option);
4550#endif
4551
anthony92c93bd2012-03-19 14:02:47 +00004552#undef _exception
anthony43f425d2012-02-26 12:58:58 +00004553}