blob: 80ea2125fab13c1f6718eec8b4d93ee6f667b4d1 [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"
anthony43f425d2012-02-26 12:58:58 +000053#include "MagickWand/magick-cli-private.h"
anthonyfd706f92012-01-19 04:22:02 +000054#include "MagickWand/operation.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*/
63#define UndefinedCompressionQuality 0UL
64/*
65 Constant declaration. (temporary exports)
66*/
67static const char
68 BackgroundColor[] = "#fff", /* white */
anthony72feaa62012-01-17 06:46:23 +000069 BorderColor[] = "#dfdfdf", /* sRGB gray */
70 MatteColor[] = "#bdbdbd"; /* slightly darker gray */
anthony805a2d42011-09-25 08:25:12 +000071
72/*
73** Function to report on the progress of image operations
74*/
75static MagickBooleanType MonitorProgress(const char *text,
76 const MagickOffsetType offset,const MagickSizeType extent,
anthony43f425d2012-02-26 12:58:58 +000077 void *wand_unused(cli_wandent_data))
anthony805a2d42011-09-25 08:25:12 +000078{
79 char
80 message[MaxTextExtent],
81 tag[MaxTextExtent];
82
83 const char
84 *locale_message;
85
86 register char
87 *p;
88
89 if (extent < 2)
90 return(MagickTrue);
91 (void) CopyMagickMemory(tag,text,MaxTextExtent);
92 p=strrchr(tag,'/');
93 if (p != (char *) NULL)
94 *p='\0';
95 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
96 locale_message=GetLocaleMessage(message);
97 if (locale_message == message)
98 locale_message=tag;
99 if (p == (char *) NULL)
100 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
101 locale_message,(long) offset,(unsigned long) extent,(long)
102 (100L*offset/(extent-1)));
103 else
104 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
105 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
106 (100L*offset/(extent-1)));
107 if (offset == (MagickOffsetType) (extent-1))
108 (void) FormatLocaleFile(stderr,"\n");
109 (void) fflush(stderr);
110 return(MagickTrue);
111}
112
113/*
114** GetImageCache() will read an image into a image cache if not already
115** present then return the image that is in the cache under that filename.
116*/
117static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
118 ExceptionInfo *exception)
119{
120 char
121 key[MaxTextExtent];
122
123 ExceptionInfo
124 *sans_exception;
125
126 Image
127 *image;
128
129 ImageInfo
130 *read_info;
131
132 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
133 sans_exception=AcquireExceptionInfo();
134 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
135 sans_exception=DestroyExceptionInfo(sans_exception);
136 if (image != (Image *) NULL)
137 return(image);
138 read_info=CloneImageInfo(image_info);
139 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
140 image=ReadImage(read_info,exception);
141 read_info=DestroyImageInfo(read_info);
142 if (image != (Image *) NULL)
143 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
144 return(image);
145}
146
147/*
anthonya89dd172011-10-04 13:29:35 +0000148 SparseColorOption() parse the complex -sparse-color argument into an
149 an array of floating point values than call SparseColorImage().
150 Argument is a complex mix of floating-point pixel coodinates, and color
151 specifications (or direct floating point numbers). The number of floats
152 needed to represent a color varies depending on teh current channel
153 setting.
anthony43f425d2012-02-26 12:58:58 +0000154
155 This really should be in MagickCore, so that other API's can make use of it.
anthony805a2d42011-09-25 08:25:12 +0000156*/
157static Image *SparseColorOption(const Image *image,
158 const SparseColorMethod method,const char *arguments,
anthony31f1bf72012-01-30 12:37:22 +0000159 ExceptionInfo *exception)
anthony805a2d42011-09-25 08:25:12 +0000160{
161 char
162 token[MaxTextExtent];
163
164 const char
165 *p;
166
167 double
168 *sparse_arguments;
169
170 Image
171 *sparse_image;
172
173 PixelInfo
174 color;
175
176 MagickBooleanType
177 error;
178
179 register size_t
180 x;
181
182 size_t
183 number_arguments,
184 number_colors;
185
186 assert(image != (Image *) NULL);
187 assert(image->signature == MagickSignature);
188 if (image->debug != MagickFalse)
189 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
190 assert(exception != (ExceptionInfo *) NULL);
191 assert(exception->signature == MagickSignature);
192 /*
193 Limit channels according to image - and add up number of color channel.
194 */
195 number_colors=0;
196 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
197 number_colors++;
198 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
199 number_colors++;
200 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
201 number_colors++;
202 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
203 (image->colorspace == CMYKColorspace))
204 number_colors++;
205 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
206 (image->matte != MagickFalse))
207 number_colors++;
208
209 /*
210 Read string, to determine number of arguments needed,
211 */
212 p=arguments;
213 x=0;
214 while( *p != '\0' )
215 {
216 GetMagickToken(p,&p,token);
217 if ( token[0] == ',' ) continue;
anthony31f1bf72012-01-30 12:37:22 +0000218 if ( isalpha((int) token[0]) || token[0] == '#' )
219 x += number_colors; /* color argument found */
anthony805a2d42011-09-25 08:25:12 +0000220 else {
221 x++; /* floating point argument */
222 }
223 }
224 error=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +0000225 /* control points and color values */
226 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
227 number_arguments=x;
anthony805a2d42011-09-25 08:25:12 +0000228 if ( error ) {
229 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000230 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000231 "Invalid number of Arguments");
232 return( (Image *)NULL);
233 }
234
235 /* Allocate and fill in the floating point arguments */
236 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
237 sizeof(*sparse_arguments));
238 if (sparse_arguments == (double *) NULL) {
239 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
240 "MemoryAllocationFailed","%s","SparseColorOption");
241 return( (Image *)NULL);
242 }
243 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
244 sizeof(*sparse_arguments));
245 p=arguments;
246 x=0;
247 while( *p != '\0' && x < number_arguments ) {
248 /* X coordinate */
249 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
250 if ( token[0] == '\0' ) break;
251 if ( isalpha((int) token[0]) || token[0] == '#' ) {
252 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000253 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000254 "Color found, instead of X-coord");
255 error = MagickTrue;
256 break;
257 }
cristydbdd0e32011-11-04 23:29:40 +0000258 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +0000259 /* Y coordinate */
260 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
261 if ( token[0] == '\0' ) break;
262 if ( isalpha((int) token[0]) || token[0] == '#' ) {
263 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +0000264 OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
anthony805a2d42011-09-25 08:25:12 +0000265 "Color found, instead of Y-coord");
266 error = MagickTrue;
267 break;
268 }
cristydbdd0e32011-11-04 23:29:40 +0000269 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
anthony31f1bf72012-01-30 12:37:22 +0000270 /* color name or function given in string argument */
271 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
272 if ( token[0] == '\0' ) break;
273 if ( isalpha((int) token[0]) || token[0] == '#' ) {
274 /* Color string given */
275 (void) QueryColorCompliance(token,AllCompliance,&color,
276 exception);
277 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
278 sparse_arguments[x++] = QuantumScale*color.red;
279 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
280 sparse_arguments[x++] = QuantumScale*color.green;
281 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
282 sparse_arguments[x++] = QuantumScale*color.blue;
283 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
284 (image->colorspace == CMYKColorspace))
285 sparse_arguments[x++] = QuantumScale*color.black;
286 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
287 (image->matte != MagickFalse))
288 sparse_arguments[x++] = QuantumScale*color.alpha;
anthony805a2d42011-09-25 08:25:12 +0000289 }
anthony31f1bf72012-01-30 12:37:22 +0000290 else {
291 /* Colors given as a set of floating point values - experimental */
292 /* NB: token contains the first floating point value to use! */
293 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
294 {
295 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
296 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
297 break;
298 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
299 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000300 }
anthony31f1bf72012-01-30 12:37:22 +0000301 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
302 {
303 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
304 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
305 break;
306 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
307 token[0] = ','; /* used this token - get another */
308 }
309 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
310 {
311 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
312 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
313 break;
314 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
315 token[0] = ','; /* used this token - get another */
316 }
317 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
318 (image->colorspace == CMYKColorspace))
319 {
320 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
321 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
322 break;
323 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
324 token[0] = ','; /* used this token - get another */
325 }
326 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
327 (image->matte != MagickFalse))
328 {
329 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
330 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
331 break;
332 sparse_arguments[x++]=StringToDouble(token,(char **) NULL);
333 token[0] = ','; /* used this token - get another */
anthony805a2d42011-09-25 08:25:12 +0000334 }
335 }
336 }
337 if ( number_arguments != x && !error ) {
338 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
anthony43f425d2012-02-26 12:58:58 +0000339 "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
anthony805a2d42011-09-25 08:25:12 +0000340 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
341 return( (Image *)NULL);
342 }
343 if ( error )
344 return( (Image *)NULL);
345
anthony31f1bf72012-01-30 12:37:22 +0000346 /* Call the Sparse Color Interpolation function with the parsed arguments */
anthony805a2d42011-09-25 08:25:12 +0000347 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
348 exception);
349 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
350 return( sparse_image );
351}
352
353/*
354%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
355% %
356% %
357% %
anthony43f425d2012-02-26 12:58:58 +0000358+ A c q u i r e W a n d C L I %
anthony805a2d42011-09-25 08:25:12 +0000359% %
360% %
361% %
362%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363%
anthony43f425d2012-02-26 12:58:58 +0000364% AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
365% Wand). The given image_info and exception is included as is if provided.
anthony805a2d42011-09-25 08:25:12 +0000366%
anthony43f425d2012-02-26 12:58:58 +0000367% Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
368% needed.
369%
370% The format of the NewMagickWand method is:
371%
372% MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
373% ExceptionInfo *exception)
374%
375*/
376WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
377 ExceptionInfo *exception)
378{
379 MagickCLI
380 *cli_wand;
381
382 /* precaution - as per NewMagickWand() */
383 {
384 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
385 const char *quantum = GetMagickQuantumDepth(&depth);
386 if (depth != MAGICKCORE_QUANTUM_DEPTH)
387 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
388 }
389
390 /* allocate memory for MgaickCLI */
391 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
392 if (cli_wand == (MagickCLI *) NULL)
393 {
394 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
395 GetExceptionMessage(errno));
396 return((MagickCLI *)NULL);
397 }
398
399 /* Initialize Wand Part of MagickCLI
400 FUTURE: this is a repeat of code from NewMagickWand()
401 However some parts may be given fro man external source!
402 */
403 cli_wand->wand.id=AcquireWandId();
404 (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
405 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
406 cli_wand->wand.images=NewImageList();
407 if ( image_info == (ImageInfo *)NULL)
408 cli_wand->wand.image_info=AcquireImageInfo();
409 else
410 cli_wand->wand.image_info=image_info;
411 if ( exception == (ExceptionInfo *)NULL)
412 cli_wand->wand.exception=AcquireExceptionInfo();
413 else
414 cli_wand->wand.exception=exception;
415 cli_wand->wand.debug=IsEventLogging();
416 cli_wand->wand.signature=WandSignature;
417
418 /* Initialize CLI Part of MagickCLI */
419 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
420 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
421 cli_wand->image_list_stack=(Stack *)NULL;
422 cli_wand->image_info_stack=(Stack *)NULL;
423 cli_wand->signature=WandSignature;
424
425 if (cli_wand->wand.debug != MagickFalse)
426 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
427 return(cli_wand);
428}
429
430/*
431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432% %
433% %
434% %
435+ D e s t r o y W a n d C L I %
436% %
437% %
438% %
439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440%
441% DestroyMagickCLI() destorys everything in a CLI wand, including image_info
442% and any exceptions, if still present in the wand.
443%
444% The format of the NewMagickWand method is:
445%
446% MagickWand *DestroyMagickCLI()
447% Exception *exception)
448%
449*/
450WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
451{
452 Stack
453 *node;
454
455 assert(cli_wand != (MagickCLI *) NULL);
456 assert(cli_wand->signature == WandSignature);
457 assert(cli_wand->wand.signature == WandSignature);
458 if (cli_wand->wand.debug != MagickFalse)
459 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
460
461 /* Destroy CLI part of MagickCLI */
462 if (cli_wand->draw_info != (DrawInfo *) NULL )
463 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
464 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
465 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
466 while(cli_wand->image_list_stack != (Stack *)NULL)
467 {
468 node=cli_wand->image_list_stack;
469 cli_wand->image_list_stack=node->next;
470 (void) DestroyImageList((Image *)node->data);
471 (void) RelinquishMagickMemory(node);
472 }
473 while(cli_wand->image_info_stack != (Stack *)NULL)
474 {
475 node=cli_wand->image_info_stack;
476 cli_wand->image_info_stack=node->next;
477 (void) DestroyImageInfo((ImageInfo *)node->data);
478 (void) RelinquishMagickMemory(node);
479 }
480 cli_wand->signature=(~WandSignature);
481
482 /* Destroy Wand part MagickCLI */
483 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
484 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
485 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
486 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
487 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
488 RelinquishWandId(cli_wand->wand.id);
489 cli_wand->wand.signature=(~WandSignature);
490
491 return((MagickCLI *)NULL);
492}
493
494/*
495%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
496% %
497% %
498% %
499+ C L I S e t t i n g O p t i o n I n f o %
500% %
501% %
502% %
503%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504%
505% CLISettingOptionInfo() applies a single settings option into a CLI wand
506% holding the image_info, draw_info, quantize_info structures that will be
507% used when processing the images.
508%
509% These options do no require images to be present in the CLI wand for them
510% to be able to be set, in which case they will generally be applied to image
511% that are read in later
anthony80c37752012-01-16 01:03:11 +0000512%
513% Options handled by this function are listed in CommandOptions[] of
anthonyfd706f92012-01-19 04:22:02 +0000514% "option.c" that is one of "SettingOptionFlags" option flags.
anthony805a2d42011-09-25 08:25:12 +0000515%
anthonyd1447672012-01-19 05:33:53 +0000516% The format of the WandSettingOptionInfo method is:
anthony1afdc7a2011-10-05 11:54:28 +0000517%
anthony43f425d2012-02-26 12:58:58 +0000518% void CLISettingOptionInfo(MagickCLI *cli_wand,const char *option,
anthony31f1bf72012-01-30 12:37:22 +0000519% const char *arg)
anthony805a2d42011-09-25 08:25:12 +0000520%
521% A description of each parameter follows:
522%
anthony43f425d2012-02-26 12:58:58 +0000523% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +0000524%
anthonydcf510d2011-10-30 13:51:40 +0000525% o option: The option string to be set
anthony805a2d42011-09-25 08:25:12 +0000526%
anthony72feaa62012-01-17 06:46:23 +0000527% o arg: The single argument used to set this option.
528% If NULL the setting is reset to its default value.
anthony31f1bf72012-01-30 12:37:22 +0000529% For boolean (no argument) settings false=NULL, true=any_string
anthonydcf510d2011-10-30 13:51:40 +0000530%
anthony72feaa62012-01-17 06:46:23 +0000531% Example usage...
532%
anthony43f425d2012-02-26 12:58:58 +0000533% CLISettingOptionInfo(cli_wand, "background", MagickTrue, "Red");
534% CLISettingOptionInfo(cli_wand, "adjoin", "true");
535% CLISettingOptionInfo(cli_wand, "adjoin", NULL);
anthony72feaa62012-01-17 06:46:23 +0000536%
537% Or for handling command line arguments EG: +/-option ["arg"]
anthonydcf510d2011-10-30 13:51:40 +0000538%
539% argc,argv
540% i=index in argv
541%
542% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
543% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
anthonyfd706f92012-01-19 04:22:02 +0000544% if ( (flags & SettingOptionFlags) != 0 )
anthony43f425d2012-02-26 12:58:58 +0000545% CLISettingOptionInfo(cli_wand, argv[i]+1,
anthonyfd706f92012-01-19 04:22:02 +0000546% (((*argv[i])!='-') ? (char *)NULL
547% : (count>0) ? argv[i+1] : "true") );
anthonydcf510d2011-10-30 13:51:40 +0000548% i += count+1;
549%
anthony805a2d42011-09-25 08:25:12 +0000550*/
anthony43f425d2012-02-26 12:58:58 +0000551WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,const char *option,
anthony31f1bf72012-01-30 12:37:22 +0000552 const char *arg)
anthony805a2d42011-09-25 08:25:12 +0000553{
anthony43f425d2012-02-26 12:58:58 +0000554 assert(cli_wand != (MagickCLI *) NULL);
555 assert(cli_wand->signature == WandSignature);
556 assert(cli_wand->wand.signature == WandSignature);
557 if (cli_wand->wand.debug != MagickFalse)
558 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony1afdc7a2011-10-05 11:54:28 +0000559
anthony43f425d2012-02-26 12:58:58 +0000560#define image_info (cli_wand->wand.image_info)
561#define exception (cli_wand->wand.exception)
562#define draw_info (cli_wand->draw_info)
563#define quantize_info (cli_wand->quantize_info)
anthony72feaa62012-01-17 06:46:23 +0000564#define IfSetOption (arg!=(char *)NULL)
565#define ArgOption(def) (IfSetOption?arg:(const char *)(def))
566#define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
anthony74b1cfc2011-10-06 12:44:16 +0000567
568 switch (*option)
anthony805a2d42011-09-25 08:25:12 +0000569 {
570 case 'a':
571 {
anthony74b1cfc2011-10-06 12:44:16 +0000572 if (LocaleCompare("adjoin",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000573 {
anthony72feaa62012-01-17 06:46:23 +0000574 image_info->adjoin = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000575 break;
576 }
anthony74b1cfc2011-10-06 12:44:16 +0000577 if (LocaleCompare("affine",option) == 0)
anthony1afdc7a2011-10-05 11:54:28 +0000578 {
anthony31f1bf72012-01-30 12:37:22 +0000579 /* DEPRECIATED: draw_info setting only: for -draw and -transform */
anthony74b1cfc2011-10-06 12:44:16 +0000580 if (IfSetOption)
anthony72feaa62012-01-17 06:46:23 +0000581 (void) ParseAffineGeometry(arg,&draw_info->affine,exception);
anthony74b1cfc2011-10-06 12:44:16 +0000582 else
anthony72feaa62012-01-17 06:46:23 +0000583 GetAffineMatrix(&draw_info->affine);
anthony1afdc7a2011-10-05 11:54:28 +0000584 break;
585 }
anthony74b1cfc2011-10-06 12:44:16 +0000586 if (LocaleCompare("antialias",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000587 {
anthony1afdc7a2011-10-05 11:54:28 +0000588 image_info->antialias =
anthony72feaa62012-01-17 06:46:23 +0000589 draw_info->stroke_antialias =
590 draw_info->text_antialias = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +0000591 break;
592 }
anthony31f1bf72012-01-30 12:37:22 +0000593 if (LocaleCompare("attenuate",option+1) == 0)
594 {
595 (void) SetImageOption(image_info,option,ArgOption(NULL));
596 break;
597 }
anthony74b1cfc2011-10-06 12:44:16 +0000598 if (LocaleCompare("authenticate",option) == 0)
anthonydcf510d2011-10-30 13:51:40 +0000599 {
anthony72feaa62012-01-17 06:46:23 +0000600 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000601 break;
602 }
603 break;
604 }
605 case 'b':
606 {
anthony74b1cfc2011-10-06 12:44:16 +0000607 if (LocaleCompare("background",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000608 {
anthony74b1cfc2011-10-06 12:44:16 +0000609 /* FUTURE: both image_info attribute & ImageOption in use!
anthony72feaa62012-01-17 06:46:23 +0000610 image_info only used directly for generating new images.
611 SyncImageSettings() used to set per-image attribute.
612
613 FUTURE: if image_info->background_color is not set then
614 we should fall back to image
615 Note that +background, means fall-back to image background
616 and only if not set fall back to BackgroundColor const.
anthony74b1cfc2011-10-06 12:44:16 +0000617 */
anthony72feaa62012-01-17 06:46:23 +0000618 (void) SetImageOption(image_info,option,ArgOption(NULL));
619 (void) QueryColorCompliance(ArgOption(BackgroundColor),AllCompliance,
620 &image_info->background_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000621 break;
622 }
anthony74b1cfc2011-10-06 12:44:16 +0000623 if (LocaleCompare("bias",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000624 {
anthony74b1cfc2011-10-06 12:44:16 +0000625 /* FUTURE: bias OBSOLETED, replaced by "convolve:bias"
anthony31f1bf72012-01-30 12:37:22 +0000626 as it is actually rarely used except in direct convolve operations
627 Usage outside a direct convolve operation is actally non-sensible!
anthony72feaa62012-01-17 06:46:23 +0000628
629 SyncImageSettings() used to set per-image attribute.
anthony74b1cfc2011-10-06 12:44:16 +0000630 */
anthony72feaa62012-01-17 06:46:23 +0000631 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000632 break;
633 }
anthony74b1cfc2011-10-06 12:44:16 +0000634 if (LocaleCompare("black-point-compensation",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000635 {
anthony72feaa62012-01-17 06:46:23 +0000636 /* Used as a image chromaticity setting
637 SyncImageSettings() used to set per-image attribute.
638 */
anthony74b1cfc2011-10-06 12:44:16 +0000639 (void) SetImageOption(image_info,option,
640 IfSetOption ? "true" : "false" );
anthony805a2d42011-09-25 08:25:12 +0000641 break;
642 }
anthony74b1cfc2011-10-06 12:44:16 +0000643 if (LocaleCompare("blue-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000644 {
anthonyafbaed72011-10-26 12:05:04 +0000645 /* Image chromaticity X,Y NB: Y=X if Y not defined
646 Used by many coders including PNG
anthony72feaa62012-01-17 06:46:23 +0000647 SyncImageSettings() used to set per-image attribute.
anthonyafbaed72011-10-26 12:05:04 +0000648 */
anthony72feaa62012-01-17 06:46:23 +0000649 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000650 break;
651 }
anthony74b1cfc2011-10-06 12:44:16 +0000652 if (LocaleCompare("bordercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000653 {
anthony72feaa62012-01-17 06:46:23 +0000654 /* FUTURE: both image_info attribute & ImageOption in use!
655 SyncImageSettings() used to set per-image attribute.
656 */
anthony74b1cfc2011-10-06 12:44:16 +0000657 if (IfSetOption)
anthony805a2d42011-09-25 08:25:12 +0000658 {
anthonydcf510d2011-10-30 13:51:40 +0000659 (void) SetImageOption(image_info,option,arg);
anthony72feaa62012-01-17 06:46:23 +0000660 (void) QueryColorCompliance(arg,AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000661 &image_info->border_color,exception);
anthonydcf510d2011-10-30 13:51:40 +0000662 (void) QueryColorCompliance(arg,AllCompliance,
anthony74b1cfc2011-10-06 12:44:16 +0000663 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000664 break;
665 }
anthony74b1cfc2011-10-06 12:44:16 +0000666 (void) DeleteImageOption(image_info,option);
667 (void) QueryColorCompliance(BorderColor,AllCompliance,
668 &image_info->border_color,exception);
669 (void) QueryColorCompliance(BorderColor,AllCompliance,
670 &draw_info->border_color,exception);
anthony805a2d42011-09-25 08:25:12 +0000671 break;
672 }
anthony74b1cfc2011-10-06 12:44:16 +0000673 if (LocaleCompare("box",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000674 {
anthonyfd706f92012-01-19 04:22:02 +0000675 /* DEPRECIATED - now "undercolor" */
anthony43f425d2012-02-26 12:58:58 +0000676 CLISettingOptionInfo(cli_wand,"undercolor",arg);
anthonyfd706f92012-01-19 04:22:02 +0000677 break;
anthony805a2d42011-09-25 08:25:12 +0000678 }
679 break;
680 }
681 case 'c':
682 {
anthony74b1cfc2011-10-06 12:44:16 +0000683 if (LocaleCompare("cache",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000684 {
685 MagickSizeType
686 limit;
687
688 limit=MagickResourceInfinity;
anthonydcf510d2011-10-30 13:51:40 +0000689 if (LocaleCompare("unlimited",arg) != 0)
cristy9b34e302011-11-05 02:15:45 +0000690 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg,100.0);
anthony805a2d42011-09-25 08:25:12 +0000691 (void) SetMagickResourceLimit(MemoryResource,limit);
692 (void) SetMagickResourceLimit(MapResource,2*limit);
693 break;
694 }
anthony74b1cfc2011-10-06 12:44:16 +0000695 if (LocaleCompare("caption",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000696 {
anthony72feaa62012-01-17 06:46:23 +0000697 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000698 break;
699 }
anthony74b1cfc2011-10-06 12:44:16 +0000700 if (LocaleCompare("channel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000701 {
anthony43f425d2012-02-26 12:58:58 +0000702 /* FUTURE: -channel mask {vaules}
703 This is applied to images in SimpleImageOperator!!!
704 Move it to SyncImageSettings() - or alternative
anthony31f1bf72012-01-30 12:37:22 +0000705 */
anthony74b1cfc2011-10-06 12:44:16 +0000706 image_info->channel=(ChannelType) (
anthonydcf510d2011-10-30 13:51:40 +0000707 IfSetOption ? ParseChannelOption(arg) : DefaultChannels );
anthony805a2d42011-09-25 08:25:12 +0000708 break;
709 }
anthony74b1cfc2011-10-06 12:44:16 +0000710 if (LocaleCompare("colorspace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000711 {
anthonyafbaed72011-10-26 12:05:04 +0000712 /* Setting used for new images via AquireImage()
713 But also used as a SimpleImageOperator
714 Undefined colorspace means don't modify images on
715 read or as a operation */
anthony72feaa62012-01-17 06:46:23 +0000716 image_info->colorspace=(ColorspaceType) ParseCommandOption(
717 MagickColorspaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000718 break;
719 }
anthony74b1cfc2011-10-06 12:44:16 +0000720 if (LocaleCompare("comment",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000721 {
anthony72feaa62012-01-17 06:46:23 +0000722 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000723 break;
724 }
anthony74b1cfc2011-10-06 12:44:16 +0000725 if (LocaleCompare("compose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000726 {
anthony72feaa62012-01-17 06:46:23 +0000727 /* FUTURE: image_info should be used,
728 SyncImageSettings() used to set per-image attribute. - REMOVE
729
anthonyafbaed72011-10-26 12:05:04 +0000730 This setting should NOT be used to set image 'compose'
anthony72feaa62012-01-17 06:46:23 +0000731 "-layer" operators shoud use image_info if defined otherwise
732 they should use a per-image compose setting.
anthony965524b2011-10-07 12:34:14 +0000733 */
anthony72feaa62012-01-17 06:46:23 +0000734 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony965524b2011-10-07 12:34:14 +0000735 image_info->compose=(CompositeOperator) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000736 MagickComposeOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000737 break;
738 }
anthony74b1cfc2011-10-06 12:44:16 +0000739 if (LocaleCompare("compress",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000740 {
anthony5f867ae2011-10-09 10:28:34 +0000741 /* FUTURE: What should be used? image_info or ImageOption ???
742 The former is more efficent, but Crisy prefers the latter!
anthony72feaa62012-01-17 06:46:23 +0000743 SyncImageSettings() used to set per-image attribute.
anthony5f867ae2011-10-09 10:28:34 +0000744
745 The coders appears to use image_info, not Image_Option
746 however the image attribute (for save) is set from the
747 ImageOption!
anthony72feaa62012-01-17 06:46:23 +0000748
749 Note that "undefined" is a different setting to "none".
anthony5f867ae2011-10-09 10:28:34 +0000750 */
anthony72feaa62012-01-17 06:46:23 +0000751 (void) SetImageOption(image_info,option,ArgOption(NULL));
752 image_info->compression=(CompressionType) ParseCommandOption(
753 MagickCompressOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000754 break;
755 }
756 break;
757 }
758 case 'd':
759 {
anthony74b1cfc2011-10-06 12:44:16 +0000760 if (LocaleCompare("debug",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000761 {
anthony72feaa62012-01-17 06:46:23 +0000762 /* SyncImageSettings() used to set per-image attribute. */
763 (void) SetLogEventMask(ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000764 image_info->debug=IsEventLogging(); /* extract logging*/
anthony43f425d2012-02-26 12:58:58 +0000765 cli_wand->wand.debug=IsEventLogging();
anthony805a2d42011-09-25 08:25:12 +0000766 break;
767 }
anthony74b1cfc2011-10-06 12:44:16 +0000768 if (LocaleCompare("define",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000769 {
anthony72feaa62012-01-17 06:46:23 +0000770 /* DefineImageOption() equals SetImageOption() but with '='
771 It does not however set individual image options.
772 -set will set individual image options as well!
anthony5f867ae2011-10-09 10:28:34 +0000773 */
anthonydcf510d2011-10-30 13:51:40 +0000774 if (LocaleNCompare(arg,"registry:",9) == 0)
anthony805a2d42011-09-25 08:25:12 +0000775 {
anthony5f867ae2011-10-09 10:28:34 +0000776 if (IfSetOption)
anthonydcf510d2011-10-30 13:51:40 +0000777 (void) DefineImageRegistry(StringRegistryType,arg+9,
anthony5f867ae2011-10-09 10:28:34 +0000778 exception);
779 else
anthony72feaa62012-01-17 06:46:23 +0000780 (void) DeleteImageRegistry(arg+9);
anthony805a2d42011-09-25 08:25:12 +0000781 break;
782 }
anthony5f867ae2011-10-09 10:28:34 +0000783 if (IfSetOption)
anthony72feaa62012-01-17 06:46:23 +0000784 (void) DefineImageOption(image_info,arg);
anthony5f867ae2011-10-09 10:28:34 +0000785 else
anthony72feaa62012-01-17 06:46:23 +0000786 (void) DeleteImageOption(image_info,arg);
anthony805a2d42011-09-25 08:25:12 +0000787 break;
788 }
anthony74b1cfc2011-10-06 12:44:16 +0000789 if (LocaleCompare("delay",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000790 {
anthonyafbaed72011-10-26 12:05:04 +0000791 /* Only used for new images via AcquireImage()
792 FUTURE: Option should also be used for "-morph" (color morphing)
anthony5f867ae2011-10-09 10:28:34 +0000793 */
anthony72feaa62012-01-17 06:46:23 +0000794 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +0000795 break;
796 }
anthony74b1cfc2011-10-06 12:44:16 +0000797 if (LocaleCompare("density",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000798 {
anthony72feaa62012-01-17 06:46:23 +0000799 /* FUTURE: strings used in image_info attr and draw_info!
800 Basically as density can be in a XxY form!
801
802 SyncImageSettings() used to set per-image attribute.
803 */
804 (void) SetImageOption(image_info,option,ArgOption(NULL));
805 (void) CloneString(&image_info->density,ArgOption(NULL));
806 (void) CloneString(&draw_info->density,image_info->density);
anthony805a2d42011-09-25 08:25:12 +0000807 break;
808 }
anthony74b1cfc2011-10-06 12:44:16 +0000809 if (LocaleCompare("depth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000810 {
anthony72feaa62012-01-17 06:46:23 +0000811 /* This is also a SimpleImageOperator! for 8->16 vaule trunc !!!!
812 SyncImageSettings() used to set per-image attribute.
813 */
anthonydcf510d2011-10-30 13:51:40 +0000814 image_info->depth=IfSetOption?StringToUnsignedLong(arg)
anthony5f867ae2011-10-09 10:28:34 +0000815 :MAGICKCORE_QUANTUM_DEPTH;
anthony805a2d42011-09-25 08:25:12 +0000816 break;
817 }
anthony74b1cfc2011-10-06 12:44:16 +0000818 if (LocaleCompare("direction",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000819 {
anthony6dc09cd2011-10-12 08:56:49 +0000820 /* Image Option is only used to set draw_info */
anthony72feaa62012-01-17 06:46:23 +0000821 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony5f867ae2011-10-09 10:28:34 +0000822 draw_info->direction=(DirectionType) ParseCommandOption(
823 MagickDirectionOptions,MagickFalse,
anthony72feaa62012-01-17 06:46:23 +0000824 ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000825 break;
826 }
anthony74b1cfc2011-10-06 12:44:16 +0000827 if (LocaleCompare("display",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000828 {
anthony72feaa62012-01-17 06:46:23 +0000829 (void) CloneString(&image_info->server_name,ArgOption(NULL));
830 (void) CloneString(&draw_info->server_name,image_info->server_name);
anthony805a2d42011-09-25 08:25:12 +0000831 break;
832 }
anthony74b1cfc2011-10-06 12:44:16 +0000833 if (LocaleCompare("dispose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000834 {
anthony72feaa62012-01-17 06:46:23 +0000835 /* only used in setting new images */
836 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000837 break;
838 }
anthony74b1cfc2011-10-06 12:44:16 +0000839 if (LocaleCompare("dither",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000840 {
anthony72feaa62012-01-17 06:46:23 +0000841 /* image_info attr (on/off), quantize_info attr (on/off)
842 but also ImageInfo and quantize_info method!
843 FUTURE: merge the duality of the dithering options
844 */
845 image_info->dither = quantize_info->dither = ArgBoolean;
846 (void) SetImageOption(image_info,option,ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000847 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000848 MagickDitherOptions,MagickFalse,ArgOption("none"));
anthony5f867ae2011-10-09 10:28:34 +0000849 if (quantize_info->dither_method == NoDitherMethod)
anthony72feaa62012-01-17 06:46:23 +0000850 image_info->dither = quantize_info->dither = MagickFalse;
anthony805a2d42011-09-25 08:25:12 +0000851 break;
852 }
853 break;
854 }
855 case 'e':
856 {
anthony74b1cfc2011-10-06 12:44:16 +0000857 if (LocaleCompare("encoding",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000858 {
anthony72feaa62012-01-17 06:46:23 +0000859 (void) CloneString(&draw_info->encoding,ArgOption("undefined"));
860 (void) SetImageOption(image_info,option,draw_info->encoding);
anthony805a2d42011-09-25 08:25:12 +0000861 break;
862 }
anthony74b1cfc2011-10-06 12:44:16 +0000863 if (LocaleCompare("endian",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000864 {
anthony72feaa62012-01-17 06:46:23 +0000865 /* Both image_info attr and ImageInfo */
866 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000867 image_info->endian=(EndianType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000868 MagickEndianOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000869 break;
870 }
anthony74b1cfc2011-10-06 12:44:16 +0000871 if (LocaleCompare("extract",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000872 {
anthony72feaa62012-01-17 06:46:23 +0000873 (void) CloneString(&image_info->extract,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000874 break;
875 }
876 break;
877 }
878 case 'f':
879 {
anthony72feaa62012-01-17 06:46:23 +0000880 if (LocaleCompare("family",option) == 0)
anthony6dc09cd2011-10-12 08:56:49 +0000881 {
anthony72feaa62012-01-17 06:46:23 +0000882 (void) CloneString(&draw_info->family,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000883 break;
884 }
anthony74b1cfc2011-10-06 12:44:16 +0000885 if (LocaleCompare("fill",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000886 {
anthonyfd706f92012-01-19 04:22:02 +0000887 /* Set "fill" OR "fill-pattern" in draw_info
888 The original fill color is preserved if a fill-pattern is given.
889 That way it does not effect other operations that directly using
890 the fill color and, can be retored using "+tile".
anthonyafbaed72011-10-26 12:05:04 +0000891 */
anthony6dc09cd2011-10-12 08:56:49 +0000892 const char
anthony72feaa62012-01-17 06:46:23 +0000893 *value;
894
895 MagickBooleanType
896 status;
anthony6dc09cd2011-10-12 08:56:49 +0000897
898 ExceptionInfo
899 *sans;
900
anthonyfd706f92012-01-19 04:22:02 +0000901 PixelInfo
902 color;
903
anthony72feaa62012-01-17 06:46:23 +0000904 value = ArgOption("none");
anthony6dc09cd2011-10-12 08:56:49 +0000905 (void) SetImageOption(image_info,option,value);
anthony6dc09cd2011-10-12 08:56:49 +0000906 if (draw_info->fill_pattern != (Image *) NULL)
907 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
anthony72feaa62012-01-17 06:46:23 +0000908
909 /* is it a color or a image? -- ignore exceptions */
910 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +0000911 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthony72feaa62012-01-17 06:46:23 +0000912 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +0000913
anthony6dc09cd2011-10-12 08:56:49 +0000914 if (status == MagickFalse)
anthony72feaa62012-01-17 06:46:23 +0000915 draw_info->fill_pattern=GetImageCache(image_info,value,exception);
anthonyfd706f92012-01-19 04:22:02 +0000916 else
917 draw_info->fill=color;
anthony805a2d42011-09-25 08:25:12 +0000918 break;
919 }
anthony74b1cfc2011-10-06 12:44:16 +0000920 if (LocaleCompare("filter",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000921 {
anthony72feaa62012-01-17 06:46:23 +0000922 /* SyncImageSettings() used to set per-image attribute. */
923 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000924 break;
925 }
anthonydcf510d2011-10-30 13:51:40 +0000926 if (LocaleCompare("font",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000927 {
anthony72feaa62012-01-17 06:46:23 +0000928 (void) CloneString(&draw_info->font,ArgOption(NULL));
anthony6dc09cd2011-10-12 08:56:49 +0000929 (void) CloneString(&image_info->font,draw_info->font);
anthony805a2d42011-09-25 08:25:12 +0000930 break;
931 }
anthony74b1cfc2011-10-06 12:44:16 +0000932 if (LocaleCompare("format",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000933 {
anthonydcf510d2011-10-30 13:51:40 +0000934 /* FUTURE: why the ping test, you could set ping after this! */
935 /*
anthony805a2d42011-09-25 08:25:12 +0000936 register const char
937 *q;
938
anthonydcf510d2011-10-30 13:51:40 +0000939 for (q=strchr(arg,'%'); q != (char *) NULL; q=strchr(q+1,'%'))
anthony805a2d42011-09-25 08:25:12 +0000940 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
941 image_info->ping=MagickFalse;
anthonydcf510d2011-10-30 13:51:40 +0000942 */
anthony72feaa62012-01-17 06:46:23 +0000943 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +0000944 break;
945 }
anthony74b1cfc2011-10-06 12:44:16 +0000946 if (LocaleCompare("fuzz",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000947 {
anthony72feaa62012-01-17 06:46:23 +0000948 /* Option used to set image fuzz! unless blank canvas (from color)
anthonydcf510d2011-10-30 13:51:40 +0000949 Image attribute used for color compare operations
anthony72feaa62012-01-17 06:46:23 +0000950 SyncImageSettings() used to set per-image attribute.
951
952 Can't find anything else using image_info->fuzz directly!
anthony6613bf32011-10-15 07:24:44 +0000953 */
954 if (IfSetOption)
cristy947cb4c2011-10-20 18:41:46 +0000955 {
anthony80c37752012-01-16 01:03:11 +0000956 image_info->fuzz=StringToDoubleInterval(arg,(double)
957 QuantumRange+1.0);
anthonydcf510d2011-10-30 13:51:40 +0000958 (void) SetImageOption(image_info,option,arg);
cristy947cb4c2011-10-20 18:41:46 +0000959 break;
960 }
961 image_info->fuzz=0.0;
962 (void) SetImageOption(image_info,option,"0");
anthony805a2d42011-09-25 08:25:12 +0000963 break;
964 }
965 break;
966 }
967 case 'g':
968 {
anthony74b1cfc2011-10-06 12:44:16 +0000969 if (LocaleCompare("gravity",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000970 {
anthony72feaa62012-01-17 06:46:23 +0000971 /* SyncImageSettings() used to set per-image attribute. */
972 (void) SetImageOption(image_info,option,ArgOption("none"));
anthony6dc09cd2011-10-12 08:56:49 +0000973 draw_info->gravity=(GravityType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +0000974 MagickGravityOptions,MagickFalse,ArgOption("none"));
anthony805a2d42011-09-25 08:25:12 +0000975 break;
976 }
anthony74b1cfc2011-10-06 12:44:16 +0000977 if (LocaleCompare("green-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000978 {
anthonydcf510d2011-10-30 13:51:40 +0000979 /* Image chromaticity X,Y NB: Y=X if Y not defined
anthony72feaa62012-01-17 06:46:23 +0000980 SyncImageSettings() used to set per-image attribute.
981 Used directly by many coders
anthonydcf510d2011-10-30 13:51:40 +0000982 */
anthony72feaa62012-01-17 06:46:23 +0000983 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +0000984 break;
985 }
986 break;
987 }
988 case 'i':
989 {
anthony74b1cfc2011-10-06 12:44:16 +0000990 if (LocaleCompare("intent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +0000991 {
anthony72feaa62012-01-17 06:46:23 +0000992 /* Only used by coders: MIFF, MPC, BMP, PNG
anthonydcf510d2011-10-30 13:51:40 +0000993 and for image profile call to AcquireTransformThreadSet()
anthony72feaa62012-01-17 06:46:23 +0000994 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +0000995 */
anthony72feaa62012-01-17 06:46:23 +0000996 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +0000997 break;
998 }
anthony74b1cfc2011-10-06 12:44:16 +0000999 if (LocaleCompare("interlace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001000 {
anthony72feaa62012-01-17 06:46:23 +00001001 /* image_info is directly used by coders (so why an image setting?)
1002 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001003 */
anthony72feaa62012-01-17 06:46:23 +00001004 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001005 image_info->interlace=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001006 MagickInterlaceOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001007 break;
1008 }
anthony74b1cfc2011-10-06 12:44:16 +00001009 if (LocaleCompare("interline-spacing",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001010 {
anthony72feaa62012-01-17 06:46:23 +00001011 (void) SetImageOption(image_info,option, ArgOption(NULL));
1012 draw_info->interline_spacing=StringToDouble(ArgOption("0"),
1013 (char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001014 break;
1015 }
anthony74b1cfc2011-10-06 12:44:16 +00001016 if (LocaleCompare("interpolate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001017 {
anthonyfd706f92012-01-19 04:22:02 +00001018 /* SyncImageSettings() used to set per-image attribute. */
anthony72feaa62012-01-17 06:46:23 +00001019 (void) SetImageOption(image_info,option,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001020 break;
1021 }
cristy947cb4c2011-10-20 18:41:46 +00001022 if (LocaleCompare("interword-spacing",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001023 {
anthony72feaa62012-01-17 06:46:23 +00001024 (void) SetImageOption(image_info,option, ArgOption(NULL));
1025 draw_info->interword_spacing=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001026 break;
1027 }
1028 break;
1029 }
1030 case 'k':
1031 {
anthony74b1cfc2011-10-06 12:44:16 +00001032 if (LocaleCompare("kerning",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001033 {
anthony72feaa62012-01-17 06:46:23 +00001034 (void) SetImageOption(image_info,option,ArgOption(NULL));
1035 draw_info->kerning=StringToDouble(ArgOption("0"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001036 break;
1037 }
1038 break;
1039 }
1040 case 'l':
1041 {
anthony74b1cfc2011-10-06 12:44:16 +00001042 if (LocaleCompare("label",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001043 {
anthony72feaa62012-01-17 06:46:23 +00001044 /* only used for new images - not in SyncImageOptions() */
1045 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001046 break;
1047 }
anthony74b1cfc2011-10-06 12:44:16 +00001048 if (LocaleCompare("log",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001049 {
anthonydcf510d2011-10-30 13:51:40 +00001050 if (IfSetOption)
1051 (void) SetLogFormat(arg);
anthony805a2d42011-09-25 08:25:12 +00001052 break;
1053 }
anthony74b1cfc2011-10-06 12:44:16 +00001054 if (LocaleCompare("loop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001055 {
anthony72feaa62012-01-17 06:46:23 +00001056 /* SyncImageSettings() used to set per-image attribute. */
1057 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001058 break;
1059 }
1060 break;
1061 }
1062 case 'm':
1063 {
anthony74b1cfc2011-10-06 12:44:16 +00001064 if (LocaleCompare("mattecolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001065 {
anthony72feaa62012-01-17 06:46:23 +00001066 /* SyncImageSettings() used to set per-image attribute. */
1067 (void) SetImageOption(image_info,option,ArgOption(NULL));
1068 (void) QueryColorCompliance(ArgOption(MatteColor),AllCompliance,
1069 &image_info->matte_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001070 break;
1071 }
anthony74b1cfc2011-10-06 12:44:16 +00001072 if (LocaleCompare("monitor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001073 {
anthony31f1bf72012-01-30 12:37:22 +00001074 (void) SetImageInfoProgressMonitor(image_info, IfSetOption?
1075 MonitorProgress: (MagickProgressMonitor) NULL, (void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00001076 break;
1077 }
anthony74b1cfc2011-10-06 12:44:16 +00001078 if (LocaleCompare("monochrome",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001079 {
anthony72feaa62012-01-17 06:46:23 +00001080 /* Setting (for some input coders)
1081 But also a special 'type' operator
1082 */
1083 image_info->monochrome= ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001084 break;
1085 }
1086 break;
1087 }
1088 case 'o':
1089 {
anthony74b1cfc2011-10-06 12:44:16 +00001090 if (LocaleCompare("orient",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001091 {
anthony72feaa62012-01-17 06:46:23 +00001092 /* Is not used when defining for new images.
anthonydcf510d2011-10-30 13:51:40 +00001093 This makes it more of a 'operation' than a setting
anthony72feaa62012-01-17 06:46:23 +00001094 FUTURE: make set meta-data operator instead.
1095 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001096 */
anthony72feaa62012-01-17 06:46:23 +00001097 (void) SetImageOption(image_info,option, ArgOption(NULL));
anthonydcf510d2011-10-30 13:51:40 +00001098 image_info->orientation=(InterlaceType) ParseCommandOption(
anthony72feaa62012-01-17 06:46:23 +00001099 MagickOrientationOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001100 break;
1101 }
1102 }
1103 case 'p':
1104 {
anthony74b1cfc2011-10-06 12:44:16 +00001105 if (LocaleCompare("page",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001106 {
anthony72feaa62012-01-17 06:46:23 +00001107 /* Only used for new images and image generators
1108 SyncImageSettings() used to set per-image attribute. ?????
1109 That last is WRONG!!!!
1110 */
anthony805a2d42011-09-25 08:25:12 +00001111 char
1112 *canonical_page,
1113 page[MaxTextExtent];
1114
1115 const char
1116 *image_option;
1117
1118 MagickStatusType
1119 flags;
1120
1121 RectangleInfo
1122 geometry;
1123
anthonydcf510d2011-10-30 13:51:40 +00001124 if (!IfSetOption)
anthony805a2d42011-09-25 08:25:12 +00001125 {
anthony74b1cfc2011-10-06 12:44:16 +00001126 (void) DeleteImageOption(image_info,option);
anthony805a2d42011-09-25 08:25:12 +00001127 (void) CloneString(&image_info->page,(char *) NULL);
1128 break;
1129 }
1130 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1131 image_option=GetImageOption(image_info,"page");
1132 if (image_option != (const char *) NULL)
1133 flags=ParseAbsoluteGeometry(image_option,&geometry);
anthonydcf510d2011-10-30 13:51:40 +00001134 canonical_page=GetPageGeometry(arg);
anthony805a2d42011-09-25 08:25:12 +00001135 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1136 canonical_page=DestroyString(canonical_page);
1137 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1138 (unsigned long) geometry.width,(unsigned long) geometry.height);
1139 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1140 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1141 (unsigned long) geometry.width,(unsigned long) geometry.height,
1142 (long) geometry.x,(long) geometry.y);
anthony74b1cfc2011-10-06 12:44:16 +00001143 (void) SetImageOption(image_info,option,page);
anthony805a2d42011-09-25 08:25:12 +00001144 (void) CloneString(&image_info->page,page);
1145 break;
1146 }
anthony74b1cfc2011-10-06 12:44:16 +00001147 if (LocaleCompare("ping",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001148 {
anthony72feaa62012-01-17 06:46:23 +00001149 image_info->ping = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001150 break;
1151 }
anthony74b1cfc2011-10-06 12:44:16 +00001152 if (LocaleCompare("pointsize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001153 {
anthony72feaa62012-01-17 06:46:23 +00001154 image_info->pointsize=draw_info->pointsize=
1155 StringToDouble(ArgOption("12"),(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00001156 break;
1157 }
anthony74b1cfc2011-10-06 12:44:16 +00001158 if (LocaleCompare("precision",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001159 {
anthony72feaa62012-01-17 06:46:23 +00001160 (void) SetMagickPrecision(StringToInteger(ArgOption("-1")));
anthony805a2d42011-09-25 08:25:12 +00001161 break;
1162 }
anthonydcf510d2011-10-30 13:51:40 +00001163 /* FUTURE: Only the 'preview' coder appears to use this
1164 * Depreciate the coder? Leaving only the 'preview' operator.
anthony74b1cfc2011-10-06 12:44:16 +00001165 if (LocaleCompare("preview",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001166 {
anthonydcf510d2011-10-30 13:51:40 +00001167 image_info->preview_type=UndefinedPreview;
1168 if (IfSetOption)
1169 image_info->preview_type=(PreviewType) ParseCommandOption(
1170 MagickPreviewOptions,MagickFalse,arg);
anthony805a2d42011-09-25 08:25:12 +00001171 break;
1172 }
anthonydcf510d2011-10-30 13:51:40 +00001173 */
anthony805a2d42011-09-25 08:25:12 +00001174 break;
1175 }
1176 case 'q':
1177 {
anthony74b1cfc2011-10-06 12:44:16 +00001178 if (LocaleCompare("quality",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001179 {
anthony72feaa62012-01-17 06:46:23 +00001180 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthonydcf510d2011-10-30 13:51:40 +00001181 image_info->quality=UndefinedCompressionQuality;
anthony72feaa62012-01-17 06:46:23 +00001182 if (IfSetOption)
1183 image_info->quality=StringToUnsignedLong(arg);
anthony805a2d42011-09-25 08:25:12 +00001184 break;
1185 }
anthonyafbaed72011-10-26 12:05:04 +00001186 if (LocaleCompare("quantize",option) == 0)
1187 {
anthony72feaa62012-01-17 06:46:23 +00001188 /* Just a set direct in quantize_info */
anthonyafbaed72011-10-26 12:05:04 +00001189 quantize_info->colorspace=UndefinedColorspace;
1190 if (IfSetOption)
1191 quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
anthonydcf510d2011-10-30 13:51:40 +00001192 MagickColorspaceOptions,MagickFalse,arg);
anthonyafbaed72011-10-26 12:05:04 +00001193 break;
1194 }
anthony74b1cfc2011-10-06 12:44:16 +00001195 if (LocaleCompare("quiet",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001196 {
anthonydcf510d2011-10-30 13:51:40 +00001197 /* FUTURE: if two -quiet is performed you can not do +quiet! */
anthony805a2d42011-09-25 08:25:12 +00001198 static WarningHandler
1199 warning_handler = (WarningHandler) NULL;
anthony72feaa62012-01-17 06:46:23 +00001200
anthonyafbaed72011-10-26 12:05:04 +00001201 WarningHandler
1202 tmp = SetWarningHandler((WarningHandler) NULL);
anthony805a2d42011-09-25 08:25:12 +00001203
anthonyafbaed72011-10-26 12:05:04 +00001204 if ( tmp != (WarningHandler) NULL)
1205 warning_handler = tmp; /* remember the old handler */
1206 if (!IfSetOption) /* set the old handler */
1207 warning_handler=SetWarningHandler(warning_handler);
anthony805a2d42011-09-25 08:25:12 +00001208 break;
1209 }
1210 break;
1211 }
1212 case 'r':
1213 {
anthony74b1cfc2011-10-06 12:44:16 +00001214 if (LocaleCompare("red-primary",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001215 {
anthonydcf510d2011-10-30 13:51:40 +00001216 /* Image chromaticity X,Y NB: Y=X if Y not defined
1217 Used by many coders
anthony72feaa62012-01-17 06:46:23 +00001218 SyncImageSettings() used to set per-image attribute.
anthonydcf510d2011-10-30 13:51:40 +00001219 */
anthony72feaa62012-01-17 06:46:23 +00001220 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001221 break;
1222 }
anthonyafbaed72011-10-26 12:05:04 +00001223 if (LocaleCompare("render",option) == 0)
1224 {
1225 /* draw_info only setting */
1226 draw_info->render= IfSetOption ? MagickFalse : MagickTrue;
1227 break;
1228 }
anthony43f425d2012-02-26 12:58:58 +00001229 if (LocaleCompare("respect-parenthesis",option) == 0)
1230 {
1231 (void) SetImageOption(image_info,option,ArgOption(NULL));
1232 break;
1233 }
anthony805a2d42011-09-25 08:25:12 +00001234 break;
1235 }
1236 case 's':
1237 {
anthony74b1cfc2011-10-06 12:44:16 +00001238 if (LocaleCompare("sampling-factor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001239 {
anthonyafbaed72011-10-26 12:05:04 +00001240 /* FUTURE: should be converted to jpeg:sampling_factor */
anthony72feaa62012-01-17 06:46:23 +00001241 (void) CloneString(&image_info->sampling_factor,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001242 break;
1243 }
anthony74b1cfc2011-10-06 12:44:16 +00001244 if (LocaleCompare("scene",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001245 {
anthony72feaa62012-01-17 06:46:23 +00001246 /* SyncImageSettings() used to set per-image attribute.
1247 What ??? Why ????
1248 */
1249 (void) SetImageOption(image_info,option,ArgOption(NULL));
1250 image_info->scene=StringToUnsignedLong(ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001251 break;
1252 }
anthony74b1cfc2011-10-06 12:44:16 +00001253 if (LocaleCompare("seed",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001254 {
anthonyafbaed72011-10-26 12:05:04 +00001255 SeedPseudoRandomGenerator(
anthonydcf510d2011-10-30 13:51:40 +00001256 IfSetOption ? (size_t) StringToUnsignedLong(arg)
anthonyafbaed72011-10-26 12:05:04 +00001257 : (size_t) time((time_t *) NULL) );
anthony805a2d42011-09-25 08:25:12 +00001258 break;
1259 }
anthony74b1cfc2011-10-06 12:44:16 +00001260 if (LocaleCompare("size",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001261 {
anthonyafbaed72011-10-26 12:05:04 +00001262 /* FUTURE: string in image_info -- convert to Option ???
1263 Look at the special handling for "size" in SetImageOption()
anthony74b1cfc2011-10-06 12:44:16 +00001264 */
anthony72feaa62012-01-17 06:46:23 +00001265 (void) CloneString(&image_info->size,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001266 break;
1267 }
1268 if (LocaleCompare("stretch",option) == 0)
1269 {
anthony72feaa62012-01-17 06:46:23 +00001270 draw_info->stretch=(StretchType) ParseCommandOption(
1271 MagickStretchOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001272 break;
1273 }
anthony74b1cfc2011-10-06 12:44:16 +00001274 if (LocaleCompare("stroke",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001275 {
anthonyafbaed72011-10-26 12:05:04 +00001276 /* set stroke color OR stroke-pattern
anthonyfd706f92012-01-19 04:22:02 +00001277 UPDATE: ensure stroke color is not destroyed is a pattern
1278 is given. Just in case the color is also used for other purposes.
anthonyafbaed72011-10-26 12:05:04 +00001279 */
1280 const char
anthony72feaa62012-01-17 06:46:23 +00001281 *value;
1282
1283 MagickBooleanType
1284 status;
anthonyafbaed72011-10-26 12:05:04 +00001285
1286 ExceptionInfo
1287 *sans;
1288
anthonyfd706f92012-01-19 04:22:02 +00001289 PixelInfo
1290 color;
1291
anthony72feaa62012-01-17 06:46:23 +00001292 value = ArgOption("none");
anthonyafbaed72011-10-26 12:05:04 +00001293 (void) SetImageOption(image_info,option,value);
anthony72feaa62012-01-17 06:46:23 +00001294 if (draw_info->stroke_pattern != (Image *) NULL)
1295 draw_info->stroke_pattern=DestroyImage(draw_info->stroke_pattern);
1296
1297 /* is it a color or a image? -- ignore exceptions */
anthonyafbaed72011-10-26 12:05:04 +00001298 sans=AcquireExceptionInfo();
anthonyfd706f92012-01-19 04:22:02 +00001299 status=QueryColorCompliance(value,AllCompliance,&color,sans);
anthonyafbaed72011-10-26 12:05:04 +00001300 sans=DestroyExceptionInfo(sans);
anthonyfd706f92012-01-19 04:22:02 +00001301
anthonyafbaed72011-10-26 12:05:04 +00001302 if (status == MagickFalse)
anthonyfd706f92012-01-19 04:22:02 +00001303 draw_info->stroke_pattern=GetImageCache(image_info,value,exception);
1304 else
1305 draw_info->stroke=color;
anthony805a2d42011-09-25 08:25:12 +00001306 break;
1307 }
anthony74b1cfc2011-10-06 12:44:16 +00001308 if (LocaleCompare("strokewidth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001309 {
anthony72feaa62012-01-17 06:46:23 +00001310 (void) SetImageOption(image_info,option,ArgOption(NULL));
1311 draw_info->stroke_width=StringToDouble(ArgOption("1.0"),
1312 (char **) NULL);
anthonyafbaed72011-10-26 12:05:04 +00001313 break;
1314 }
1315 if (LocaleCompare("style",option) == 0)
1316 {
anthony72feaa62012-01-17 06:46:23 +00001317 draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1318 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001319 break;
1320 }
anthony74b1cfc2011-10-06 12:44:16 +00001321 if (LocaleCompare("synchronize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001322 {
anthony72feaa62012-01-17 06:46:23 +00001323 image_info->synchronize = ArgBoolean;
anthony805a2d42011-09-25 08:25:12 +00001324 break;
1325 }
1326 break;
1327 }
1328 case 't':
1329 {
anthony74b1cfc2011-10-06 12:44:16 +00001330 if (LocaleCompare("taint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001331 {
anthony72feaa62012-01-17 06:46:23 +00001332 /* SyncImageSettings() used to set per-image attribute. */
anthonyafbaed72011-10-26 12:05:04 +00001333 (void) SetImageOption(image_info,option,
1334 IfSetOption ? "true" : "false");
anthony805a2d42011-09-25 08:25:12 +00001335 break;
1336 }
anthony74b1cfc2011-10-06 12:44:16 +00001337 if (LocaleCompare("texture",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001338 {
anthonyafbaed72011-10-26 12:05:04 +00001339 /* FUTURE: move image_info string to option splay-tree */
anthony72feaa62012-01-17 06:46:23 +00001340 (void) CloneString(&image_info->texture,ArgOption(NULL));
anthonyafbaed72011-10-26 12:05:04 +00001341 break;
1342 }
1343 if (LocaleCompare("tile",option) == 0)
1344 {
anthony72feaa62012-01-17 06:46:23 +00001345 draw_info->fill_pattern=IfSetOption
1346 ?GetImageCache(image_info,arg,exception)
1347 :DestroyImage(draw_info->fill_pattern);
anthony805a2d42011-09-25 08:25:12 +00001348 break;
1349 }
anthony74b1cfc2011-10-06 12:44:16 +00001350 if (LocaleCompare("tile-offset",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001351 {
anthony72feaa62012-01-17 06:46:23 +00001352 /* SyncImageSettings() used to set per-image attribute. ??? */
1353 (void) SetImageOption(image_info,option,ArgOption("0"));
anthony805a2d42011-09-25 08:25:12 +00001354 break;
1355 }
anthony74b1cfc2011-10-06 12:44:16 +00001356 if (LocaleCompare("transparent-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001357 {
anthonyafbaed72011-10-26 12:05:04 +00001358 /* FUTURE: both image_info attribute & ImageOption in use!
1359 image_info only used for generating new images.
anthony72feaa62012-01-17 06:46:23 +00001360 SyncImageSettings() used to set per-image attribute.
1361
anthonyafbaed72011-10-26 12:05:04 +00001362 Note that +transparent-color, means fall-back to image
1363 attribute so ImageOption is deleted, not set to a default.
1364 */
anthony72feaa62012-01-17 06:46:23 +00001365 (void) SetImageOption(image_info,option,ArgOption(NULL));
1366 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1367 &image_info->transparent_color,exception);
anthony805a2d42011-09-25 08:25:12 +00001368 break;
1369 }
anthony31f1bf72012-01-30 12:37:22 +00001370 if (LocaleCompare("treedepth",option) == 0)
1371 {
1372 (void) SetImageOption(image_info,option,ArgOption(NULL));
1373 quantize_info->tree_depth=StringToUnsignedLong(ArgOption("0"));
1374 break;
1375 }
anthony74b1cfc2011-10-06 12:44:16 +00001376 if (LocaleCompare("type",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001377 {
anthony72feaa62012-01-17 06:46:23 +00001378 /* SyncImageSettings() used to set per-image attribute. */
1379 (void) SetImageOption(image_info,option,ArgOption(NULL));
1380 image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1381 MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001382 break;
1383 }
1384 break;
1385 }
1386 case 'u':
1387 {
anthony74b1cfc2011-10-06 12:44:16 +00001388 if (LocaleCompare("undercolor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001389 {
anthony72feaa62012-01-17 06:46:23 +00001390 (void) SetImageOption(image_info,option,ArgOption(NULL));
1391 (void) QueryColorCompliance(ArgOption("none"),AllCompliance,
1392 &draw_info->undercolor,exception);
anthony805a2d42011-09-25 08:25:12 +00001393 break;
1394 }
anthony74b1cfc2011-10-06 12:44:16 +00001395 if (LocaleCompare("units",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001396 {
anthony72feaa62012-01-17 06:46:23 +00001397 /* SyncImageSettings() used to set per-image attribute.
1398 Should this effect draw_info X and Y resolution?
1399 FUTURE: this probably should be part of the density setting
1400 */
1401 (void) SetImageOption(image_info,option,ArgOption(NULL));
1402 image_info->units=(ResolutionType) ParseCommandOption(
1403 MagickResolutionOptions,MagickFalse,ArgOption("undefined"));
anthony805a2d42011-09-25 08:25:12 +00001404 break;
1405 }
1406 break;
1407 }
1408 case 'v':
1409 {
anthony74b1cfc2011-10-06 12:44:16 +00001410 if (LocaleCompare("verbose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001411 {
anthonyab3a50c2011-10-27 11:48:57 +00001412 /* FUTURE: Also an image artifact, set in Simple Operators.
1413 But artifact is only used in verbose output.
1414 */
anthony31f1bf72012-01-30 12:37:22 +00001415 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony72feaa62012-01-17 06:46:23 +00001416 image_info->verbose= ArgBoolean;
anthonyab3a50c2011-10-27 11:48:57 +00001417 image_info->ping=MagickFalse; /* verbose can't be a ping */
anthony805a2d42011-09-25 08:25:12 +00001418 break;
1419 }
anthony74b1cfc2011-10-06 12:44:16 +00001420 if (LocaleCompare("view",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001421 {
anthony72feaa62012-01-17 06:46:23 +00001422 /* FUTURE: Convert from image_info to ImageOption
anthonyab3a50c2011-10-27 11:48:57 +00001423 Only used by coder FPX
1424 */
anthony72feaa62012-01-17 06:46:23 +00001425 (void) CloneString(&image_info->view,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001426 break;
1427 }
anthony74b1cfc2011-10-06 12:44:16 +00001428 if (LocaleCompare("virtual-pixel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001429 {
anthonyfd706f92012-01-19 04:22:02 +00001430 /* SyncImageSettings() used to set per-image attribute.
1431 This is VERY deep in the image caching structure.
1432 */
anthony72feaa62012-01-17 06:46:23 +00001433 (void) SetImageOption(image_info,option,ArgOption(NULL));
anthony805a2d42011-09-25 08:25:12 +00001434 break;
1435 }
1436 break;
1437 }
1438 case 'w':
1439 {
anthonydcf510d2011-10-30 13:51:40 +00001440 if (LocaleCompare("weight",option) == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001441 {
anthony72feaa62012-01-17 06:46:23 +00001442 /* Just what does using a font 'weight' do ???
anthonydcf510d2011-10-30 13:51:40 +00001443 There is no "-list weight" output (reference manual says there is)
anthonyab3a50c2011-10-27 11:48:57 +00001444 */
anthony72feaa62012-01-17 06:46:23 +00001445 if (!IfSetOption)
1446 break;
anthonydcf510d2011-10-30 13:51:40 +00001447 draw_info->weight=StringToUnsignedLong(arg);
1448 if (LocaleCompare(arg,"all") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001449 draw_info->weight=0;
anthonydcf510d2011-10-30 13:51:40 +00001450 if (LocaleCompare(arg,"bold") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001451 draw_info->weight=700;
anthonydcf510d2011-10-30 13:51:40 +00001452 if (LocaleCompare(arg,"bolder") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001453 if (draw_info->weight <= 800)
1454 draw_info->weight+=100;
anthonydcf510d2011-10-30 13:51:40 +00001455 if (LocaleCompare(arg,"lighter") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001456 if (draw_info->weight >= 100)
1457 draw_info->weight-=100;
anthonydcf510d2011-10-30 13:51:40 +00001458 if (LocaleCompare(arg,"normal") == 0)
anthonyab3a50c2011-10-27 11:48:57 +00001459 draw_info->weight=400;
1460 break;
1461 }
anthony74b1cfc2011-10-06 12:44:16 +00001462 if (LocaleCompare("white-point",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001463 {
anthony72feaa62012-01-17 06:46:23 +00001464 /* Used as a image chromaticity setting
1465 SyncImageSettings() used to set per-image attribute.
1466 */
1467 (void) SetImageOption(image_info,option,ArgOption("0.0"));
anthony805a2d42011-09-25 08:25:12 +00001468 break;
1469 }
1470 break;
1471 }
1472 default:
1473 break;
1474 }
anthonyfd706f92012-01-19 04:22:02 +00001475#undef image_info
anthony43f425d2012-02-26 12:58:58 +00001476#undef exception
anthonyfd706f92012-01-19 04:22:02 +00001477#undef draw_info
1478#undef quantize_info
anthonyfd706f92012-01-19 04:22:02 +00001479#undef IfSetOption
1480#undef ArgOption
1481#undef ArgBoolean
1482
anthony31f1bf72012-01-30 12:37:22 +00001483 return;
anthony805a2d42011-09-25 08:25:12 +00001484}
1485
1486/*
1487%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1488% %
1489% %
1490% %
anthony43f425d2012-02-26 12:58:58 +00001491+ 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 +00001492% %
1493% %
1494% %
1495%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1496%
anthony31f1bf72012-01-30 12:37:22 +00001497% WandSimpleOperatorImages() applys one simple image operation given to all
anthony43f425d2012-02-26 12:58:58 +00001498% the images in the CLI wand, with the settings that was previously saved in
1499% the CLI wand.
anthonydcf510d2011-10-30 13:51:40 +00001500%
1501% It is assumed that any per-image settings are up-to-date with respect to
anthony43f425d2012-02-26 12:58:58 +00001502% extra settings that were already saved in the wand.
anthony805a2d42011-09-25 08:25:12 +00001503%
anthonyd1447672012-01-19 05:33:53 +00001504% The format of the WandSimpleOperatorImage method is:
anthony805a2d42011-09-25 08:25:12 +00001505%
anthony43f425d2012-02-26 12:58:58 +00001506% void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthonyfd706f92012-01-19 04:22:02 +00001507% const MagickBooleanType plus_alt_op, const char *option,
1508% const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001509%
1510% A description of each parameter follows:
1511%
anthony43f425d2012-02-26 12:58:58 +00001512% o cli_wand: structure holding settings and images to be operated on
anthony805a2d42011-09-25 08:25:12 +00001513%
anthonyfd706f92012-01-19 04:22:02 +00001514% o plus_alt_op: request the 'plus' or alturnative form of the operation
anthony805a2d42011-09-25 08:25:12 +00001515%
anthonyfd706f92012-01-19 04:22:02 +00001516% o option: The option string for the operation
anthonydcf510d2011-10-30 13:51:40 +00001517%
anthonyfd706f92012-01-19 04:22:02 +00001518% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00001519%
anthony31f1bf72012-01-30 12:37:22 +00001520% Any problems will be added to the 'exception' entry of the given wand.
anthony805a2d42011-09-25 08:25:12 +00001521%
anthony31f1bf72012-01-30 12:37:22 +00001522% Example usage...
anthonydcf510d2011-10-30 13:51:40 +00001523%
anthony43f425d2012-02-26 12:58:58 +00001524% CLISimpleOperatorImages(cli_wand, MagickFalse,"crop","100x100+20+30",NULL);
1525% CLISimpleOperatorImages(cli_wand, MagickTrue, "repage",NULL,NULL);
1526% CLISimpleOperatorImages(cli_wand, MagickTrue, "distort","SRT","45");
1527% if ( cli_wand->wand.exception->severity != UndefinedException ) {
anthony31f1bf72012-01-30 12:37:22 +00001528% CatchException(exception);
1529% exit(1);
1530% }
anthonyfd706f92012-01-19 04:22:02 +00001531%
1532% Or for handling command line arguments EG: +/-option ["arg"]
anthonydcf510d2011-10-30 13:51:40 +00001533%
anthony43f425d2012-02-26 12:58:58 +00001534% cli_wand
anthonydcf510d2011-10-30 13:51:40 +00001535% argc,argv
1536% i=index in argv
1537%
1538% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
1539% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
anthonye8f56492012-02-12 12:39:02 +00001540% if ( (flags & SimpleOperatorOptionFlag) != 0 )
anthony43f425d2012-02-26 12:58:58 +00001541% CLISimpleOperatorImages(cli_wand,
anthony36a8c2c2012-02-10 00:08:44 +00001542% ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
anthonyfd706f92012-01-19 04:22:02 +00001543% count>=1 ? argv[i+1] : (char *)NULL,
1544% count>=2 ? argv[i+2] : (char *)NULL );
anthonydcf510d2011-10-30 13:51:40 +00001545% i += count+1;
1546%
anthony805a2d42011-09-25 08:25:12 +00001547*/
anthony31f1bf72012-01-30 12:37:22 +00001548
1549/*
1550 Internal subrountine to apply one simple image operation to the current
anthony43f425d2012-02-26 12:58:58 +00001551 image pointed to by the CLI wand.
anthony31f1bf72012-01-30 12:37:22 +00001552
1553 The image in the list may be modified in three different ways...
1554 * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1555 * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1556 * one image replace by a list of images (-separate and -crop only!)
1557
1558 In each case the result replaces the original image in the list, as well as
1559 the pointer to the modified image (last image added if replaced by a list
1560 of images) is returned.
1561
1562 As the image pointed to may be replaced, the first image in the list may
1563 also change. GetFirstImageInList() should be used by caller if they wish
1564 return the Image pointer to the first image in list.
1565*/
anthony43f425d2012-02-26 12:58:58 +00001566static void CLISimpleOperatorImage(MagickCLI *cli_wand,
anthony36a8c2c2012-02-10 00:08:44 +00001567 const MagickBooleanType plus_alt_op, const char *option,
1568 const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00001569{
1570 Image *
1571 new_image;
1572
anthony805a2d42011-09-25 08:25:12 +00001573 GeometryInfo
1574 geometry_info;
1575
1576 RectangleInfo
1577 geometry;
1578
1579 MagickStatusType
anthony805a2d42011-09-25 08:25:12 +00001580 flags;
1581
anthony43f425d2012-02-26 12:58:58 +00001582#define image_info (cli_wand->wand.image_info)
1583#define image (cli_wand->wand.images)
1584#define exception (cli_wand->wand.exception)
1585#define draw_info (cli_wand->draw_info)
1586#define quantize_info (cli_wand->quantize_info)
anthony31f1bf72012-01-30 12:37:22 +00001587#define normal_op (plus_alt_op?MagickFalse:MagickTrue)
anthonyfd706f92012-01-19 04:22:02 +00001588
anthony43f425d2012-02-26 12:58:58 +00001589 assert(cli_wand != (MagickCLI *) NULL);
1590 assert(cli_wand->signature == WandSignature);
1591 assert(cli_wand->wand.signature == WandSignature);
1592 assert(image != (Image *) NULL); /* an image must be present */
1593 if (cli_wand->wand.debug != MagickFalse)
1594 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthonydcf510d2011-10-30 13:51:40 +00001595
anthony805a2d42011-09-25 08:25:12 +00001596 SetGeometryInfo(&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001597
anthonydcf510d2011-10-30 13:51:40 +00001598 new_image = (Image *)NULL; /* the replacement image, if not null at end */
anthony805a2d42011-09-25 08:25:12 +00001599
anthonyfd706f92012-01-19 04:22:02 +00001600 /* FUTURE: We may need somthing a little more optimized than this!
1601 Perhaps, do the 'sync' if 'settings tainted' before next operator.
1602 */
anthony31f1bf72012-01-30 12:37:22 +00001603 (void) SyncImageSettings(image_info,image,exception);
anthonydcf510d2011-10-30 13:51:40 +00001604
1605 switch (*option)
anthony805a2d42011-09-25 08:25:12 +00001606 {
1607 case 'a':
1608 {
anthonydcf510d2011-10-30 13:51:40 +00001609 if (LocaleCompare("adaptive-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001610 {
anthonyfd706f92012-01-19 04:22:02 +00001611 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001612 if ((flags & SigmaValue) == 0)
1613 geometry_info.sigma=1.0;
1614 if ((flags & XiValue) == 0)
1615 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001616 new_image=AdaptiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001617 geometry_info.sigma,geometry_info.xi,exception);
1618 break;
1619 }
anthonydcf510d2011-10-30 13:51:40 +00001620 if (LocaleCompare("adaptive-resize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001621 {
anthony31f1bf72012-01-30 12:37:22 +00001622 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
1623 new_image=AdaptiveResizeImage(image,geometry.width,geometry.height,
anthonyfd706f92012-01-19 04:22:02 +00001624 exception);
anthony805a2d42011-09-25 08:25:12 +00001625 break;
1626 }
anthonydcf510d2011-10-30 13:51:40 +00001627 if (LocaleCompare("adaptive-sharpen",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001628 {
anthonyfd706f92012-01-19 04:22:02 +00001629 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001630 if ((flags & SigmaValue) == 0)
1631 geometry_info.sigma=1.0;
1632 if ((flags & XiValue) == 0)
1633 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001634 new_image=AdaptiveSharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001635 geometry_info.sigma,geometry_info.xi,exception);
1636 break;
1637 }
anthonydcf510d2011-10-30 13:51:40 +00001638 if (LocaleCompare("alpha",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001639 {
1640 AlphaChannelType
1641 alpha_type;
1642
anthony805a2d42011-09-25 08:25:12 +00001643 alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
anthonyfd706f92012-01-19 04:22:02 +00001644 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00001645 (void) SetImageAlphaChannel(image,alpha_type,exception);
anthony805a2d42011-09-25 08:25:12 +00001646 break;
1647 }
anthonydcf510d2011-10-30 13:51:40 +00001648 if (LocaleCompare("annotate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001649 {
1650 char
1651 *text,
1652 geometry[MaxTextExtent];
1653
anthony805a2d42011-09-25 08:25:12 +00001654 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00001655 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001656 if ((flags & SigmaValue) == 0)
1657 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00001658 text=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00001659 exception);
1660 if (text == (char *) NULL)
1661 break;
1662 (void) CloneString(&draw_info->text,text);
1663 text=DestroyString(text);
1664 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1665 geometry_info.xi,geometry_info.psi);
1666 (void) CloneString(&draw_info->geometry,geometry);
1667 draw_info->affine.sx=cos(DegreesToRadians(
1668 fmod(geometry_info.rho,360.0)));
1669 draw_info->affine.rx=sin(DegreesToRadians(
1670 fmod(geometry_info.rho,360.0)));
1671 draw_info->affine.ry=(-sin(DegreesToRadians(
1672 fmod(geometry_info.sigma,360.0))));
1673 draw_info->affine.sy=cos(DegreesToRadians(
1674 fmod(geometry_info.sigma,360.0)));
anthony31f1bf72012-01-30 12:37:22 +00001675 (void) AnnotateImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00001676 GetAffineMatrix(&draw_info->affine);
anthony805a2d42011-09-25 08:25:12 +00001677 break;
1678 }
anthonydcf510d2011-10-30 13:51:40 +00001679 if (LocaleCompare("auto-gamma",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001680 {
anthony31f1bf72012-01-30 12:37:22 +00001681 (void) AutoGammaImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001682 break;
1683 }
anthonydcf510d2011-10-30 13:51:40 +00001684 if (LocaleCompare("auto-level",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001685 {
anthony31f1bf72012-01-30 12:37:22 +00001686 (void) AutoLevelImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001687 break;
1688 }
anthonydcf510d2011-10-30 13:51:40 +00001689 if (LocaleCompare("auto-orient",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001690 {
anthony31f1bf72012-01-30 12:37:22 +00001691 switch (image->orientation)
anthony805a2d42011-09-25 08:25:12 +00001692 {
1693 case TopRightOrientation:
1694 {
anthony31f1bf72012-01-30 12:37:22 +00001695 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001696 break;
1697 }
1698 case BottomRightOrientation:
1699 {
anthony31f1bf72012-01-30 12:37:22 +00001700 new_image=RotateImage(image,180.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001701 break;
1702 }
1703 case BottomLeftOrientation:
1704 {
anthony31f1bf72012-01-30 12:37:22 +00001705 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001706 break;
1707 }
1708 case LeftTopOrientation:
1709 {
anthony31f1bf72012-01-30 12:37:22 +00001710 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001711 break;
1712 }
1713 case RightTopOrientation:
1714 {
anthony31f1bf72012-01-30 12:37:22 +00001715 new_image=RotateImage(image,90.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001716 break;
1717 }
1718 case RightBottomOrientation:
1719 {
anthony31f1bf72012-01-30 12:37:22 +00001720 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001721 break;
1722 }
1723 case LeftBottomOrientation:
1724 {
anthony31f1bf72012-01-30 12:37:22 +00001725 new_image=RotateImage(image,270.0,exception);
anthony805a2d42011-09-25 08:25:12 +00001726 break;
1727 }
1728 default:
1729 break;
1730 }
1731 if (new_image != (Image *) NULL)
1732 new_image->orientation=TopLeftOrientation;
1733 break;
1734 }
1735 break;
1736 }
1737 case 'b':
1738 {
anthonydcf510d2011-10-30 13:51:40 +00001739 if (LocaleCompare("black-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001740 {
anthony31f1bf72012-01-30 12:37:22 +00001741 (void) BlackThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001742 break;
1743 }
anthonydcf510d2011-10-30 13:51:40 +00001744 if (LocaleCompare("blue-shift",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001745 {
anthony805a2d42011-09-25 08:25:12 +00001746 geometry_info.rho=1.5;
anthonyfd706f92012-01-19 04:22:02 +00001747 if (plus_alt_op == MagickFalse)
1748 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00001749 new_image=BlueShiftImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00001750 break;
1751 }
anthonydcf510d2011-10-30 13:51:40 +00001752 if (LocaleCompare("blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001753 {
anthony74b1cfc2011-10-06 12:44:16 +00001754 /* FUTURE: use of "bias" in a blur is non-sensible */
anthonyfd706f92012-01-19 04:22:02 +00001755 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001756 if ((flags & SigmaValue) == 0)
1757 geometry_info.sigma=1.0;
1758 if ((flags & XiValue) == 0)
1759 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00001760 new_image=BlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001761 geometry_info.sigma,geometry_info.xi,exception);
1762 break;
1763 }
anthonydcf510d2011-10-30 13:51:40 +00001764 if (LocaleCompare("border",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001765 {
anthony31f1bf72012-01-30 12:37:22 +00001766 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00001767 compose;
1768
1769 const char*
anthony5f867ae2011-10-09 10:28:34 +00001770 value;
1771
1772 value=GetImageOption(image_info,"compose");
1773 if (value != (const char *) NULL)
1774 compose=(CompositeOperator) ParseCommandOption(
1775 MagickComposeOptions,MagickFalse,value);
1776 else
1777 compose=OverCompositeOp; /* use Over not image->compose */
1778
anthony31f1bf72012-01-30 12:37:22 +00001779 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001780 if ((flags & SigmaValue) == 0)
1781 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00001782 new_image=BorderImage(image,&geometry,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00001783 break;
1784 }
anthonydcf510d2011-10-30 13:51:40 +00001785 if (LocaleCompare("brightness-contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001786 {
1787 double
1788 brightness,
1789 contrast;
1790
1791 GeometryInfo
1792 geometry_info;
1793
1794 MagickStatusType
1795 flags;
1796
anthonyfd706f92012-01-19 04:22:02 +00001797 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001798 brightness=geometry_info.rho;
1799 contrast=0.0;
1800 if ((flags & SigmaValue) != 0)
1801 contrast=geometry_info.sigma;
anthony31f1bf72012-01-30 12:37:22 +00001802 (void) BrightnessContrastImage(image,brightness,contrast,
anthony805a2d42011-09-25 08:25:12 +00001803 exception);
anthony805a2d42011-09-25 08:25:12 +00001804 break;
1805 }
1806 break;
1807 }
1808 case 'c':
1809 {
anthonydcf510d2011-10-30 13:51:40 +00001810 if (LocaleCompare("cdl",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001811 {
1812 char
1813 *color_correction_collection;
1814
1815 /*
1816 Color correct with a color decision list.
1817 */
anthonyfd706f92012-01-19 04:22:02 +00001818 color_correction_collection=FileToString(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00001819 if (color_correction_collection == (char *) NULL)
1820 break;
anthony31f1bf72012-01-30 12:37:22 +00001821 (void) ColorDecisionListImage(image,color_correction_collection,
anthony805a2d42011-09-25 08:25:12 +00001822 exception);
anthony805a2d42011-09-25 08:25:12 +00001823 break;
1824 }
anthonydcf510d2011-10-30 13:51:40 +00001825 if (LocaleCompare("channel",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001826 {
anthonyfd706f92012-01-19 04:22:02 +00001827 /* The "channel" setting has already been set
anthonyd1447672012-01-19 05:33:53 +00001828 FUTURE: This probably should be part of WandSettingOptionInfo()
anthonyfd706f92012-01-19 04:22:02 +00001829 or SyncImageSettings().
1830 */
anthony31f1bf72012-01-30 12:37:22 +00001831 SetPixelChannelMapMask(image,image_info->channel);
anthony805a2d42011-09-25 08:25:12 +00001832 break;
1833 }
cristy87c02f42012-02-24 00:19:10 +00001834 if (LocaleCompare("channel-extract",option) == 0)
1835 {
1836 puts("stand by...");
1837 break;
1838 }
1839 if (LocaleCompare("channel-swap",option) == 0)
1840 {
1841 puts("stand by...");
1842 break;
1843 }
anthonydcf510d2011-10-30 13:51:40 +00001844 if (LocaleCompare("charcoal",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001845 {
anthonyfd706f92012-01-19 04:22:02 +00001846 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00001847 if ((flags & SigmaValue) == 0)
1848 geometry_info.sigma=1.0;
1849 if ((flags & XiValue) == 0)
1850 geometry_info.xi=1.0;
anthony31f1bf72012-01-30 12:37:22 +00001851 new_image=CharcoalImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00001852 geometry_info.sigma,geometry_info.xi,exception);
1853 break;
1854 }
anthonydcf510d2011-10-30 13:51:40 +00001855 if (LocaleCompare("chop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001856 {
anthony31f1bf72012-01-30 12:37:22 +00001857 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
1858 new_image=ChopImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00001859 break;
1860 }
anthonydcf510d2011-10-30 13:51:40 +00001861 if (LocaleCompare("clamp",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001862 {
anthony31f1bf72012-01-30 12:37:22 +00001863 (void) ClampImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001864 break;
1865 }
anthony43f425d2012-02-26 12:58:58 +00001866 if (LocaleCompare("cli_wandp",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001867 {
anthonyfd706f92012-01-19 04:22:02 +00001868 if (plus_alt_op == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001869 (void) ClipImage(image,exception);
anthony43f425d2012-02-26 12:58:58 +00001870 else /* "+mask" remove the write mask */
anthony31f1bf72012-01-30 12:37:22 +00001871 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00001872 break;
1873 }
anthony43f425d2012-02-26 12:58:58 +00001874 if (LocaleCompare("cli_wandp-mask",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001875 {
1876 CacheView
1877 *mask_view;
1878
1879 Image
1880 *mask_image;
1881
1882 register Quantum
1883 *restrict q;
1884
1885 register ssize_t
1886 x;
1887
1888 ssize_t
1889 y;
1890
anthonyfd706f92012-01-19 04:22:02 +00001891 if (plus_alt_op != MagickFalse)
anthony43f425d2012-02-26 12:58:58 +00001892 { /* "+cli_wandp-mask" Remove the write mask */
anthony31f1bf72012-01-30 12:37:22 +00001893 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00001894 break;
1895 }
anthonyfd706f92012-01-19 04:22:02 +00001896 mask_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00001897 if (mask_image == (Image *) NULL)
1898 break;
anthonyfd706f92012-01-19 04:22:02 +00001899 if (SetImageStorageClass(mask_image,DirectClass,exception)
1900 == MagickFalse)
anthony31f1bf72012-01-30 12:37:22 +00001901 break;
anthony43f425d2012-02-26 12:58:58 +00001902 /* Create a write mask from cli_wandp-mask image */
anthonyfd706f92012-01-19 04:22:02 +00001903 /* FUTURE: use Alpha operations instead and create a Grey Image */
anthony805a2d42011-09-25 08:25:12 +00001904 mask_view=AcquireCacheView(mask_image);
1905 for (y=0; y < (ssize_t) mask_image->rows; y++)
1906 {
1907 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1908 exception);
1909 if (q == (Quantum *) NULL)
1910 break;
1911 for (x=0; x < (ssize_t) mask_image->columns; x++)
1912 {
1913 if (mask_image->matte == MagickFalse)
1914 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1915 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1916 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1917 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1918 q+=GetPixelChannels(mask_image);
1919 }
1920 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1921 break;
1922 }
anthonyfd706f92012-01-19 04:22:02 +00001923 /* clean up and set the write mask */
anthony805a2d42011-09-25 08:25:12 +00001924 mask_view=DestroyCacheView(mask_view);
1925 mask_image->matte=MagickTrue;
anthony31f1bf72012-01-30 12:37:22 +00001926 (void) SetImageMask(image,mask_image,exception);
anthony805a2d42011-09-25 08:25:12 +00001927 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00001928 break;
1929 }
anthony43f425d2012-02-26 12:58:58 +00001930 if (LocaleCompare("cli_wandp-path",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001931 {
anthony31f1bf72012-01-30 12:37:22 +00001932 (void) ClipImagePath(image,arg1,
anthonyfd706f92012-01-19 04:22:02 +00001933 (MagickBooleanType)(!(int)plus_alt_op),exception);
anthony805a2d42011-09-25 08:25:12 +00001934 break;
1935 }
anthonydcf510d2011-10-30 13:51:40 +00001936 if (LocaleCompare("colorize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001937 {
anthony31f1bf72012-01-30 12:37:22 +00001938 new_image=ColorizeImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00001939 break;
1940 }
anthonydcf510d2011-10-30 13:51:40 +00001941 if (LocaleCompare("color-matrix",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001942 {
1943 KernelInfo
1944 *kernel;
1945
anthonyfd706f92012-01-19 04:22:02 +00001946 kernel=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00001947 if (kernel == (KernelInfo *) NULL)
1948 break;
anthony31f1bf72012-01-30 12:37:22 +00001949 new_image=ColorMatrixImage(image,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00001950 kernel=DestroyKernelInfo(kernel);
1951 break;
1952 }
anthonydcf510d2011-10-30 13:51:40 +00001953 if (LocaleCompare("colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001954 {
anthonyfd706f92012-01-19 04:22:02 +00001955 /* Reduce the number of colors in the image.
1956 FUTURE: also provide 'plus version with image 'color counts'
1957 */
1958 quantize_info->number_colors=StringToUnsignedLong(arg1);
anthony805a2d42011-09-25 08:25:12 +00001959 if (quantize_info->number_colors == 0)
1960 break;
anthony31f1bf72012-01-30 12:37:22 +00001961 if ((image->storage_class == DirectClass) ||
1962 image->colors > quantize_info->number_colors)
1963 (void) QuantizeImage(quantize_info,image,exception);
anthony805a2d42011-09-25 08:25:12 +00001964 else
anthony31f1bf72012-01-30 12:37:22 +00001965 (void) CompressImageColormap(image,exception);
anthony805a2d42011-09-25 08:25:12 +00001966 break;
1967 }
anthonydcf510d2011-10-30 13:51:40 +00001968 if (LocaleCompare("colorspace",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001969 {
anthony31f1bf72012-01-30 12:37:22 +00001970 /* WARNING: this is both a image_info setting (already done)
1971 and a operator to change image colorspace.
1972
1973 FUTURE: default colorspace should be sRGB!
anthonyd2cdc862011-10-07 14:07:17 +00001974 Unless some type of 'linear colorspace' mode is set.
anthony31f1bf72012-01-30 12:37:22 +00001975
anthonyd2cdc862011-10-07 14:07:17 +00001976 Note that +colorspace sets "undefined" or no effect on
1977 new images, but forces images already in memory back to RGB!
anthony31f1bf72012-01-30 12:37:22 +00001978 That seems to be a little strange!
anthonyd2cdc862011-10-07 14:07:17 +00001979 */
anthony31f1bf72012-01-30 12:37:22 +00001980 (void) TransformImageColorspace(image,
1981 plus_alt_op ? RGBColorspace : image_info->colorspace,
anthony6613bf32011-10-15 07:24:44 +00001982 exception);
anthony805a2d42011-09-25 08:25:12 +00001983 break;
1984 }
anthonydcf510d2011-10-30 13:51:40 +00001985 if (LocaleCompare("contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001986 {
anthony31f1bf72012-01-30 12:37:22 +00001987 (void) ContrastImage(image,
anthonyfd706f92012-01-19 04:22:02 +00001988 (MagickBooleanType)(!(int)plus_alt_op),exception);
anthony805a2d42011-09-25 08:25:12 +00001989 break;
1990 }
anthonydcf510d2011-10-30 13:51:40 +00001991 if (LocaleCompare("contrast-stretch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00001992 {
1993 double
1994 black_point,
1995 white_point;
1996
1997 MagickStatusType
1998 flags;
1999
anthonyfd706f92012-01-19 04:22:02 +00002000 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002001 black_point=geometry_info.rho;
2002 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2003 black_point;
2004 if ((flags & PercentValue) != 0)
2005 {
anthony31f1bf72012-01-30 12:37:22 +00002006 black_point*=(double) image->columns*image->rows/100.0;
2007 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002008 }
anthony31f1bf72012-01-30 12:37:22 +00002009 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00002010 white_point;
anthony31f1bf72012-01-30 12:37:22 +00002011 (void) ContrastStretchImage(image,black_point,white_point,
anthony805a2d42011-09-25 08:25:12 +00002012 exception);
anthony805a2d42011-09-25 08:25:12 +00002013 break;
2014 }
anthonydcf510d2011-10-30 13:51:40 +00002015 if (LocaleCompare("convolve",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002016 {
2017 KernelInfo
2018 *kernel_info;
2019
anthonyfd706f92012-01-19 04:22:02 +00002020 kernel_info=AcquireKernelInfo(arg1);
anthony805a2d42011-09-25 08:25:12 +00002021 if (kernel_info == (KernelInfo *) NULL)
2022 break;
anthony31f1bf72012-01-30 12:37:22 +00002023 kernel_info->bias=image->bias;
2024 new_image=ConvolveImage(image,kernel_info,exception);
anthony805a2d42011-09-25 08:25:12 +00002025 kernel_info=DestroyKernelInfo(kernel_info);
2026 break;
2027 }
anthonydcf510d2011-10-30 13:51:40 +00002028 if (LocaleCompare("crop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002029 {
anthony31f1bf72012-01-30 12:37:22 +00002030 /* WARNING: This can generate multiple images! */
2031 new_image=CropImageToTiles(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002032 break;
2033 }
anthonydcf510d2011-10-30 13:51:40 +00002034 if (LocaleCompare("cycle",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002035 {
anthony31f1bf72012-01-30 12:37:22 +00002036 (void) CycleColormapImage(image,(ssize_t) StringToLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00002037 exception);
2038 break;
2039 }
2040 break;
2041 }
2042 case 'd':
2043 {
anthonydcf510d2011-10-30 13:51:40 +00002044 if (LocaleCompare("decipher",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002045 {
2046 StringInfo
2047 *passkey;
2048
anthonyfd706f92012-01-19 04:22:02 +00002049 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00002050 if (passkey != (StringInfo *) NULL)
2051 {
anthony31f1bf72012-01-30 12:37:22 +00002052 (void) PasskeyDecipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00002053 passkey=DestroyStringInfo(passkey);
2054 }
2055 break;
2056 }
anthonydcf510d2011-10-30 13:51:40 +00002057 if (LocaleCompare("depth",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002058 {
anthonydcf510d2011-10-30 13:51:40 +00002059 /* The image_info->depth setting has already been set
2060 We just need to apply it to all images in current sequence
anthony31f1bf72012-01-30 12:37:22 +00002061
anthonydcf510d2011-10-30 13:51:40 +00002062 WARNING: Depth from 8 to 16 causes 'quantum rounding to images!
2063 That is it really is an operation, not a setting! Arrgghhh
anthony31f1bf72012-01-30 12:37:22 +00002064
anthonyfd706f92012-01-19 04:22:02 +00002065 FUTURE: this should not be an operator!!!
anthonydcf510d2011-10-30 13:51:40 +00002066 */
anthony31f1bf72012-01-30 12:37:22 +00002067 (void) SetImageDepth(image,image_info->depth,exception);
anthony805a2d42011-09-25 08:25:12 +00002068 break;
2069 }
anthonydcf510d2011-10-30 13:51:40 +00002070 if (LocaleCompare("deskew",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002071 {
2072 double
2073 threshold;
2074
anthonyfd706f92012-01-19 04:22:02 +00002075 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002076 threshold=40.0*QuantumRange/100.0;
2077 else
anthonyfd706f92012-01-19 04:22:02 +00002078 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002079 new_image=DeskewImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00002080 break;
2081 }
anthonydcf510d2011-10-30 13:51:40 +00002082 if (LocaleCompare("despeckle",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002083 {
anthony31f1bf72012-01-30 12:37:22 +00002084 new_image=DespeckleImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002085 break;
2086 }
anthonydcf510d2011-10-30 13:51:40 +00002087 if (LocaleCompare("distort",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002088 {
2089 char
2090 *args,
2091 token[MaxTextExtent];
2092
2093 const char
2094 *p;
2095
2096 DistortImageMethod
2097 method;
2098
2099 double
2100 *arguments;
2101
2102 register ssize_t
2103 x;
2104
2105 size_t
2106 number_arguments;
2107
anthony805a2d42011-09-25 08:25:12 +00002108 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
anthonyfd706f92012-01-19 04:22:02 +00002109 MagickFalse,arg1);
anthony80c37752012-01-16 01:03:11 +00002110 if (method == ResizeDistortion)
anthony805a2d42011-09-25 08:25:12 +00002111 {
anthony80c37752012-01-16 01:03:11 +00002112 double
2113 resize_args[2];
anthony805a2d42011-09-25 08:25:12 +00002114 /* Special Case - Argument is actually a resize geometry!
2115 ** Convert that to an appropriate distortion argument array.
anthonyfd706f92012-01-19 04:22:02 +00002116 ** FUTURE: make a separate special resize operator
anthony805a2d42011-09-25 08:25:12 +00002117 */
anthony31f1bf72012-01-30 12:37:22 +00002118 (void) ParseRegionGeometry(image,arg2,&geometry,
anthony80c37752012-01-16 01:03:11 +00002119 exception);
2120 resize_args[0]=(double) geometry.width;
2121 resize_args[1]=(double) geometry.height;
anthony31f1bf72012-01-30 12:37:22 +00002122 new_image=DistortImage(image,method,(size_t)2,
anthony80c37752012-01-16 01:03:11 +00002123 resize_args,MagickTrue,exception);
anthony805a2d42011-09-25 08:25:12 +00002124 break;
2125 }
anthonyfd706f92012-01-19 04:22:02 +00002126 /* handle percent arguments */
anthony31f1bf72012-01-30 12:37:22 +00002127 args=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002128 exception);
2129 if (args == (char *) NULL)
2130 break;
anthonyfd706f92012-01-19 04:22:02 +00002131 /* convert arguments into an array of doubles
2132 FUTURE: make this a separate function.
2133 Also make use of new 'sentinal' feature to avoid need for
2134 tokenization.
2135 */
anthony805a2d42011-09-25 08:25:12 +00002136 p=(char *) args;
2137 for (x=0; *p != '\0'; x++)
2138 {
2139 GetMagickToken(p,&p,token);
2140 if (*token == ',')
2141 GetMagickToken(p,&p,token);
2142 }
2143 number_arguments=(size_t) x;
2144 arguments=(double *) AcquireQuantumMemory(number_arguments,
2145 sizeof(*arguments));
2146 if (arguments == (double *) NULL)
2147 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002148 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002149 (void) ResetMagickMemory(arguments,0,number_arguments*
2150 sizeof(*arguments));
2151 p=(char *) args;
2152 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2153 {
2154 GetMagickToken(p,&p,token);
2155 if (*token == ',')
2156 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002157 arguments[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002158 }
2159 args=DestroyString(args);
anthony31f1bf72012-01-30 12:37:22 +00002160 new_image=DistortImage(image,method,number_arguments,arguments,
anthonyfd706f92012-01-19 04:22:02 +00002161 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002162 arguments=(double *) RelinquishMagickMemory(arguments);
2163 break;
2164 }
anthonydcf510d2011-10-30 13:51:40 +00002165 if (LocaleCompare("draw",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002166 {
anthonyfd706f92012-01-19 04:22:02 +00002167 (void) CloneString(&draw_info->primitive,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002168 (void) DrawImage(image,draw_info,exception);
anthonyfd706f92012-01-19 04:22:02 +00002169 (void) CloneString(&draw_info->primitive,(char *)NULL);
anthony805a2d42011-09-25 08:25:12 +00002170 break;
2171 }
2172 break;
2173 }
2174 case 'e':
2175 {
anthonydcf510d2011-10-30 13:51:40 +00002176 if (LocaleCompare("edge",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002177 {
anthonyfd706f92012-01-19 04:22:02 +00002178 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002179 if ((flags & SigmaValue) == 0)
2180 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002181 new_image=EdgeImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002182 geometry_info.sigma,exception);
2183 break;
2184 }
anthonydcf510d2011-10-30 13:51:40 +00002185 if (LocaleCompare("emboss",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002186 {
anthonyfd706f92012-01-19 04:22:02 +00002187 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002188 if ((flags & SigmaValue) == 0)
2189 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002190 new_image=EmbossImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002191 geometry_info.sigma,exception);
2192 break;
2193 }
anthonydcf510d2011-10-30 13:51:40 +00002194 if (LocaleCompare("encipher",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002195 {
2196 StringInfo
2197 *passkey;
2198
anthonyfd706f92012-01-19 04:22:02 +00002199 passkey=FileToStringInfo(arg1,~0,exception);
anthony805a2d42011-09-25 08:25:12 +00002200 if (passkey != (StringInfo *) NULL)
2201 {
anthony31f1bf72012-01-30 12:37:22 +00002202 (void) PasskeyEncipherImage(image,passkey,exception);
anthony805a2d42011-09-25 08:25:12 +00002203 passkey=DestroyStringInfo(passkey);
2204 }
2205 break;
2206 }
anthonydcf510d2011-10-30 13:51:40 +00002207 if (LocaleCompare("enhance",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002208 {
anthony31f1bf72012-01-30 12:37:22 +00002209 new_image=EnhanceImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002210 break;
2211 }
anthonydcf510d2011-10-30 13:51:40 +00002212 if (LocaleCompare("equalize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002213 {
anthony31f1bf72012-01-30 12:37:22 +00002214 (void) EqualizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002215 break;
2216 }
anthonydcf510d2011-10-30 13:51:40 +00002217 if (LocaleCompare("evaluate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002218 {
2219 double
2220 constant;
2221
2222 MagickEvaluateOperator
2223 op;
2224
anthony805a2d42011-09-25 08:25:12 +00002225 op=(MagickEvaluateOperator) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00002226 MagickEvaluateOptions,MagickFalse,arg1);
2227 constant=StringToDoubleInterval(arg2,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00002228 (void) EvaluateImage(image,op,constant,exception);
anthony805a2d42011-09-25 08:25:12 +00002229 break;
2230 }
anthonydcf510d2011-10-30 13:51:40 +00002231 if (LocaleCompare("extent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002232 {
anthony31f1bf72012-01-30 12:37:22 +00002233 flags=ParseGravityGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002234 if (geometry.width == 0)
anthony31f1bf72012-01-30 12:37:22 +00002235 geometry.width=image->columns;
anthony805a2d42011-09-25 08:25:12 +00002236 if (geometry.height == 0)
anthony31f1bf72012-01-30 12:37:22 +00002237 geometry.height=image->rows;
2238 new_image=ExtentImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002239 break;
2240 }
2241 break;
2242 }
2243 case 'f':
2244 {
anthonydcf510d2011-10-30 13:51:40 +00002245 if (LocaleCompare("features",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002246 {
anthony31f1bf72012-01-30 12:37:22 +00002247 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
2248 if (plus_alt_op != MagickFalse)
2249 {
2250 (void) DeleteImageArtifact(image,"identify:features");
2251 break;
2252 }
2253 (void) SetImageArtifact(image,"identify:features","true");
2254 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00002255 break;
2256 }
anthonydcf510d2011-10-30 13:51:40 +00002257 if (LocaleCompare("flip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002258 {
anthony31f1bf72012-01-30 12:37:22 +00002259 new_image=FlipImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002260 break;
2261 }
anthonydcf510d2011-10-30 13:51:40 +00002262 if (LocaleCompare("flop",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002263 {
anthony31f1bf72012-01-30 12:37:22 +00002264 new_image=FlopImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002265 break;
2266 }
anthonydcf510d2011-10-30 13:51:40 +00002267 if (LocaleCompare("floodfill",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002268 {
2269 PixelInfo
2270 target;
2271
anthony31f1bf72012-01-30 12:37:22 +00002272 (void) ParsePageGeometry(image,arg1,&geometry,exception);
anthonyfd706f92012-01-19 04:22:02 +00002273 (void) QueryColorCompliance(arg2,AllCompliance,&target,exception);
anthony31f1bf72012-01-30 12:37:22 +00002274 (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
anthonyfd706f92012-01-19 04:22:02 +00002275 geometry.y,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002276 break;
2277 }
anthonydcf510d2011-10-30 13:51:40 +00002278 if (LocaleCompare("frame",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002279 {
2280 FrameInfo
2281 frame_info;
2282
anthony31f1bf72012-01-30 12:37:22 +00002283 CompositeOperator
anthonyfd706f92012-01-19 04:22:02 +00002284 compose;
2285
2286 const char*
2287 value;
2288
2289 value=GetImageOption(image_info,"compose");
2290 if (value != (const char *) NULL)
2291 compose=(CompositeOperator) ParseCommandOption(
2292 MagickComposeOptions,MagickFalse,value);
2293 else
2294 compose=OverCompositeOp; /* use Over not image->compose */
2295
anthony31f1bf72012-01-30 12:37:22 +00002296 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002297 frame_info.width=geometry.width;
2298 frame_info.height=geometry.height;
2299 if ((flags & HeightValue) == 0)
2300 frame_info.height=geometry.width;
2301 frame_info.outer_bevel=geometry.x;
2302 frame_info.inner_bevel=geometry.y;
2303 frame_info.x=(ssize_t) frame_info.width;
2304 frame_info.y=(ssize_t) frame_info.height;
anthony31f1bf72012-01-30 12:37:22 +00002305 frame_info.width=image->columns+2*frame_info.width;
2306 frame_info.height=image->rows+2*frame_info.height;
2307 new_image=FrameImage(image,&frame_info,compose,exception);
anthony805a2d42011-09-25 08:25:12 +00002308 break;
2309 }
anthonydcf510d2011-10-30 13:51:40 +00002310 if (LocaleCompare("function",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002311 {
2312 char
2313 *arguments,
2314 token[MaxTextExtent];
2315
2316 const char
2317 *p;
2318
2319 double
2320 *parameters;
2321
2322 MagickFunction
2323 function;
2324
2325 register ssize_t
2326 x;
2327
2328 size_t
2329 number_parameters;
2330
cristy947cb4c2011-10-20 18:41:46 +00002331 /*
2332 Function Modify Image Values
anthonyfd706f92012-01-19 04:22:02 +00002333 FUTURE: code should be almost a duplicate of that is "distort"
cristy947cb4c2011-10-20 18:41:46 +00002334 */
anthony805a2d42011-09-25 08:25:12 +00002335 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
anthonyfd706f92012-01-19 04:22:02 +00002336 MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00002337 arguments=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00002338 exception);
2339 if (arguments == (char *) NULL)
2340 break;
2341 p=(char *) arguments;
2342 for (x=0; *p != '\0'; x++)
2343 {
2344 GetMagickToken(p,&p,token);
2345 if (*token == ',')
2346 GetMagickToken(p,&p,token);
2347 }
2348 number_parameters=(size_t) x;
2349 parameters=(double *) AcquireQuantumMemory(number_parameters,
2350 sizeof(*parameters));
2351 if (parameters == (double *) NULL)
2352 ThrowWandFatalException(ResourceLimitFatalError,
anthony31f1bf72012-01-30 12:37:22 +00002353 "MemoryAllocationFailed",image->filename);
anthony805a2d42011-09-25 08:25:12 +00002354 (void) ResetMagickMemory(parameters,0,number_parameters*
2355 sizeof(*parameters));
2356 p=(char *) arguments;
2357 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2358 {
2359 GetMagickToken(p,&p,token);
2360 if (*token == ',')
2361 GetMagickToken(p,&p,token);
cristydbdd0e32011-11-04 23:29:40 +00002362 parameters[x]=StringToDouble(token,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002363 }
2364 arguments=DestroyString(arguments);
anthony31f1bf72012-01-30 12:37:22 +00002365 (void) FunctionImage(image,function,number_parameters,parameters,
anthony805a2d42011-09-25 08:25:12 +00002366 exception);
2367 parameters=(double *) RelinquishMagickMemory(parameters);
2368 break;
2369 }
2370 break;
2371 }
2372 case 'g':
2373 {
anthonydcf510d2011-10-30 13:51:40 +00002374 if (LocaleCompare("gamma",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002375 {
anthony31f1bf72012-01-30 12:37:22 +00002376 if (plus_alt_op != MagickFalse)
2377 image->gamma=StringToDouble(arg1,(char **) NULL);
anthony805a2d42011-09-25 08:25:12 +00002378 else
anthony31f1bf72012-01-30 12:37:22 +00002379 (void) GammaImage(image,StringToDouble(arg1,(char **) NULL),
anthonyfd706f92012-01-19 04:22:02 +00002380 exception);
anthony805a2d42011-09-25 08:25:12 +00002381 break;
2382 }
anthonydcf510d2011-10-30 13:51:40 +00002383 if ((LocaleCompare("gaussian-blur",option) == 0) ||
2384 (LocaleCompare("gaussian",option) == 0))
anthony805a2d42011-09-25 08:25:12 +00002385 {
anthonyfd706f92012-01-19 04:22:02 +00002386 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002387 if ((flags & SigmaValue) == 0)
2388 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002389 new_image=GaussianBlurImage(image,geometry_info.rho,
cristyd89705a2012-01-20 02:52:24 +00002390 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00002391 break;
2392 }
anthonydcf510d2011-10-30 13:51:40 +00002393 if (LocaleCompare("geometry",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002394 {
anthonyfd706f92012-01-19 04:22:02 +00002395 /*
anthony31f1bf72012-01-30 12:37:22 +00002396 Record Image offset for composition. (A Setting)
2397 Resize last image. (ListOperator)
2398 FUTURE: Why if no 'offset' does this resize ALL images?
2399 Also why is the setting recorded in the IMAGE non-sense!
anthonyfd706f92012-01-19 04:22:02 +00002400 */
anthony31f1bf72012-01-30 12:37:22 +00002401 if (plus_alt_op != MagickFalse)
anthonyfd706f92012-01-19 04:22:02 +00002402 { /* remove the previous composition geometry offset! */
anthony31f1bf72012-01-30 12:37:22 +00002403 if (image->geometry != (char *) NULL)
2404 image->geometry=DestroyString(image->geometry);
anthony805a2d42011-09-25 08:25:12 +00002405 break;
2406 }
anthony31f1bf72012-01-30 12:37:22 +00002407 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002408 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
anthony31f1bf72012-01-30 12:37:22 +00002409 (void) CloneString(&image->geometry,arg1);
anthony805a2d42011-09-25 08:25:12 +00002410 else
anthony31f1bf72012-01-30 12:37:22 +00002411 new_image=ResizeImage(image,geometry.width,geometry.height,
2412 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002413 break;
2414 }
anthony805a2d42011-09-25 08:25:12 +00002415 break;
2416 }
2417 case 'h':
2418 {
anthonydcf510d2011-10-30 13:51:40 +00002419 if (LocaleCompare("highlight-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002420 {
anthony31f1bf72012-01-30 12:37:22 +00002421 (void) SetImageArtifact(image,option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002422 break;
2423 }
2424 break;
2425 }
2426 case 'i':
2427 {
anthonydcf510d2011-10-30 13:51:40 +00002428 if (LocaleCompare("identify",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002429 {
anthony31f1bf72012-01-30 12:37:22 +00002430 const char
2431 *format,
anthony805a2d42011-09-25 08:25:12 +00002432 *text;
2433
anthony31f1bf72012-01-30 12:37:22 +00002434 format=GetImageOption(image_info,"format");
anthony805a2d42011-09-25 08:25:12 +00002435 if (format == (char *) NULL)
2436 {
anthony31f1bf72012-01-30 12:37:22 +00002437 (void) IdentifyImage(image,stdout,image_info->verbose,
anthony805a2d42011-09-25 08:25:12 +00002438 exception);
2439 break;
2440 }
anthony31f1bf72012-01-30 12:37:22 +00002441 text=InterpretImageProperties(image_info,image,format,exception);
anthony805a2d42011-09-25 08:25:12 +00002442 if (text == (char *) NULL)
2443 break;
2444 (void) fputs(text,stdout);
2445 (void) fputc('\n',stdout);
anthony31f1bf72012-01-30 12:37:22 +00002446 text=DestroyString((char *)text);
anthony805a2d42011-09-25 08:25:12 +00002447 break;
2448 }
anthonydcf510d2011-10-30 13:51:40 +00002449 if (LocaleCompare("implode",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002450 {
anthonyfd706f92012-01-19 04:22:02 +00002451 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002452 new_image=ImplodeImage(image,geometry_info.rho,
2453 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002454 break;
2455 }
anthonyfd706f92012-01-19 04:22:02 +00002456 if (LocaleCompare("interpolative-resize",option) == 0)
cristy947cb4c2011-10-20 18:41:46 +00002457 {
anthony31f1bf72012-01-30 12:37:22 +00002458 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2459 new_image=InterpolativeResizeImage(image,geometry.width,
2460 geometry.height,image->interpolate,exception);
cristy947cb4c2011-10-20 18:41:46 +00002461 break;
2462 }
anthony805a2d42011-09-25 08:25:12 +00002463 break;
2464 }
2465 case 'l':
2466 {
anthonydcf510d2011-10-30 13:51:40 +00002467 if (LocaleCompare("lat",option) == 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 & PercentValue) != 0)
2471 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002472 new_image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
2473 (size_t) geometry_info.sigma,(double) geometry_info.xi,
2474 exception);
anthony805a2d42011-09-25 08:25:12 +00002475 break;
2476 }
anthonydcf510d2011-10-30 13:51:40 +00002477 if (LocaleCompare("level",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002478 {
2479 MagickRealType
2480 black_point,
2481 gamma,
2482 white_point;
2483
2484 MagickStatusType
2485 flags;
2486
anthonyfd706f92012-01-19 04:22:02 +00002487 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002488 black_point=geometry_info.rho;
2489 white_point=(MagickRealType) QuantumRange;
2490 if ((flags & SigmaValue) != 0)
2491 white_point=geometry_info.sigma;
2492 gamma=1.0;
2493 if ((flags & XiValue) != 0)
2494 gamma=geometry_info.xi;
2495 if ((flags & PercentValue) != 0)
2496 {
2497 black_point*=(MagickRealType) (QuantumRange/100.0);
2498 white_point*=(MagickRealType) (QuantumRange/100.0);
2499 }
2500 if ((flags & SigmaValue) == 0)
2501 white_point=(MagickRealType) QuantumRange-black_point;
anthony31f1bf72012-01-30 12:37:22 +00002502 if (plus_alt_op || ((flags & AspectValue) != 0))
2503 (void) LevelizeImage(image,black_point,white_point,gamma,
anthony805a2d42011-09-25 08:25:12 +00002504 exception);
2505 else
anthony31f1bf72012-01-30 12:37:22 +00002506 (void) LevelImage(image,black_point,white_point,gamma,
anthony805a2d42011-09-25 08:25:12 +00002507 exception);
anthony805a2d42011-09-25 08:25:12 +00002508 break;
2509 }
anthonydcf510d2011-10-30 13:51:40 +00002510 if (LocaleCompare("level-colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002511 {
2512 char
2513 token[MaxTextExtent];
2514
2515 const char
2516 *p;
2517
2518 PixelInfo
2519 black_point,
2520 white_point;
2521
anthonyfd706f92012-01-19 04:22:02 +00002522 p=(const char *) arg1;
anthony805a2d42011-09-25 08:25:12 +00002523 GetMagickToken(p,&p,token); /* get black point color */
2524 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002525 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002526 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002527 else
cristy269c9412011-10-13 23:41:15 +00002528 (void) QueryColorCompliance("#000000",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002529 &black_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002530 if (isalpha((int) token[0]) || (token[0] == '#'))
2531 GetMagickToken(p,&p,token);
2532 if (*token == '\0')
2533 white_point=black_point; /* set everything to that color */
2534 else
2535 {
2536 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2537 GetMagickToken(p,&p,token); /* Get white point color. */
2538 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
cristy269c9412011-10-13 23:41:15 +00002539 (void) QueryColorCompliance(token,AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002540 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002541 else
cristy269c9412011-10-13 23:41:15 +00002542 (void) QueryColorCompliance("#ffffff",AllCompliance,
anthonya89dd172011-10-04 13:29:35 +00002543 &white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002544 }
anthony31f1bf72012-01-30 12:37:22 +00002545 (void) LevelImageColors(image,&black_point,&white_point,
2546 plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002547 break;
2548 }
anthonydcf510d2011-10-30 13:51:40 +00002549 if (LocaleCompare("linear-stretch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002550 {
2551 double
2552 black_point,
2553 white_point;
2554
2555 MagickStatusType
2556 flags;
2557
anthonyfd706f92012-01-19 04:22:02 +00002558 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002559 black_point=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002560 white_point=(MagickRealType) image->columns*image->rows;
anthony805a2d42011-09-25 08:25:12 +00002561 if ((flags & SigmaValue) != 0)
2562 white_point=geometry_info.sigma;
2563 if ((flags & PercentValue) != 0)
2564 {
anthony31f1bf72012-01-30 12:37:22 +00002565 black_point*=(double) image->columns*image->rows/100.0;
2566 white_point*=(double) image->columns*image->rows/100.0;
anthony805a2d42011-09-25 08:25:12 +00002567 }
2568 if ((flags & SigmaValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00002569 white_point=(MagickRealType) image->columns*image->rows-
anthony805a2d42011-09-25 08:25:12 +00002570 black_point;
anthony31f1bf72012-01-30 12:37:22 +00002571 (void) LinearStretchImage(image,black_point,white_point,exception);
anthony805a2d42011-09-25 08:25:12 +00002572 break;
2573 }
anthonydcf510d2011-10-30 13:51:40 +00002574 if (LocaleCompare("liquid-rescale",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002575 {
anthony31f1bf72012-01-30 12:37:22 +00002576 flags=ParseRegionGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002577 if ((flags & XValue) == 0)
2578 geometry.x=1;
2579 if ((flags & YValue) == 0)
2580 geometry.y=0;
anthony31f1bf72012-01-30 12:37:22 +00002581 new_image=LiquidRescaleImage(image,geometry.width,
anthony805a2d42011-09-25 08:25:12 +00002582 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2583 break;
2584 }
anthonydcf510d2011-10-30 13:51:40 +00002585 if (LocaleCompare("lowlight-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002586 {
anthony31f1bf72012-01-30 12:37:22 +00002587 (void) SetImageArtifact(image,option,arg1);
anthony805a2d42011-09-25 08:25:12 +00002588 break;
2589 }
2590 break;
2591 }
2592 case 'm':
2593 {
anthonydcf510d2011-10-30 13:51:40 +00002594 if (LocaleCompare("map",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002595 {
2596 Image
2597 *remap_image;
2598
anthony31f1bf72012-01-30 12:37:22 +00002599 /* DEPRECIATED use -remap */
anthonyfd706f92012-01-19 04:22:02 +00002600 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002601 if (remap_image == (Image *) NULL)
2602 break;
anthony31f1bf72012-01-30 12:37:22 +00002603 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002604 remap_image=DestroyImage(remap_image);
2605 break;
2606 }
anthonydcf510d2011-10-30 13:51:40 +00002607 if (LocaleCompare("mask",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002608 {
2609 Image
2610 *mask;
2611
anthony31f1bf72012-01-30 12:37:22 +00002612 if (plus_alt_op != MagickFalse)
2613 { /* Remove a mask. */
2614 (void) SetImageMask(image,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00002615 break;
2616 }
anthony31f1bf72012-01-30 12:37:22 +00002617 /* Set the image mask. */
anthonyfd706f92012-01-19 04:22:02 +00002618 mask=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002619 if (mask == (Image *) NULL)
2620 break;
anthony31f1bf72012-01-30 12:37:22 +00002621 (void) SetImageMask(image,mask,exception);
anthony805a2d42011-09-25 08:25:12 +00002622 mask=DestroyImage(mask);
2623 break;
2624 }
anthonydcf510d2011-10-30 13:51:40 +00002625 if (LocaleCompare("matte",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002626 {
anthony31f1bf72012-01-30 12:37:22 +00002627 /* DEPRECIATED */
2628 (void) SetImageAlphaChannel(image,plus_alt_op ?
2629 DeactivateAlphaChannel:SetAlphaChannel ,exception);
anthony805a2d42011-09-25 08:25:12 +00002630 break;
2631 }
anthonydcf510d2011-10-30 13:51:40 +00002632 if (LocaleCompare("mode",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002633 {
anthonyfd706f92012-01-19 04:22:02 +00002634 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002635 if ((flags & SigmaValue) == 0)
2636 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002637 new_image=StatisticImage(image,ModeStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002638 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2639 break;
2640 }
anthonydcf510d2011-10-30 13:51:40 +00002641 if (LocaleCompare("modulate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002642 {
anthony31f1bf72012-01-30 12:37:22 +00002643 (void) ModulateImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002644 break;
2645 }
anthonydcf510d2011-10-30 13:51:40 +00002646 if (LocaleCompare("monitor",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002647 {
anthony31f1bf72012-01-30 12:37:22 +00002648 (void) SetImageProgressMonitor(image, plus_alt_op?
2649 (MagickProgressMonitor) NULL:MonitorProgress,(void *) NULL);
anthony805a2d42011-09-25 08:25:12 +00002650 break;
2651 }
anthonydcf510d2011-10-30 13:51:40 +00002652 if (LocaleCompare("monochrome",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002653 {
anthony31f1bf72012-01-30 12:37:22 +00002654 (void) SetImageType(image,BilevelType,exception);
anthony805a2d42011-09-25 08:25:12 +00002655 break;
2656 }
anthonydcf510d2011-10-30 13:51:40 +00002657 if (LocaleCompare("morphology",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002658 {
2659 char
2660 token[MaxTextExtent];
2661
2662 const char
2663 *p;
2664
2665 KernelInfo
2666 *kernel;
2667
2668 MorphologyMethod
2669 method;
2670
2671 ssize_t
2672 iterations;
2673
anthonyfd706f92012-01-19 04:22:02 +00002674 p=arg1;
anthony805a2d42011-09-25 08:25:12 +00002675 GetMagickToken(p,&p,token);
2676 method=(MorphologyMethod) ParseCommandOption(
2677 MagickMorphologyOptions,MagickFalse,token);
2678 iterations=1L;
2679 GetMagickToken(p,&p,token);
2680 if ((*p == ':') || (*p == ','))
2681 GetMagickToken(p,&p,token);
2682 if ((*p != '\0'))
2683 iterations=(ssize_t) StringToLong(p);
anthonyfd706f92012-01-19 04:22:02 +00002684 kernel=AcquireKernelInfo(arg2);
anthony805a2d42011-09-25 08:25:12 +00002685 if (kernel == (KernelInfo *) NULL)
2686 {
2687 (void) ThrowMagickException(exception,GetMagickModule(),
anthony31f1bf72012-01-30 12:37:22 +00002688 OptionError,"UnabletoParseKernel","morphology");
anthony805a2d42011-09-25 08:25:12 +00002689 break;
2690 }
anthony31f1bf72012-01-30 12:37:22 +00002691 new_image=MorphologyImage(image,method,iterations,kernel,exception);
anthony805a2d42011-09-25 08:25:12 +00002692 kernel=DestroyKernelInfo(kernel);
2693 break;
2694 }
anthonydcf510d2011-10-30 13:51:40 +00002695 if (LocaleCompare("motion-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002696 {
anthonyfd706f92012-01-19 04:22:02 +00002697 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002698 if ((flags & SigmaValue) == 0)
2699 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00002700 new_image=MotionBlurImage(image,geometry_info.rho,
2701 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
2702 exception);
anthony805a2d42011-09-25 08:25:12 +00002703 break;
2704 }
2705 break;
2706 }
2707 case 'n':
2708 {
anthonydcf510d2011-10-30 13:51:40 +00002709 if (LocaleCompare("negate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002710 {
anthony31f1bf72012-01-30 12:37:22 +00002711 (void) NegateImage(image, plus_alt_op, exception);
anthony805a2d42011-09-25 08:25:12 +00002712 break;
2713 }
anthonydcf510d2011-10-30 13:51:40 +00002714 if (LocaleCompare("noise",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002715 {
anthony31f1bf72012-01-30 12:37:22 +00002716 if (plus_alt_op == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00002717 {
anthonyfd706f92012-01-19 04:22:02 +00002718 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002719 if ((flags & SigmaValue) == 0)
2720 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002721 new_image=StatisticImage(image,NonpeakStatistic,(size_t)
anthony805a2d42011-09-25 08:25:12 +00002722 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2723 }
2724 else
2725 {
2726 NoiseType
2727 noise;
2728
anthony31f1bf72012-01-30 12:37:22 +00002729 double
2730 attenuate;
2731
2732 const char*
2733 value;
2734
anthony805a2d42011-09-25 08:25:12 +00002735 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
anthony31f1bf72012-01-30 12:37:22 +00002736 MagickFalse,arg1),
2737
2738 value=GetImageOption(image_info,"attenuate");
2739 if (value != (const char *) NULL)
2740 attenuate=StringToDouble(value,(char **) NULL);
2741 else
2742 attenuate=1.0;
2743
2744 new_image=AddNoiseImage(image,noise,attenuate,exception);
anthony805a2d42011-09-25 08:25:12 +00002745 }
2746 break;
2747 }
anthonydcf510d2011-10-30 13:51:40 +00002748 if (LocaleCompare("normalize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002749 {
anthony31f1bf72012-01-30 12:37:22 +00002750 (void) NormalizeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00002751 break;
2752 }
2753 break;
2754 }
2755 case 'o':
2756 {
anthonydcf510d2011-10-30 13:51:40 +00002757 if (LocaleCompare("opaque",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002758 {
2759 PixelInfo
2760 target;
2761
anthony31f1bf72012-01-30 12:37:22 +00002762 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
2763 (void) OpaquePaintImage(image,&target,&draw_info->fill,plus_alt_op,
2764 exception);
anthony805a2d42011-09-25 08:25:12 +00002765 break;
2766 }
anthonydcf510d2011-10-30 13:51:40 +00002767 if (LocaleCompare("ordered-dither",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002768 {
anthony31f1bf72012-01-30 12:37:22 +00002769 (void) OrderedPosterizeImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002770 break;
2771 }
2772 break;
2773 }
2774 case 'p':
2775 {
anthonydcf510d2011-10-30 13:51:40 +00002776 if (LocaleCompare("paint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002777 {
anthonyfd706f92012-01-19 04:22:02 +00002778 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002779 new_image=OilPaintImage(image,geometry_info.rho,geometry_info.sigma,
2780 exception);
anthony805a2d42011-09-25 08:25:12 +00002781 break;
2782 }
anthonydcf510d2011-10-30 13:51:40 +00002783 if (LocaleCompare("polaroid",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002784 {
cristye9e3d382011-12-14 01:50:13 +00002785 const char
2786 *caption;
2787
anthony805a2d42011-09-25 08:25:12 +00002788 double
2789 angle;
2790
anthony31f1bf72012-01-30 12:37:22 +00002791 if (plus_alt_op != MagickFalse)
2792 {
2793 RandomInfo
2794 *random_info;
anthony805a2d42011-09-25 08:25:12 +00002795
anthony31f1bf72012-01-30 12:37:22 +00002796 random_info=AcquireRandomInfo();
2797 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
2798 random_info=DestroyRandomInfo(random_info);
2799 }
2800 else
anthony805a2d42011-09-25 08:25:12 +00002801 {
2802 SetGeometryInfo(&geometry_info);
anthonyfd706f92012-01-19 04:22:02 +00002803 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002804 angle=geometry_info.rho;
2805 }
anthony31f1bf72012-01-30 12:37:22 +00002806 caption=GetImageProperty(image,"caption",exception);
2807 new_image=PolaroidImage(image,draw_info,caption,angle,
2808 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00002809 break;
2810 }
anthonydcf510d2011-10-30 13:51:40 +00002811 if (LocaleCompare("posterize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002812 {
anthony31f1bf72012-01-30 12:37:22 +00002813 (void) ParseGeometry(arg1,&geometry_info);
2814 (void) PosterizeImage(image,(size_t) geometry_info.rho,
2815 quantize_info->dither,exception);
anthony805a2d42011-09-25 08:25:12 +00002816 break;
2817 }
anthonydcf510d2011-10-30 13:51:40 +00002818 if (LocaleCompare("preview",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002819 {
2820 PreviewType
cristy947cb4c2011-10-20 18:41:46 +00002821 preview_type;
anthony170fce92011-10-20 11:50:23 +00002822
anthony31f1bf72012-01-30 12:37:22 +00002823 /* FUTURE: should be a 'Genesis' option?
2824 Option however is also in WandSettingOptionInfo()
cristy947cb4c2011-10-20 18:41:46 +00002825 */
anthony31f1bf72012-01-30 12:37:22 +00002826 preview_type=UndefinedPreview;
2827 if (plus_alt_op == MagickFalse)
2828 preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
2829 MagickFalse,arg1);
2830 new_image=PreviewImage(image,preview_type,exception);
anthony805a2d42011-09-25 08:25:12 +00002831 break;
2832 }
anthonydcf510d2011-10-30 13:51:40 +00002833 if (LocaleCompare("profile",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002834 {
2835 const char
2836 *name;
2837
2838 const StringInfo
2839 *profile;
2840
2841 Image
2842 *profile_image;
2843
2844 ImageInfo
2845 *profile_info;
2846
anthony31f1bf72012-01-30 12:37:22 +00002847 if (plus_alt_op != MagickFalse)
2848 { /* Remove a profile from the image. */
2849 (void) ProfileImage(image,arg1,(const unsigned char *)
cristy092d71c2011-10-14 18:01:29 +00002850 NULL,0,exception);
anthony805a2d42011-09-25 08:25:12 +00002851 break;
2852 }
anthony31f1bf72012-01-30 12:37:22 +00002853 /* Associate a profile with the image. */
anthony805a2d42011-09-25 08:25:12 +00002854 profile_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00002855 profile=GetImageProfile(image,"iptc");
anthony805a2d42011-09-25 08:25:12 +00002856 if (profile != (StringInfo *) NULL)
2857 profile_info->profile=(void *) CloneStringInfo(profile);
anthonyfd706f92012-01-19 04:22:02 +00002858 profile_image=GetImageCache(profile_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002859 profile_info=DestroyImageInfo(profile_info);
2860 if (profile_image == (Image *) NULL)
2861 {
2862 StringInfo
2863 *profile;
2864
2865 profile_info=CloneImageInfo(image_info);
anthonyfd706f92012-01-19 04:22:02 +00002866 (void) CopyMagickString(profile_info->filename,arg1,
anthony805a2d42011-09-25 08:25:12 +00002867 MaxTextExtent);
2868 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
2869 if (profile != (StringInfo *) NULL)
2870 {
anthony31f1bf72012-01-30 12:37:22 +00002871 (void) ProfileImage(image,profile_info->magick,
anthony805a2d42011-09-25 08:25:12 +00002872 GetStringInfoDatum(profile),(size_t)
cristy092d71c2011-10-14 18:01:29 +00002873 GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002874 profile=DestroyStringInfo(profile);
2875 }
2876 profile_info=DestroyImageInfo(profile_info);
2877 break;
2878 }
2879 ResetImageProfileIterator(profile_image);
2880 name=GetNextImageProfile(profile_image);
2881 while (name != (const char *) NULL)
2882 {
2883 profile=GetImageProfile(profile_image,name);
2884 if (profile != (StringInfo *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002885 (void) ProfileImage(image,name,GetStringInfoDatum(profile),
cristy092d71c2011-10-14 18:01:29 +00002886 (size_t) GetStringInfoLength(profile),exception);
anthony805a2d42011-09-25 08:25:12 +00002887 name=GetNextImageProfile(profile_image);
2888 }
2889 profile_image=DestroyImage(profile_image);
2890 break;
2891 }
2892 break;
2893 }
anthony805a2d42011-09-25 08:25:12 +00002894 case 'r':
2895 {
anthonydcf510d2011-10-30 13:51:40 +00002896 if (LocaleCompare("radial-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002897 {
anthonyfd706f92012-01-19 04:22:02 +00002898 flags=ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002899 new_image=RadialBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002900 geometry_info.sigma,exception);
2901 break;
2902 }
anthonydcf510d2011-10-30 13:51:40 +00002903 if (LocaleCompare("raise",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002904 {
anthony31f1bf72012-01-30 12:37:22 +00002905 flags=ParsePageGeometry(image,arg1,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00002906 if ((flags & SigmaValue) == 0)
2907 geometry.height=geometry.width;
anthony31f1bf72012-01-30 12:37:22 +00002908 (void) RaiseImage(image,&geometry,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00002909 break;
2910 }
anthonydcf510d2011-10-30 13:51:40 +00002911 if (LocaleCompare("random-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002912 {
anthony31f1bf72012-01-30 12:37:22 +00002913 (void) RandomThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002914 break;
2915 }
anthonydcf510d2011-10-30 13:51:40 +00002916 if (LocaleCompare("remap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002917 {
2918 Image
2919 *remap_image;
2920
anthonyfd706f92012-01-19 04:22:02 +00002921 remap_image=GetImageCache(image_info,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00002922 if (remap_image == (Image *) NULL)
2923 break;
anthony31f1bf72012-01-30 12:37:22 +00002924 (void) RemapImage(quantize_info,image,remap_image,exception);
anthony805a2d42011-09-25 08:25:12 +00002925 remap_image=DestroyImage(remap_image);
2926 break;
2927 }
anthonydcf510d2011-10-30 13:51:40 +00002928 if (LocaleCompare("repage",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002929 {
anthony31f1bf72012-01-30 12:37:22 +00002930 if (plus_alt_op == MagickFalse)
2931 (void) ResetImagePage(image,arg1);
2932 else
2933 (void) ParseAbsoluteGeometry("0x0+0+0",&image->page);
anthony805a2d42011-09-25 08:25:12 +00002934 break;
2935 }
anthonydcf510d2011-10-30 13:51:40 +00002936 if (LocaleCompare("resample",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002937 {
anthony31f1bf72012-01-30 12:37:22 +00002938 /* FUTURE: remove blur arguemnt - no longer used */
anthonyfd706f92012-01-19 04:22:02 +00002939 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002940 if ((flags & SigmaValue) == 0)
2941 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00002942 new_image=ResampleImage(image,geometry_info.rho,
2943 geometry_info.sigma,image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002944 break;
2945 }
anthonydcf510d2011-10-30 13:51:40 +00002946 if (LocaleCompare("resize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002947 {
anthonyafbaed72011-10-26 12:05:04 +00002948 /* FUTURE: remove blur argument - no longer used */
anthony31f1bf72012-01-30 12:37:22 +00002949 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2950 new_image=ResizeImage(image,geometry.width,geometry.height,
2951 image->filter,image->blur,exception);
anthony805a2d42011-09-25 08:25:12 +00002952 break;
2953 }
anthonydcf510d2011-10-30 13:51:40 +00002954 if (LocaleCompare("roll",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002955 {
anthony31f1bf72012-01-30 12:37:22 +00002956 (void) ParsePageGeometry(image,arg1,&geometry,exception);
2957 new_image=RollImage(image,geometry.x,geometry.y,exception);
anthony805a2d42011-09-25 08:25:12 +00002958 break;
2959 }
anthonydcf510d2011-10-30 13:51:40 +00002960 if (LocaleCompare("rotate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002961 {
anthonyfd706f92012-01-19 04:22:02 +00002962 if (strchr(arg1,'>') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002963 if (image->columns <= image->rows)
anthony805a2d42011-09-25 08:25:12 +00002964 break;
anthonyfd706f92012-01-19 04:22:02 +00002965 if (strchr(arg1,'<') != (char *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00002966 if (image->columns >= image->rows)
anthony805a2d42011-09-25 08:25:12 +00002967 break;
anthonyafbaed72011-10-26 12:05:04 +00002968
anthonyfd706f92012-01-19 04:22:02 +00002969 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00002970 new_image=RotateImage(image,geometry_info.rho,exception);
anthony805a2d42011-09-25 08:25:12 +00002971 break;
2972 }
2973 break;
2974 }
2975 case 's':
2976 {
anthonydcf510d2011-10-30 13:51:40 +00002977 if (LocaleCompare("sample",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002978 {
anthony31f1bf72012-01-30 12:37:22 +00002979 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2980 new_image=SampleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00002981 exception);
2982 break;
2983 }
anthonydcf510d2011-10-30 13:51:40 +00002984 if (LocaleCompare("scale",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002985 {
anthony31f1bf72012-01-30 12:37:22 +00002986 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
2987 new_image=ScaleImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00002988 exception);
2989 break;
2990 }
anthonydcf510d2011-10-30 13:51:40 +00002991 if (LocaleCompare("selective-blur",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00002992 {
anthonyfd706f92012-01-19 04:22:02 +00002993 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00002994 if ((flags & PercentValue) != 0)
2995 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
anthony31f1bf72012-01-30 12:37:22 +00002996 new_image=SelectiveBlurImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00002997 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
2998 break;
2999 }
anthonydcf510d2011-10-30 13:51:40 +00003000 if (LocaleCompare("separate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003001 {
anthony31f1bf72012-01-30 12:37:22 +00003002 /* WARNING: This can generate multiple images! */
anthony43f425d2012-02-26 12:58:58 +00003003 /* FUTURE - this may be replaced by a "-channel" method */
anthony31f1bf72012-01-30 12:37:22 +00003004 new_image=SeparateImages(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003005 break;
3006 }
anthonydcf510d2011-10-30 13:51:40 +00003007 if (LocaleCompare("sepia-tone",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003008 {
3009 double
3010 threshold;
3011
anthonyfd706f92012-01-19 04:22:02 +00003012 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00003013 new_image=SepiaToneImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00003014 break;
3015 }
anthonydcf510d2011-10-30 13:51:40 +00003016 if (LocaleCompare("segment",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003017 {
anthonyfd706f92012-01-19 04:22:02 +00003018 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003019 if ((flags & SigmaValue) == 0)
3020 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003021 (void) SegmentImage(image,image->colorspace,
anthony805a2d42011-09-25 08:25:12 +00003022 image_info->verbose,geometry_info.rho,geometry_info.sigma,
3023 exception);
3024 break;
3025 }
anthonydcf510d2011-10-30 13:51:40 +00003026 if (LocaleCompare("set",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003027 {
3028 char
3029 *value;
3030
anthony31f1bf72012-01-30 12:37:22 +00003031 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003032 {
anthonyfd706f92012-01-19 04:22:02 +00003033 if (LocaleNCompare(arg1,"registry:",9) == 0)
3034 (void) DeleteImageRegistry(arg1+9);
anthony805a2d42011-09-25 08:25:12 +00003035 else
anthony31f1bf72012-01-30 12:37:22 +00003036 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003037 {
anthonyfd706f92012-01-19 04:22:02 +00003038 (void) DeleteImageOption(image_info,arg1+7);
anthony31f1bf72012-01-30 12:37:22 +00003039 (void) DeleteImageArtifact(image,arg1+7);
anthony805a2d42011-09-25 08:25:12 +00003040 }
3041 else
anthony31f1bf72012-01-30 12:37:22 +00003042 (void) DeleteImageProperty(image,arg1);
anthony805a2d42011-09-25 08:25:12 +00003043 break;
3044 }
anthony31f1bf72012-01-30 12:37:22 +00003045 value=InterpretImageProperties(image_info,image,arg2,
anthony805a2d42011-09-25 08:25:12 +00003046 exception);
3047 if (value == (char *) NULL)
3048 break;
anthonyfd706f92012-01-19 04:22:02 +00003049 if (LocaleNCompare(arg1,"registry:",9) == 0)
3050 (void) SetImageRegistry(StringRegistryType,arg1+9,value,
anthony805a2d42011-09-25 08:25:12 +00003051 exception);
3052 else
anthonyfd706f92012-01-19 04:22:02 +00003053 if (LocaleNCompare(arg1,"option:",7) == 0)
anthony805a2d42011-09-25 08:25:12 +00003054 {
anthonyfd706f92012-01-19 04:22:02 +00003055 (void) SetImageOption(image_info,arg1+7,value);
anthony31f1bf72012-01-30 12:37:22 +00003056 (void) SetImageArtifact(image,arg1+7,value);
anthony805a2d42011-09-25 08:25:12 +00003057 }
3058 else
anthony31f1bf72012-01-30 12:37:22 +00003059 (void) SetImageProperty(image,arg1,value,exception);
anthony805a2d42011-09-25 08:25:12 +00003060 value=DestroyString(value);
3061 break;
3062 }
anthonydcf510d2011-10-30 13:51:40 +00003063 if (LocaleCompare("shade",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003064 {
anthonyfd706f92012-01-19 04:22:02 +00003065 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003066 if ((flags & SigmaValue) == 0)
3067 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003068 new_image=ShadeImage(image,normal_op,geometry_info.rho,
3069 geometry_info.sigma,exception);
anthony805a2d42011-09-25 08:25:12 +00003070 break;
3071 }
anthonydcf510d2011-10-30 13:51:40 +00003072 if (LocaleCompare("shadow",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003073 {
anthonyfd706f92012-01-19 04:22:02 +00003074 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003075 if ((flags & SigmaValue) == 0)
3076 geometry_info.sigma=1.0;
3077 if ((flags & XiValue) == 0)
3078 geometry_info.xi=4.0;
3079 if ((flags & PsiValue) == 0)
3080 geometry_info.psi=4.0;
anthony31f1bf72012-01-30 12:37:22 +00003081 new_image=ShadowImage(image,geometry_info.rho,
3082 geometry_info.sigma,image->bias,(ssize_t)
cristyeb6e6582011-12-09 09:14:23 +00003083 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
3084 exception);
anthony805a2d42011-09-25 08:25:12 +00003085 break;
3086 }
anthonydcf510d2011-10-30 13:51:40 +00003087 if (LocaleCompare("sharpen",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003088 {
anthonyfd706f92012-01-19 04:22:02 +00003089 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003090 if ((flags & SigmaValue) == 0)
3091 geometry_info.sigma=1.0;
3092 if ((flags & XiValue) == 0)
3093 geometry_info.xi=0.0;
anthony31f1bf72012-01-30 12:37:22 +00003094 new_image=SharpenImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003095 geometry_info.sigma,geometry_info.xi,exception);
3096 break;
3097 }
anthonydcf510d2011-10-30 13:51:40 +00003098 if (LocaleCompare("shave",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003099 {
anthony31f1bf72012-01-30 12:37:22 +00003100 flags=ParsePageGeometry(image,arg1,&geometry,exception);
3101 new_image=ShaveImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003102 break;
3103 }
anthonydcf510d2011-10-30 13:51:40 +00003104 if (LocaleCompare("shear",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003105 {
anthonyfd706f92012-01-19 04:22:02 +00003106 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003107 if ((flags & SigmaValue) == 0)
3108 geometry_info.sigma=geometry_info.rho;
anthony31f1bf72012-01-30 12:37:22 +00003109 new_image=ShearImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003110 geometry_info.sigma,exception);
3111 break;
3112 }
anthonydcf510d2011-10-30 13:51:40 +00003113 if (LocaleCompare("sigmoidal-contrast",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003114 {
anthonyfd706f92012-01-19 04:22:02 +00003115 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003116 if ((flags & SigmaValue) == 0)
3117 geometry_info.sigma=(double) QuantumRange/2.0;
3118 if ((flags & PercentValue) != 0)
3119 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3120 100.0;
anthony31f1bf72012-01-30 12:37:22 +00003121 (void) SigmoidalContrastImage(image,normal_op,geometry_info.rho,
3122 geometry_info.sigma,
anthony805a2d42011-09-25 08:25:12 +00003123 exception);
3124 break;
3125 }
anthonydcf510d2011-10-30 13:51:40 +00003126 if (LocaleCompare("sketch",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003127 {
anthonyfd706f92012-01-19 04:22:02 +00003128 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003129 if ((flags & SigmaValue) == 0)
3130 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003131 new_image=SketchImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003132 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3133 break;
3134 }
anthonydcf510d2011-10-30 13:51:40 +00003135 if (LocaleCompare("solarize",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003136 {
anthony31f1bf72012-01-30 12:37:22 +00003137 (void) SolarizeImage(image,StringToDoubleInterval(arg1,(double)
3138 QuantumRange+1.0),exception);
anthony805a2d42011-09-25 08:25:12 +00003139 break;
3140 }
anthonydcf510d2011-10-30 13:51:40 +00003141 if (LocaleCompare("sparse-color",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003142 {
3143 SparseColorMethod
3144 method;
3145
3146 char
3147 *arguments;
3148
anthony805a2d42011-09-25 08:25:12 +00003149 method=(SparseColorMethod) ParseCommandOption(
anthonyfd706f92012-01-19 04:22:02 +00003150 MagickSparseColorOptions,MagickFalse,arg1);
anthony31f1bf72012-01-30 12:37:22 +00003151 arguments=InterpretImageProperties(image_info,image,arg2,exception);
anthony805a2d42011-09-25 08:25:12 +00003152 if (arguments == (char *) NULL)
3153 break;
anthony31f1bf72012-01-30 12:37:22 +00003154 new_image=SparseColorOption(image,method,arguments,exception);
anthony805a2d42011-09-25 08:25:12 +00003155 arguments=DestroyString(arguments);
3156 break;
3157 }
anthonydcf510d2011-10-30 13:51:40 +00003158 if (LocaleCompare("splice",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003159 {
anthony31f1bf72012-01-30 12:37:22 +00003160 (void) ParseGravityGeometry(image,arg1,&geometry,exception);
3161 new_image=SpliceImage(image,&geometry,exception);
anthony805a2d42011-09-25 08:25:12 +00003162 break;
3163 }
anthonydcf510d2011-10-30 13:51:40 +00003164 if (LocaleCompare("spread",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003165 {
anthonyfd706f92012-01-19 04:22:02 +00003166 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003167 new_image=SpreadImage(image,geometry_info.rho,image->interpolate,
3168 exception);
anthony805a2d42011-09-25 08:25:12 +00003169 break;
3170 }
anthonydcf510d2011-10-30 13:51:40 +00003171 if (LocaleCompare("statistic",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003172 {
3173 StatisticType
3174 type;
3175
anthony805a2d42011-09-25 08:25:12 +00003176 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
anthonyfd706f92012-01-19 04:22:02 +00003177 MagickFalse,arg1);
3178 (void) ParseGeometry(arg2,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003179 new_image=StatisticImage(image,type,(size_t) geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003180 (size_t) geometry_info.sigma,exception);
3181 break;
3182 }
anthonydcf510d2011-10-30 13:51:40 +00003183 if (LocaleCompare("strip",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003184 {
anthony31f1bf72012-01-30 12:37:22 +00003185 (void) StripImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003186 break;
3187 }
anthonydcf510d2011-10-30 13:51:40 +00003188 if (LocaleCompare("swirl",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003189 {
anthonyfd706f92012-01-19 04:22:02 +00003190 (void) ParseGeometry(arg1,&geometry_info);
anthony31f1bf72012-01-30 12:37:22 +00003191 new_image=SwirlImage(image,geometry_info.rho,
3192 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003193 break;
3194 }
3195 break;
3196 }
3197 case 't':
3198 {
anthonydcf510d2011-10-30 13:51:40 +00003199 if (LocaleCompare("threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003200 {
3201 double
3202 threshold;
3203
anthony31f1bf72012-01-30 12:37:22 +00003204 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003205 threshold=(double) QuantumRange/2;
3206 else
anthonyfd706f92012-01-19 04:22:02 +00003207 threshold=StringToDoubleInterval(arg1,(double) QuantumRange+1.0);
anthony31f1bf72012-01-30 12:37:22 +00003208 (void) BilevelImage(image,threshold,exception);
anthony805a2d42011-09-25 08:25:12 +00003209 break;
3210 }
anthonydcf510d2011-10-30 13:51:40 +00003211 if (LocaleCompare("thumbnail",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003212 {
anthony31f1bf72012-01-30 12:37:22 +00003213 (void) ParseRegionGeometry(image,arg1,&geometry,exception);
3214 new_image=ThumbnailImage(image,geometry.width,geometry.height,
anthony805a2d42011-09-25 08:25:12 +00003215 exception);
3216 break;
3217 }
anthonydcf510d2011-10-30 13:51:40 +00003218 if (LocaleCompare("tint",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003219 {
anthony31f1bf72012-01-30 12:37:22 +00003220 new_image=TintImage(image,arg1,&draw_info->fill,exception);
anthony805a2d42011-09-25 08:25:12 +00003221 break;
3222 }
anthonydcf510d2011-10-30 13:51:40 +00003223 if (LocaleCompare("transform",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003224 {
anthonyfd706f92012-01-19 04:22:02 +00003225 /* DEPRECIATED */
anthony31f1bf72012-01-30 12:37:22 +00003226 new_image=AffineTransformImage(image,&draw_info->affine,
anthony805a2d42011-09-25 08:25:12 +00003227 exception);
3228 break;
3229 }
anthonydcf510d2011-10-30 13:51:40 +00003230 if (LocaleCompare("transparent",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003231 {
3232 PixelInfo
3233 target;
3234
anthony31f1bf72012-01-30 12:37:22 +00003235 (void) QueryColorCompliance(arg1,AllCompliance,&target,exception);
3236 (void) TransparentPaintImage(image,&target,(Quantum)
3237 TransparentAlpha,plus_alt_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003238 break;
3239 }
anthonydcf510d2011-10-30 13:51:40 +00003240 if (LocaleCompare("transpose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003241 {
anthony31f1bf72012-01-30 12:37:22 +00003242 new_image=TransposeImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003243 break;
3244 }
anthonydcf510d2011-10-30 13:51:40 +00003245 if (LocaleCompare("transverse",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003246 {
anthony31f1bf72012-01-30 12:37:22 +00003247 new_image=TransverseImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003248 break;
3249 }
anthonydcf510d2011-10-30 13:51:40 +00003250 if (LocaleCompare("trim",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003251 {
anthony31f1bf72012-01-30 12:37:22 +00003252 new_image=TrimImage(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003253 break;
3254 }
anthonydcf510d2011-10-30 13:51:40 +00003255 if (LocaleCompare("type",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003256 {
anthonyab3a50c2011-10-27 11:48:57 +00003257 /* Note that "type" setting should have already been defined */
anthony31f1bf72012-01-30 12:37:22 +00003258 (void) SetImageType(image,image_info->type,exception);
anthony805a2d42011-09-25 08:25:12 +00003259 break;
3260 }
3261 break;
3262 }
3263 case 'u':
3264 {
anthonydcf510d2011-10-30 13:51:40 +00003265 if (LocaleCompare("unique",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003266 {
anthony31f1bf72012-01-30 12:37:22 +00003267 /* FUTURE: move to SyncImageSettings() and AcqireImage()??? */
3268 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00003269 {
anthony31f1bf72012-01-30 12:37:22 +00003270 (void) DeleteImageArtifact(image,"identify:unique-colors");
anthony805a2d42011-09-25 08:25:12 +00003271 break;
3272 }
anthony31f1bf72012-01-30 12:37:22 +00003273 (void) SetImageArtifact(image,"identify:unique-colors","true");
3274 (void) SetImageArtifact(image,"verbose","true");
anthony805a2d42011-09-25 08:25:12 +00003275 break;
3276 }
anthonydcf510d2011-10-30 13:51:40 +00003277 if (LocaleCompare("unique-colors",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003278 {
anthony31f1bf72012-01-30 12:37:22 +00003279 new_image=UniqueImageColors(image,exception);
anthony805a2d42011-09-25 08:25:12 +00003280 break;
3281 }
anthonydcf510d2011-10-30 13:51:40 +00003282 if (LocaleCompare("unsharp",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003283 {
anthonyfd706f92012-01-19 04:22:02 +00003284 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003285 if ((flags & SigmaValue) == 0)
3286 geometry_info.sigma=1.0;
3287 if ((flags & XiValue) == 0)
3288 geometry_info.xi=1.0;
3289 if ((flags & PsiValue) == 0)
3290 geometry_info.psi=0.05;
anthony31f1bf72012-01-30 12:37:22 +00003291 new_image=UnsharpMaskImage(image,geometry_info.rho,
anthony805a2d42011-09-25 08:25:12 +00003292 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3293 break;
3294 }
3295 break;
3296 }
3297 case 'v':
3298 {
anthonydcf510d2011-10-30 13:51:40 +00003299 if (LocaleCompare("verbose",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003300 {
anthony31f1bf72012-01-30 12:37:22 +00003301 /* FUTURE: move to SyncImageSettings() and AcqireImage()???
3302 three places! ImageArtifact ImageOption image_info->verbose
3303 Some how new images also get this artifact -- how???
3304 */
3305 (void) SetImageArtifact(image,option,
3306 (plus_alt_op != MagickFalse) ? "false" : "true" );
anthony805a2d42011-09-25 08:25:12 +00003307 break;
3308 }
anthonydcf510d2011-10-30 13:51:40 +00003309 if (LocaleCompare("vignette",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003310 {
anthonyfd706f92012-01-19 04:22:02 +00003311 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003312 if ((flags & SigmaValue) == 0)
3313 geometry_info.sigma=1.0;
3314 if ((flags & XiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003315 geometry_info.xi=0.1*image->columns;
anthony805a2d42011-09-25 08:25:12 +00003316 if ((flags & PsiValue) == 0)
anthony31f1bf72012-01-30 12:37:22 +00003317 geometry_info.psi=0.1*image->rows;
3318 new_image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
3319 image->bias,(ssize_t) ceil(geometry_info.xi-0.5),
3320 (ssize_t) ceil(geometry_info.psi-0.5),exception);
anthony805a2d42011-09-25 08:25:12 +00003321 break;
3322 }
anthony805a2d42011-09-25 08:25:12 +00003323 break;
3324 }
3325 case 'w':
3326 {
anthonydcf510d2011-10-30 13:51:40 +00003327 if (LocaleCompare("wave",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003328 {
anthonyfd706f92012-01-19 04:22:02 +00003329 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00003330 if ((flags & SigmaValue) == 0)
3331 geometry_info.sigma=1.0;
anthony31f1bf72012-01-30 12:37:22 +00003332 new_image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
3333 image->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003334 break;
3335 }
anthonydcf510d2011-10-30 13:51:40 +00003336 if (LocaleCompare("white-threshold",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003337 {
anthony31f1bf72012-01-30 12:37:22 +00003338 (void) WhiteThresholdImage(image,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003339 break;
3340 }
3341 break;
3342 }
3343 default:
3344 break;
3345 }
3346 /*
3347 Replace current image with any image that was generated
anthony31f1bf72012-01-30 12:37:22 +00003348 and set image point to last image (so image->next is correct)
anthony805a2d42011-09-25 08:25:12 +00003349 */
3350 if (new_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003351 ReplaceImageInListReturnLast(&image,new_image);
anthony805a2d42011-09-25 08:25:12 +00003352
anthony31f1bf72012-01-30 12:37:22 +00003353 return;
anthonyfd706f92012-01-19 04:22:02 +00003354#undef image_info
3355#undef draw_info
3356#undef quantize_info
anthony31f1bf72012-01-30 12:37:22 +00003357#undef image
anthonyfd706f92012-01-19 04:22:02 +00003358#undef exception
anthony31f1bf72012-01-30 12:37:22 +00003359#undef normal_op
3360}
anthonyfd706f92012-01-19 04:22:02 +00003361
anthony43f425d2012-02-26 12:58:58 +00003362WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
anthony31f1bf72012-01-30 12:37:22 +00003363 const MagickBooleanType plus_alt_op, const char *option,
3364 const char *arg1, const char *arg2)
3365{
3366 size_t
anthony43f425d2012-02-26 12:58:58 +00003367 n,
anthony31f1bf72012-01-30 12:37:22 +00003368 i;
3369
anthony43f425d2012-02-26 12:58:58 +00003370 assert(cli_wand != (MagickCLI *) NULL);
3371 assert(cli_wand->signature == WandSignature);
3372 assert(cli_wand->wand.signature == WandSignature);
3373 assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
3374 if (cli_wand->wand.debug != MagickFalse)
3375 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003376
3377 i=0;
anthony43f425d2012-02-26 12:58:58 +00003378 n=GetImageListLength(cli_wand->wand.images);
3379 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
3380 while (1)
anthony31f1bf72012-01-30 12:37:22 +00003381 {
anthony31f1bf72012-01-30 12:37:22 +00003382 i++;
anthony43f425d2012-02-26 12:58:58 +00003383 CLISimpleOperatorImage(cli_wand, plus_alt_op, option, arg1, arg2);
3384 if ( cli_wand->wand.images->next == (Image *) NULL )
3385 break;
3386 cli_wand->wand.images=cli_wand->wand.images->next;
anthony31f1bf72012-01-30 12:37:22 +00003387 }
anthony43f425d2012-02-26 12:58:58 +00003388 assert( i == n );
3389 cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
anthony31f1bf72012-01-30 12:37:22 +00003390 return;
anthony805a2d42011-09-25 08:25:12 +00003391}
3392
3393/*
3394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3395% %
3396% %
3397% %
anthony43f425d2012-02-26 12:58:58 +00003398+ 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 +00003399% %
3400% %
3401% %
3402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3403%
anthony43f425d2012-02-26 12:58:58 +00003404% CLIListOperatorImages() applies a single operation that is apply to the
anthony31f1bf72012-01-30 12:37:22 +00003405% entire image list as a whole. The result is often a complete replacment
3406% of the image list with a completely new list, or just a single image.
anthony805a2d42011-09-25 08:25:12 +00003407%
3408% The format of the MogrifyImage method is:
3409%
anthony43f425d2012-02-26 12:58:58 +00003410% void CLIListOperatorImages(MagickCLI *cli_wand,
anthony36a8c2c2012-02-10 00:08:44 +00003411% const MagickBooleanType plus_alt_op,const char *option,
anthony31f1bf72012-01-30 12:37:22 +00003412% const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003413%
3414% A description of each parameter follows:
3415%
anthony43f425d2012-02-26 12:58:58 +00003416% o cli_wand: structure holding settings to be applied
anthony805a2d42011-09-25 08:25:12 +00003417%
anthony8b10b462012-02-08 12:32:44 +00003418% o plus_alt_op: request the 'plus' or alturnative form of the operation
3419%
anthony36a8c2c2012-02-10 00:08:44 +00003420% o option: The option string for the operation
3421%
anthony31f1bf72012-01-30 12:37:22 +00003422% o arg1, arg2: optional argument strings to the operation
anthony805a2d42011-09-25 08:25:12 +00003423%
anthony8b10b462012-02-08 12:32:44 +00003424% NOTE: only "limit" currently uses two arguments.
3425%
3426% Example usage...
3427%
anthony43f425d2012-02-26 12:58:58 +00003428% CLIListOperatorImages(cli_wand,MagickFalse,"duplicate", "3", NULL);
3429% CLIListOperatorImages(cli_wand,MagickTrue, "append", NULL, NULL);
3430% if ( cli_wand->wand.exception->severity != UndefinedException ) {
anthony8b10b462012-02-08 12:32:44 +00003431% CatchException(exception);
3432% exit(1);
3433% }
3434%
3435% Or for handling command line arguments EG: +/-option ["arg"]
3436%
anthony43f425d2012-02-26 12:58:58 +00003437% cli_wand
anthony8b10b462012-02-08 12:32:44 +00003438% argc,argv
3439% i=index in argv
3440%
3441% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
3442% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
anthonye8f56492012-02-12 12:39:02 +00003443% if ( (flags & ListOperatorOptionFlag) != 0 )
anthony43f425d2012-02-26 12:58:58 +00003444% CLIListOperatorImages(cli_wand,
anthony36a8c2c2012-02-10 00:08:44 +00003445% ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
anthony8b10b462012-02-08 12:32:44 +00003446% count>=1 ? argv[i+1] : (char *)NULL,
3447% count>=2 ? argv[i+2] : (char *)NULL );
3448% i += count+1;
3449%
anthony805a2d42011-09-25 08:25:12 +00003450*/
anthony43f425d2012-02-26 12:58:58 +00003451WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
anthony36a8c2c2012-02-10 00:08:44 +00003452 const MagickBooleanType plus_alt_op,const char *option,
3453 const char *arg1, const char *arg2)
anthony805a2d42011-09-25 08:25:12 +00003454{
anthony31f1bf72012-01-30 12:37:22 +00003455 Image
3456 *new_images;
anthony805a2d42011-09-25 08:25:12 +00003457
anthony43f425d2012-02-26 12:58:58 +00003458#define image_info (cli_wand->wand.image_info)
3459#define images (cli_wand->wand.images)
3460#define exception (cli_wand->wand.exception)
3461#define draw_info (cli_wand->draw_info)
3462#define quantize_info (cli_wand->quantize_info)
anthony31f1bf72012-01-30 12:37:22 +00003463#define normal_op (plus_alt_op?MagickFalse:MagickTrue)
anthony805a2d42011-09-25 08:25:12 +00003464
anthony43f425d2012-02-26 12:58:58 +00003465 assert(cli_wand != (MagickCLI *) NULL);
3466 assert(cli_wand->signature == WandSignature);
3467 assert(cli_wand->wand.signature == WandSignature);
3468 assert(images != (Image *) NULL); /* images must be present */
3469 if (cli_wand->wand.debug != MagickFalse)
3470 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
anthony31f1bf72012-01-30 12:37:22 +00003471
3472 (void) SyncImagesSettings(image_info,images,exception);
3473
3474 new_images=NewImageList();
3475
3476 switch (*option)
anthony805a2d42011-09-25 08:25:12 +00003477 {
3478 case 'a':
3479 {
anthony31f1bf72012-01-30 12:37:22 +00003480 if (LocaleCompare("append",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003481 {
anthony31f1bf72012-01-30 12:37:22 +00003482 new_images=AppendImages(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003483 break;
3484 }
anthony31f1bf72012-01-30 12:37:22 +00003485 if (LocaleCompare("average",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003486 {
anthony31f1bf72012-01-30 12:37:22 +00003487 /* DEPRECIATED - use -evaluate-sequence Mean */
anthony43f425d2012-02-26 12:58:58 +00003488 CLIListOperatorImages(cli_wand,plus_alt_op,"evaluate-sequence","Mean",
anthony31f1bf72012-01-30 12:37:22 +00003489 NULL);
anthony805a2d42011-09-25 08:25:12 +00003490 break;
3491 }
3492 break;
3493 }
3494 case 'c':
3495 {
cristy87c02f42012-02-24 00:19:10 +00003496 if (LocaleCompare("channel-inject",option) == 0)
3497 {
3498 puts("stand by...");
3499 break;
3500 }
anthony31f1bf72012-01-30 12:37:22 +00003501 if (LocaleCompare("clut",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003502 {
anthony805a2d42011-09-25 08:25:12 +00003503 Image
anthony31f1bf72012-01-30 12:37:22 +00003504 *clut_image;
anthony805a2d42011-09-25 08:25:12 +00003505
cristy87c02f42012-02-24 00:19:10 +00003506 /* FUTURE - make this a compose option (and thus layers compose )
3507 or perhaps compose last image over all other images.
3508 */
anthony31f1bf72012-01-30 12:37:22 +00003509 new_images=RemoveFirstImageFromList(&images);
3510 clut_image=RemoveLastImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003511 /* FUTURE - produce Exception, rather than silent fail */
anthony805a2d42011-09-25 08:25:12 +00003512 if (clut_image == (Image *) NULL)
cristy87c02f42012-02-24 00:19:10 +00003513 break;
anthony31f1bf72012-01-30 12:37:22 +00003514 (void) ClutImage(new_images,clut_image,images->interpolate,exception);
anthony805a2d42011-09-25 08:25:12 +00003515 clut_image=DestroyImage(clut_image);
anthony805a2d42011-09-25 08:25:12 +00003516 break;
3517 }
anthony31f1bf72012-01-30 12:37:22 +00003518 if (LocaleCompare("coalesce",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003519 {
anthony31f1bf72012-01-30 12:37:22 +00003520 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003521 break;
3522 }
anthony31f1bf72012-01-30 12:37:22 +00003523 if (LocaleCompare("combine",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003524 {
anthony43f425d2012-02-26 12:58:58 +00003525 /* FUTURE - this may be replaced by a 'channel' method */
anthony31f1bf72012-01-30 12:37:22 +00003526 new_images=CombineImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003527 break;
3528 }
anthony31f1bf72012-01-30 12:37:22 +00003529 if (LocaleCompare("composite",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003530 {
3531 Image
3532 *mask_image,
anthony31f1bf72012-01-30 12:37:22 +00003533 *source_image;
anthony805a2d42011-09-25 08:25:12 +00003534
3535 RectangleInfo
3536 geometry;
3537
anthony31f1bf72012-01-30 12:37:22 +00003538 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003539 compose;
3540
3541 const char*
3542 value;
3543
3544 value=GetImageOption(image_info,"compose");
3545 if (value != (const char *) NULL)
3546 compose=(CompositeOperator) ParseCommandOption(
3547 MagickComposeOptions,MagickFalse,value);
3548 else
anthony31f1bf72012-01-30 12:37:22 +00003549 compose=OverCompositeOp; /* use Over not source_image->compose */
anthony5f867ae2011-10-09 10:28:34 +00003550
anthony31f1bf72012-01-30 12:37:22 +00003551 new_images=RemoveFirstImageFromList(&images);
3552 source_image=RemoveFirstImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003553 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003554 if (source_image == (Image *) NULL)
3555 break;
anthonye8f56492012-02-12 12:39:02 +00003556
anthony31f1bf72012-01-30 12:37:22 +00003557 /* FUTURE - this should not be here! - should be part of -geometry */
3558 (void) TransformImage(&source_image,(char *) NULL,
3559 source_image->geometry,exception);
anthony5f867ae2011-10-09 10:28:34 +00003560
anthony31f1bf72012-01-30 12:37:22 +00003561 SetGeometry(source_image,&geometry);
3562 (void) ParseAbsoluteGeometry(source_image->geometry,&geometry);
3563 GravityAdjustGeometry(new_images->columns,new_images->rows,
3564 new_images->gravity, &geometry);
anthony5f867ae2011-10-09 10:28:34 +00003565
anthony31f1bf72012-01-30 12:37:22 +00003566 mask_image=RemoveFirstImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003567 if (mask_image != (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003568 { /* handle a third write mask image */
anthony5f867ae2011-10-09 10:28:34 +00003569 if ((compose == DisplaceCompositeOp) ||
3570 (compose == DistortCompositeOp))
anthony31f1bf72012-01-30 12:37:22 +00003571 { /* Merge Y displacement into X displace/distort map. */
3572 (void) CompositeImage(source_image,CopyGreenCompositeOp,
anthony6613bf32011-10-15 07:24:44 +00003573 mask_image,0,0,exception);
anthony805a2d42011-09-25 08:25:12 +00003574 mask_image=DestroyImage(mask_image);
3575 }
3576 else
3577 {
3578 /*
3579 Set a blending mask for the composition.
anthony805a2d42011-09-25 08:25:12 +00003580 */
cristy1539afd2012-01-30 01:32:59 +00003581 (void) NegateImage(mask_image,MagickFalse,exception);
anthony31f1bf72012-01-30 12:37:22 +00003582 (void) SetImageMask(new_images,mask_image,exception);
cristy1539afd2012-01-30 01:32:59 +00003583 mask_image=DestroyImage(mask_image);
anthony805a2d42011-09-25 08:25:12 +00003584 }
3585 }
anthony31f1bf72012-01-30 12:37:22 +00003586 (void) CompositeImage(new_images,compose,source_image,geometry.x,
3587 geometry.y,exception);
3588 (void) SetImageMask(new_images,(Image *) NULL,exception);
3589 source_image=DestroyImage(source_image);
anthony805a2d42011-09-25 08:25:12 +00003590 break;
3591 }
3592 break;
3593 }
3594 case 'd':
3595 {
anthony31f1bf72012-01-30 12:37:22 +00003596 if (LocaleCompare("deconstruct",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003597 {
anthony31f1bf72012-01-30 12:37:22 +00003598 /* DEPRECIATED - use -layers CompareAny */
anthony43f425d2012-02-26 12:58:58 +00003599 CLIListOperatorImages(cli_wand,plus_alt_op,"layer","CompareAny",NULL);
anthony805a2d42011-09-25 08:25:12 +00003600 break;
3601 }
anthony31f1bf72012-01-30 12:37:22 +00003602 if (LocaleCompare("delete",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003603 {
anthony31f1bf72012-01-30 12:37:22 +00003604 if (plus_alt_op != MagickFalse)
3605 DeleteImages(&images,"-1",exception);
anthony805a2d42011-09-25 08:25:12 +00003606 else
anthony31f1bf72012-01-30 12:37:22 +00003607 DeleteImages(&images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003608 break;
3609 }
anthony31f1bf72012-01-30 12:37:22 +00003610 if (LocaleCompare("duplicate",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003611 {
anthony31f1bf72012-01-30 12:37:22 +00003612 if (plus_alt_op != MagickFalse)
anthony36a8c2c2012-02-10 00:08:44 +00003613 new_images=DuplicateImages(images,1,"-1",exception);
anthony805a2d42011-09-25 08:25:12 +00003614 else
3615 {
3616 const char
3617 *p;
3618
3619 size_t
3620 number_duplicates;
3621
anthony31f1bf72012-01-30 12:37:22 +00003622 number_duplicates=(size_t) StringToLong(arg1);
3623 p=strchr(arg1,',');
anthony805a2d42011-09-25 08:25:12 +00003624 if (p == (const char *) NULL)
anthony36a8c2c2012-02-10 00:08:44 +00003625 new_images=DuplicateImages(images,number_duplicates,
anthony805a2d42011-09-25 08:25:12 +00003626 "-1",exception);
3627 else
anthony36a8c2c2012-02-10 00:08:44 +00003628 new_images=DuplicateImages(images,number_duplicates,p,
anthony805a2d42011-09-25 08:25:12 +00003629 exception);
3630 }
anthony36a8c2c2012-02-10 00:08:44 +00003631 AppendImageToList(&images, new_images);
3632 new_images=(Image *)NULL;
anthony805a2d42011-09-25 08:25:12 +00003633 break;
3634 }
3635 break;
3636 }
3637 case 'e':
3638 {
anthony31f1bf72012-01-30 12:37:22 +00003639 if (LocaleCompare("evaluate-sequence",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003640 {
anthony805a2d42011-09-25 08:25:12 +00003641 MagickEvaluateOperator
anthony31f1bf72012-01-30 12:37:22 +00003642 method;
anthony805a2d42011-09-25 08:25:12 +00003643
anthony31f1bf72012-01-30 12:37:22 +00003644 method=(MagickEvaluateOperator) ParseCommandOption(
3645 MagickEvaluateOptions,MagickFalse,arg1);
3646 new_images=EvaluateImages(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003647 break;
3648 }
3649 break;
3650 }
3651 case 'f':
3652 {
anthony31f1bf72012-01-30 12:37:22 +00003653 if (LocaleCompare("fft",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003654 {
anthony31f1bf72012-01-30 12:37:22 +00003655 new_images=ForwardFourierTransformImage(images,normal_op,exception);
anthony805a2d42011-09-25 08:25:12 +00003656 break;
3657 }
anthony31f1bf72012-01-30 12:37:22 +00003658 if (LocaleCompare("flatten",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003659 {
anthony31f1bf72012-01-30 12:37:22 +00003660 /* DEPRECIATED use -layers mosaic instead */
anthony43f425d2012-02-26 12:58:58 +00003661 CLIListOperatorImages(cli_wand,plus_alt_op,"layer",option,NULL);
anthony805a2d42011-09-25 08:25:12 +00003662 break;
3663 }
anthony31f1bf72012-01-30 12:37:22 +00003664 if (LocaleCompare("fx",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003665 {
anthony31f1bf72012-01-30 12:37:22 +00003666 new_images=FxImage(images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00003667 break;
3668 }
3669 break;
3670 }
3671 case 'h':
3672 {
anthony31f1bf72012-01-30 12:37:22 +00003673 if (LocaleCompare("hald-clut",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003674 {
anthony31f1bf72012-01-30 12:37:22 +00003675 /* FUTURE - make this a compose option (and thus layers compose )
3676 or perhaps compose last image over all other images.
3677 */
anthony805a2d42011-09-25 08:25:12 +00003678 Image
anthony31f1bf72012-01-30 12:37:22 +00003679 *hald_image;
anthony805a2d42011-09-25 08:25:12 +00003680
anthony31f1bf72012-01-30 12:37:22 +00003681 new_images=RemoveFirstImageFromList(&images);
3682 hald_image=RemoveLastImageFromList(&images);
anthony805a2d42011-09-25 08:25:12 +00003683 if (hald_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003684 break;
3685 (void) HaldClutImage(new_images,hald_image,exception);
anthony805a2d42011-09-25 08:25:12 +00003686 hald_image=DestroyImage(hald_image);
anthony805a2d42011-09-25 08:25:12 +00003687 break;
3688 }
3689 break;
3690 }
3691 case 'i':
3692 {
anthony31f1bf72012-01-30 12:37:22 +00003693 if (LocaleCompare("ift",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003694 {
3695 Image
anthony805a2d42011-09-25 08:25:12 +00003696 *magnitude_image,
3697 *phase_image;
3698
anthony31f1bf72012-01-30 12:37:22 +00003699 magnitude_image=RemoveFirstImageFromList(&images);
3700 phase_image=RemoveFirstImageFromList(&images);
anthonye8f56492012-02-12 12:39:02 +00003701 /* FUTURE - produce Exception, rather than silent fail */
anthony31f1bf72012-01-30 12:37:22 +00003702 if (phase_image == (Image *) NULL)
3703 break;
3704 new_images=InverseFourierTransformImage(magnitude_image,phase_image,
3705 normal_op,exception);
3706 magnitude_image=DestroyImage(magnitude_image);
3707 phase_image=DestroyImage(phase_image);
anthony805a2d42011-09-25 08:25:12 +00003708 break;
3709 }
anthony31f1bf72012-01-30 12:37:22 +00003710 if (LocaleCompare("insert",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003711 {
3712 Image
anthony31f1bf72012-01-30 12:37:22 +00003713 *insert_image,
3714 *index_image;
3715
3716 ssize_t
3717 index;
anthony805a2d42011-09-25 08:25:12 +00003718
3719 index=0;
anthony31f1bf72012-01-30 12:37:22 +00003720 insert_image=RemoveLastImageFromList(&images);
3721 if (plus_alt_op == MagickFalse)
3722 index=(ssize_t) StringToLong(arg1);
anthony43f425d2012-02-26 12:58:58 +00003723 index_image=insert_image;
anthony805a2d42011-09-25 08:25:12 +00003724 if (index == 0)
anthony31f1bf72012-01-30 12:37:22 +00003725 PrependImageToList(&images,insert_image);
anthony43f425d2012-02-26 12:58:58 +00003726 else if (index == (ssize_t) GetImageListLength(images))
3727 AppendImageToList(&images,insert_image);
anthony805a2d42011-09-25 08:25:12 +00003728 else
anthony43f425d2012-02-26 12:58:58 +00003729 {
3730 index_image=GetImageFromList(images,index-1);
3731 if (index_image == (Image *) NULL)
3732 {
3733 (void) ThrowMagickException(exception,GetMagickModule(),
3734 OptionError,"NoSuchImage","'%s'",arg1);
3735 break;
3736 }
3737 InsertImageInList(&index_image,insert_image);
3738 }
anthony31f1bf72012-01-30 12:37:22 +00003739 images=GetFirstImageInList(index_image);
anthony805a2d42011-09-25 08:25:12 +00003740 break;
3741 }
anthony805a2d42011-09-25 08:25:12 +00003742 break;
3743 }
3744 case 'l':
3745 {
anthony31f1bf72012-01-30 12:37:22 +00003746 if (LocaleCompare("layers",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003747 {
anthony805a2d42011-09-25 08:25:12 +00003748 ImageLayerMethod
3749 method;
3750
anthony805a2d42011-09-25 08:25:12 +00003751 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
anthony31f1bf72012-01-30 12:37:22 +00003752 MagickFalse,arg1);
anthony805a2d42011-09-25 08:25:12 +00003753 switch (method)
3754 {
3755 case CoalesceLayer:
3756 {
anthony31f1bf72012-01-30 12:37:22 +00003757 new_images=CoalesceImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003758 break;
3759 }
3760 case CompareAnyLayer:
3761 case CompareClearLayer:
3762 case CompareOverlayLayer:
3763 default:
3764 {
anthony31f1bf72012-01-30 12:37:22 +00003765 new_images=CompareImagesLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003766 break;
3767 }
3768 case MergeLayer:
3769 case FlattenLayer:
3770 case MosaicLayer:
3771 case TrimBoundsLayer:
3772 {
anthony31f1bf72012-01-30 12:37:22 +00003773 new_images=MergeImageLayers(images,method,exception);
anthony805a2d42011-09-25 08:25:12 +00003774 break;
3775 }
3776 case DisposeLayer:
3777 {
anthony31f1bf72012-01-30 12:37:22 +00003778 new_images=DisposeImages(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003779 break;
3780 }
3781 case OptimizeImageLayer:
3782 {
anthony31f1bf72012-01-30 12:37:22 +00003783 new_images=OptimizeImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003784 break;
3785 }
3786 case OptimizePlusLayer:
3787 {
anthony31f1bf72012-01-30 12:37:22 +00003788 new_images=OptimizePlusImageLayers(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003789 break;
3790 }
3791 case OptimizeTransLayer:
3792 {
anthony31f1bf72012-01-30 12:37:22 +00003793 OptimizeImageTransparency(images,exception);
anthony805a2d42011-09-25 08:25:12 +00003794 break;
3795 }
3796 case RemoveDupsLayer:
3797 {
anthony31f1bf72012-01-30 12:37:22 +00003798 RemoveDuplicateLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003799 break;
3800 }
3801 case RemoveZeroLayer:
3802 {
anthony31f1bf72012-01-30 12:37:22 +00003803 RemoveZeroDelayLayers(&images,exception);
anthony805a2d42011-09-25 08:25:12 +00003804 break;
3805 }
3806 case OptimizeLayer:
anthony31f1bf72012-01-30 12:37:22 +00003807 { /* General Purpose, GIF Animation Optimizer. */
3808 new_images=CoalesceImages(images,exception);
3809 if (new_images == (Image *) NULL)
3810 break;
3811 images=DestroyImageList(images);
3812 images=OptimizeImageLayers(new_images,exception);
3813 if (images == (Image *) NULL)
3814 break;
3815 new_images=DestroyImageList(new_images);
3816 OptimizeImageTransparency(images,exception);
3817 (void) RemapImages(quantize_info,images,(Image *) NULL,
anthony805a2d42011-09-25 08:25:12 +00003818 exception);
3819 break;
3820 }
3821 case CompositeLayer:
3822 {
anthony805a2d42011-09-25 08:25:12 +00003823 Image
3824 *source;
3825
3826 RectangleInfo
3827 geometry;
3828
anthony31f1bf72012-01-30 12:37:22 +00003829 CompositeOperator
anthony5f867ae2011-10-09 10:28:34 +00003830 compose;
3831
3832 const char*
3833 value;
3834
3835 value=GetImageOption(image_info,"compose");
anthony31f1bf72012-01-30 12:37:22 +00003836 compose=OverCompositeOp; /* Default to Over */
anthony5f867ae2011-10-09 10:28:34 +00003837 if (value != (const char *) NULL)
3838 compose=(CompositeOperator) ParseCommandOption(
3839 MagickComposeOptions,MagickFalse,value);
anthony5f867ae2011-10-09 10:28:34 +00003840
anthony31f1bf72012-01-30 12:37:22 +00003841 /* Split image sequence at the first 'NULL:' image. */
3842 source=images;
anthony805a2d42011-09-25 08:25:12 +00003843 while (source != (Image *) NULL)
3844 {
3845 source=GetNextImageInList(source);
3846 if ((source != (Image *) NULL) &&
3847 (LocaleCompare(source->magick,"NULL") == 0))
3848 break;
3849 }
3850 if (source != (Image *) NULL)
3851 {
3852 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
3853 (GetNextImageInList(source) == (Image *) NULL))
3854 source=(Image *) NULL;
3855 else
anthony31f1bf72012-01-30 12:37:22 +00003856 { /* Separate the two lists, junk the null: image. */
anthony805a2d42011-09-25 08:25:12 +00003857 source=SplitImageList(source->previous);
3858 DeleteImageFromList(&source);
3859 }
3860 }
3861 if (source == (Image *) NULL)
3862 {
3863 (void) ThrowMagickException(exception,GetMagickModule(),
3864 OptionError,"MissingNullSeparator","layers Composite");
anthony805a2d42011-09-25 08:25:12 +00003865 break;
3866 }
anthony31f1bf72012-01-30 12:37:22 +00003867 /* Adjust offset with gravity and virtual canvas. */
3868 SetGeometry(images,&geometry);
3869 (void) ParseAbsoluteGeometry(images->geometry,&geometry);
anthony805a2d42011-09-25 08:25:12 +00003870 geometry.width=source->page.width != 0 ?
3871 source->page.width : source->columns;
3872 geometry.height=source->page.height != 0 ?
3873 source->page.height : source->rows;
anthony31f1bf72012-01-30 12:37:22 +00003874 GravityAdjustGeometry(images->page.width != 0 ?
3875 images->page.width : images->columns,
3876 images->page.height != 0 ? images->page.height :
3877 images->rows,images->gravity,&geometry);
anthony5f867ae2011-10-09 10:28:34 +00003878
anthony31f1bf72012-01-30 12:37:22 +00003879 /* Compose the two image sequences together */
3880 CompositeLayers(images,compose,source,geometry.x,geometry.y,
anthony805a2d42011-09-25 08:25:12 +00003881 exception);
3882 source=DestroyImageList(source);
3883 break;
3884 }
3885 }
anthony805a2d42011-09-25 08:25:12 +00003886 break;
3887 }
anthony72feaa62012-01-17 06:46:23 +00003888 if (LocaleCompare("limit",option) == 0)
3889 {
3890 MagickSizeType
3891 limit;
3892
3893 ResourceType
3894 type;
3895
anthony72feaa62012-01-17 06:46:23 +00003896 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
anthony31f1bf72012-01-30 12:37:22 +00003897 MagickFalse,arg1);
anthony72feaa62012-01-17 06:46:23 +00003898 limit=MagickResourceInfinity;
anthony31f1bf72012-01-30 12:37:22 +00003899 if (LocaleCompare("unlimited",arg2) != 0)
3900 limit=(MagickSizeType) SiPrefixToDoubleInterval(arg2,100.0);
anthony72feaa62012-01-17 06:46:23 +00003901 (void) SetMagickResourceLimit(type,limit);
3902 break;
3903 }
anthony805a2d42011-09-25 08:25:12 +00003904 break;
3905 }
3906 case 'm':
3907 {
anthony31f1bf72012-01-30 12:37:22 +00003908 if (LocaleCompare("map",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003909 {
anthony31f1bf72012-01-30 12:37:22 +00003910 /* DEPRECIATED use +remap */
3911 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
anthony805a2d42011-09-25 08:25:12 +00003912 break;
3913 }
anthony31f1bf72012-01-30 12:37:22 +00003914 if (LocaleCompare("morph",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003915 {
3916 Image
3917 *morph_image;
3918
anthony31f1bf72012-01-30 12:37:22 +00003919 morph_image=MorphImages(images,StringToUnsignedLong(arg1),
anthony805a2d42011-09-25 08:25:12 +00003920 exception);
3921 if (morph_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00003922 break;
3923 images=DestroyImageList(images);
3924 images=morph_image;
anthony805a2d42011-09-25 08:25:12 +00003925 break;
3926 }
anthony31f1bf72012-01-30 12:37:22 +00003927 if (LocaleCompare("mosaic",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003928 {
anthony31f1bf72012-01-30 12:37:22 +00003929 /* DEPRECIATED use -layers mosaic instead */
anthony43f425d2012-02-26 12:58:58 +00003930 CLIListOperatorImages(cli_wand,plus_alt_op,"layer",option,NULL);
anthony805a2d42011-09-25 08:25:12 +00003931 break;
3932 }
3933 break;
3934 }
3935 case 'p':
3936 {
anthony31f1bf72012-01-30 12:37:22 +00003937 if (LocaleCompare("print",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003938 {
3939 char
3940 *string;
3941
anthony31f1bf72012-01-30 12:37:22 +00003942 string=InterpretImageProperties(image_info,images,arg1,
anthony805a2d42011-09-25 08:25:12 +00003943 exception);
3944 if (string == (char *) NULL)
3945 break;
3946 (void) FormatLocaleFile(stdout,"%s",string);
3947 string=DestroyString(string);
3948 }
anthony31f1bf72012-01-30 12:37:22 +00003949 if (LocaleCompare("process",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00003950 {
3951 char
3952 **arguments;
3953
3954 int
3955 j,
3956 number_arguments;
3957
anthony31f1bf72012-01-30 12:37:22 +00003958 arguments=StringToArgv(arg1,&number_arguments);
anthony805a2d42011-09-25 08:25:12 +00003959 if (arguments == (char **) NULL)
3960 break;
anthony31f1bf72012-01-30 12:37:22 +00003961 if (strchr(arguments[1],'=') != (char *) NULL)
anthony805a2d42011-09-25 08:25:12 +00003962 {
3963 char
3964 breaker,
3965 quote,
3966 *token;
3967
3968 const char
3969 *arguments;
3970
3971 int
3972 next,
3973 status;
3974
3975 size_t
3976 length;
3977
3978 TokenInfo
3979 *token_info;
3980
3981 /*
3982 Support old style syntax, filter="-option arg".
3983 */
anthony31f1bf72012-01-30 12:37:22 +00003984 length=strlen(arg1);
anthony805a2d42011-09-25 08:25:12 +00003985 token=(char *) NULL;
3986 if (~length >= (MaxTextExtent-1))
3987 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
3988 sizeof(*token));
3989 if (token == (char *) NULL)
3990 break;
3991 next=0;
anthony31f1bf72012-01-30 12:37:22 +00003992 arguments=arg1;
anthony805a2d42011-09-25 08:25:12 +00003993 token_info=AcquireTokenInfo();
3994 status=Tokenizer(token_info,0,token,length,arguments,"","=",
3995 "\"",'\0',&breaker,&next,&quote);
3996 token_info=DestroyTokenInfo(token_info);
3997 if (status == 0)
3998 {
3999 const char
4000 *argv;
4001
4002 argv=(&(arguments[next]));
anthony31f1bf72012-01-30 12:37:22 +00004003 (void) InvokeDynamicImageFilter(token,&images,1,&argv,
anthony805a2d42011-09-25 08:25:12 +00004004 exception);
4005 }
4006 token=DestroyString(token);
4007 break;
4008 }
4009 (void) SubstituteString(&arguments[1],"-","");
anthony31f1bf72012-01-30 12:37:22 +00004010 (void) InvokeDynamicImageFilter(arguments[1],&images,
anthony805a2d42011-09-25 08:25:12 +00004011 number_arguments-2,(const char **) arguments+2,exception);
4012 for (j=0; j < number_arguments; j++)
4013 arguments[j]=DestroyString(arguments[j]);
4014 arguments=(char **) RelinquishMagickMemory(arguments);
4015 break;
4016 }
4017 break;
4018 }
4019 case 'r':
4020 {
anthony31f1bf72012-01-30 12:37:22 +00004021 if (LocaleCompare("remap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00004022 {
anthony31f1bf72012-01-30 12:37:22 +00004023 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
4024 (void) RemapImages(quantize_info,images,(Image *) NULL,exception);
4025 break;
4026 }
4027 if (LocaleCompare("reverse",option) == 0)
4028 {
4029 ReverseImageList(&images);
anthony805a2d42011-09-25 08:25:12 +00004030 break;
4031 }
4032 break;
4033 }
4034 case 's':
4035 {
anthony31f1bf72012-01-30 12:37:22 +00004036 if (LocaleCompare("smush",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00004037 {
4038 Image
4039 *smush_image;
4040
4041 ssize_t
4042 offset;
4043
anthony31f1bf72012-01-30 12:37:22 +00004044 offset=(ssize_t) StringToLong(arg1);
4045 smush_image=SmushImages(images,normal_op,offset,exception);
anthony805a2d42011-09-25 08:25:12 +00004046 if (smush_image == (Image *) NULL)
anthony31f1bf72012-01-30 12:37:22 +00004047 break;
4048 images=DestroyImageList(images);
4049 images=smush_image;
anthony805a2d42011-09-25 08:25:12 +00004050 break;
4051 }
anthony31f1bf72012-01-30 12:37:22 +00004052 if (LocaleCompare("swap",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00004053 {
4054 Image
4055 *p,
4056 *q,
4057 *swap;
4058
4059 ssize_t
anthony31f1bf72012-01-30 12:37:22 +00004060 index,
anthony805a2d42011-09-25 08:25:12 +00004061 swap_index;
4062
anthony31f1bf72012-01-30 12:37:22 +00004063 index=-1;
4064 swap_index=-2;
4065 if (plus_alt_op == MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00004066 {
4067 GeometryInfo
4068 geometry_info;
4069
4070 MagickStatusType
4071 flags;
4072
4073 swap_index=(-1);
anthony31f1bf72012-01-30 12:37:22 +00004074 flags=ParseGeometry(arg1,&geometry_info);
anthony805a2d42011-09-25 08:25:12 +00004075 index=(ssize_t) geometry_info.rho;
4076 if ((flags & SigmaValue) != 0)
4077 swap_index=(ssize_t) geometry_info.sigma;
4078 }
anthony31f1bf72012-01-30 12:37:22 +00004079 p=GetImageFromList(images,index);
4080 q=GetImageFromList(images,swap_index);
anthony805a2d42011-09-25 08:25:12 +00004081 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4082 {
4083 (void) ThrowMagickException(exception,GetMagickModule(),
anthony43f425d2012-02-26 12:58:58 +00004084 OptionError,"NoSuchImage","'%s'",images->filename);
anthony805a2d42011-09-25 08:25:12 +00004085 break;
4086 }
4087 if (p == q)
4088 break;
4089 swap=CloneImage(p,0,0,MagickTrue,exception);
4090 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4091 ReplaceImageInList(&q,swap);
anthony31f1bf72012-01-30 12:37:22 +00004092 images=GetFirstImageInList(q);
anthony805a2d42011-09-25 08:25:12 +00004093 break;
4094 }
4095 break;
4096 }
4097 case 'w':
4098 {
anthony31f1bf72012-01-30 12:37:22 +00004099 if (LocaleCompare("write",option) == 0)
anthony805a2d42011-09-25 08:25:12 +00004100 {
4101 char
4102 key[MaxTextExtent];
4103
4104 Image
4105 *write_images;
4106
4107 ImageInfo
4108 *write_info;
4109
anthony31f1bf72012-01-30 12:37:22 +00004110 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",arg1);
anthony805a2d42011-09-25 08:25:12 +00004111 (void) DeleteImageRegistry(key);
anthony31f1bf72012-01-30 12:37:22 +00004112 write_images=images;
4113 if (plus_alt_op != MagickFalse)
4114 write_images=CloneImageList(images,exception);
anthony805a2d42011-09-25 08:25:12 +00004115 write_info=CloneImageInfo(image_info);
anthony31f1bf72012-01-30 12:37:22 +00004116 (void) WriteImages(write_info,write_images,arg1,exception);
anthony805a2d42011-09-25 08:25:12 +00004117 write_info=DestroyImageInfo(write_info);
anthony31f1bf72012-01-30 12:37:22 +00004118 if (plus_alt_op != MagickFalse)
anthony805a2d42011-09-25 08:25:12 +00004119 write_images=DestroyImageList(write_images);
4120 break;
4121 }
4122 break;
4123 }
4124 default:
4125 break;
4126 }
anthony31f1bf72012-01-30 12:37:22 +00004127 if (new_images == (Image *) NULL)
4128 return;
anthony805a2d42011-09-25 08:25:12 +00004129
anthony31f1bf72012-01-30 12:37:22 +00004130 if (images != (Image *) NULL)
4131 images=DestroyImageList(images);
anthony43f425d2012-02-26 12:58:58 +00004132 images=GetFirstImageInList(new_images);
anthony31f1bf72012-01-30 12:37:22 +00004133 return;
4134
4135#undef image_info
anthony31f1bf72012-01-30 12:37:22 +00004136#undef images
4137#undef exception
anthony43f425d2012-02-26 12:58:58 +00004138#undef draw_info
4139#undef quantize_info
anthony31f1bf72012-01-30 12:37:22 +00004140#undef normal_op
anthony805a2d42011-09-25 08:25:12 +00004141}
anthony43f425d2012-02-26 12:58:58 +00004142
4143/*
4144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4145% %
4146% %
4147% %
4148+ C L I S p e c i a l O p e r a t i o n s %
4149% %
4150% %
4151% %
4152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4153%
4154% CLISpecialOption() Applies operations that may involve empty image lists
4155% and or stacks of image lists or image_info settings.
4156%
4157% Note: inlike other Operators, these may involve other special 'option'
4158% character prefixes, other than simply '-' or '+' and as such the full
4159% original otpion must be passed.
4160%
4161% The format of the CLISpecialOption method is:
4162%
4163% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
4164% const char *arg)
4165%
4166% A description of each parameter follows:
4167%
4168% o cli_wand: the main CLI Wand to use.
4169%
4170% o option: The special option (with any switch char) to process
4171%
4172% o arg: Argument for option, if required
4173%
4174*/
4175
4176#define MaxImageStackDepth 32
4177
4178WandExport void CLISpecialOperator(MagickCLI *cli_wand,
4179 const char *option, const char *arg)
4180{
4181#define exception (cli_wand->wand.exception)
4182
4183 assert(cli_wand != (MagickCLI *) NULL);
4184 assert(cli_wand->signature == WandSignature);
4185 assert(cli_wand->wand.signature == WandSignature);
4186 if (cli_wand->wand.debug != MagickFalse)
4187 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
4188
4189 if (LocaleCompare(option,"(") == 0)
4190 {
4191 /* stack 'push' images */
4192 Stack
4193 *node;
4194
4195 size_t
4196 size;
4197
4198 const char*
4199 value;
4200
4201 size=0;
4202 node=cli_wand->image_list_stack;
4203 for ( ; node != (Stack *)NULL; node=node->next)
4204 size++;
4205 if ( size >= MaxImageStackDepth )
4206 {
4207 ThrowMagickException(exception,GetMagickModule(),
4208 OptionError,"ParenthesisNestedTooDeeply", option);
4209 return;
4210 }
4211 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4212 if (node == (Stack *) NULL)
4213 {
4214 ThrowMagickException(exception,GetMagickModule(),
4215 ResourceLimitFatalError,"MemoryAllocationFailed", "PushImages");
4216 return;
4217 }
4218 node->data = (void *)cli_wand->wand.images;
4219 cli_wand->wand.images = NewImageList();
4220 node->next = cli_wand->image_list_stack;
4221 cli_wand->image_list_stack = node;
4222
4223 /* handle respect-parenthesis */
4224 value=GetImageOption(cli_wand->wand.image_info,"respect-parenthesis");
4225 if (value != (const char *) NULL)
4226 option="{";
4227 else
4228 return;
4229 }
4230 if (LocaleCompare(option,"{") == 0)
4231 {
4232 /* stack 'push' of image_info settings */
4233 Stack
4234 *node;
4235
4236 size_t
4237 size;
4238
4239 size=0;
4240 node=cli_wand->image_info_stack;
4241 for ( ; node != (Stack *)NULL; node=node->next)
4242 size++;
4243 if ( size >= MaxImageStackDepth )
4244 {
4245 ThrowMagickException(exception,GetMagickModule(),
4246 OptionError,"ParenthesisNestedTooDeeply", option);
4247 return;
4248 }
4249 node=(Stack *) AcquireMagickMemory(sizeof(*node));
4250 if (node == (Stack *) NULL)
4251 {
4252 ThrowMagickException(exception,GetMagickModule(),
4253 ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
4254 return;
4255 }
4256
4257 node->data = (void *)cli_wand->wand.image_info;
4258 cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
4259 if (cli_wand->wand.image_info == (ImageInfo *)NULL)
4260 {
4261 ThrowMagickException(exception,GetMagickModule(),
4262 ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
4263 cli_wand->wand.image_info = (ImageInfo *)node->data;
4264 node = (Stack *)RelinquishMagickMemory(node);
4265 return;
4266 }
4267
4268 node->next = cli_wand->image_info_stack;
4269 cli_wand->image_info_stack = node;
4270
4271 return;
4272 }
4273 if (LocaleCompare(option,")") == 0)
4274 {
4275 /* pop images from stack */
4276 Stack
4277 *node;
4278
4279 const char*
4280 value;
4281
4282 node = (void *)cli_wand->image_list_stack;
4283 if ( node == (Stack *)NULL)
4284 {
4285 ThrowMagickException(exception,GetMagickModule(),
4286 OptionError,"UnbalancedParenthesis", option);
4287 return;
4288 }
4289 cli_wand->image_list_stack = node->next;
4290
4291 AppendImageToList((Image **)&node->data,cli_wand->wand.images);
4292 cli_wand->wand.images= (Image *)node->data;
4293 node = (Stack *)RelinquishMagickMemory(node);
4294
4295 /* handle respect-parenthesis - of the previous 'push' settings */
4296 node = cli_wand->image_info_stack;
4297 if ( node != (Stack *)NULL)
4298 {
4299 value=GetImageOption((ImageInfo *)node->data,"respect-parenthesis");
4300 if (value != (const char *) NULL)
4301 option="}";
4302 else
4303 return;
4304 }
4305 else
4306 return;
4307 }
4308 if (LocaleCompare(option,"}") == 0)
4309 {
4310 /* pop image_info settings from stack */
4311 Stack
4312 *node;
4313
4314 node = (void *)cli_wand->image_info_stack;
4315 if ( node == (Stack *)NULL)
4316 {
4317 ThrowMagickException(exception,GetMagickModule(),
4318 OptionError,"UnbalancedParenthesis", option);
4319 return;
4320 }
4321 cli_wand->image_info_stack = node->next;
4322
4323 (void) DestroyImageInfo(cli_wand->wand.image_info);
4324 cli_wand->wand.image_info = (ImageInfo *)node->data;
4325 node = (Stack *)RelinquishMagickMemory(node);
4326
4327 GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
4328 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
4329 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
4330
4331 return;
4332 }
4333 if (LocaleCompare(option+1,"clone") == 0)
4334 {
4335 Image
4336 *new_images;
4337
4338 if (*option == '+')
4339 arg="-1";
4340 if (IsSceneGeometry(arg,MagickFalse) == MagickFalse)
4341 {
4342 ThrowMagickException(exception,GetMagickModule(),
4343 OptionError,"InvalidArgument", "'%s': %s", option, arg);
4344 return;
4345 }
4346 if ( cli_wand->image_list_stack == (Stack *)NULL)
4347 {
4348 ThrowMagickException(exception,GetMagickModule(),
4349 OptionError,"UnableToCloneImage", option);
4350 return;
4351 }
4352 new_images = (Image *)cli_wand->image_list_stack->data;
4353 if (new_images == (Image *) NULL)
4354 {
4355 ThrowMagickException(exception,GetMagickModule(),
4356 OptionError,"UnableToCloneImage", option);
4357 return;
4358 }
4359 new_images=CloneImages(new_images,arg,exception);
4360 if (new_images == (Image *) NULL)
4361 {
4362 ThrowMagickException(exception,GetMagickModule(),
4363 OptionError,"NoSuchImage",option);
4364 return;
4365 }
4366 AppendImageToList(&cli_wand->wand.images,new_images);
4367 return;
4368 }
4369 if ( LocaleCompare("-read",option) == 0 )
4370 {
4371#if 1
4372 Image *
4373 new_images;
4374
4375 CopyMagickString(cli_wand->wand.image_info->filename,arg,MaxTextExtent);
4376 if (cli_wand->wand.image_info->ping != MagickFalse)
4377 new_images=PingImages(cli_wand->wand.image_info,exception);
4378 else
4379 new_images=ReadImages(cli_wand->wand.image_info,exception);
4380 AppendImageToList(&cli_wand->wand.images, new_images);
4381#else
4382 /* read images using MagickWand method - no ping */
4383 /* This is not working! - it locks up in a CPU loop! */
4384 MagickSetLastIterator(&cli_wand->wand);
4385 MagickReadImage(&cli_wand->wand,arg);
4386 MagickSetFirstIterator(&cli_wand->wand);
4387#endif
4388 return;
4389 }
4390 if (LocaleCompare("-noop",option) == 0)
4391 return;
4392 if (LocaleCompare("-sans",option) == 0)
4393 return;
4394 if (LocaleCompare("-sans0",option) == 0)
4395 return;
4396 if (LocaleCompare("-sans2",option) == 0)
4397 return;
4398 if (LocaleCompare("-list",option) == 0)
4399 {
4400 /* FUTURE: This should really be built into the MagickCore
4401 It does not actually require any wand or images at all!
4402 */
4403 ssize_t
4404 list;
4405
4406 list=ParseCommandOption(MagickListOptions,MagickFalse, arg);
4407 switch (list)
4408 {
4409 case MagickCoderOptions:
4410 {
4411 (void) ListCoderInfo((FILE *) NULL,exception);
4412 break;
4413 }
4414 case MagickColorOptions:
4415 {
4416 (void) ListColorInfo((FILE *) NULL,exception);
4417 break;
4418 }
4419 case MagickConfigureOptions:
4420 {
4421 (void) ListConfigureInfo((FILE *) NULL,exception);
4422 break;
4423 }
4424 case MagickDelegateOptions:
4425 {
4426 (void) ListDelegateInfo((FILE *) NULL,exception);
4427 break;
4428 }
4429 case MagickFontOptions:
4430 {
4431 (void) ListTypeInfo((FILE *) NULL,exception);
4432 break;
4433 }
4434 case MagickFormatOptions:
4435 (void) ListMagickInfo((FILE *) NULL,exception);
4436 break;
4437 case MagickLocaleOptions:
4438 (void) ListLocaleInfo((FILE *) NULL,exception);
4439 break;
4440 case MagickLogOptions:
4441 (void) ListLogInfo((FILE *) NULL,exception);
4442 break;
4443 case MagickMagicOptions:
4444 (void) ListMagicInfo((FILE *) NULL,exception);
4445 break;
4446 case MagickMimeOptions:
4447 (void) ListMimeInfo((FILE *) NULL,exception);
4448 break;
4449 case MagickModuleOptions:
4450 (void) ListModuleInfo((FILE *) NULL,exception);
4451 break;
4452 case MagickPolicyOptions:
4453 (void) ListPolicyInfo((FILE *) NULL,exception);
4454 break;
4455 case MagickResourceOptions:
4456 (void) ListMagickResourceInfo((FILE *) NULL,exception);
4457 break;
4458 case MagickThresholdOptions:
4459 (void) ListThresholdMaps((FILE *) NULL,exception);
4460 break;
4461 default:
4462 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
4463 exception);
4464 break;
4465 }
4466 return;
4467 }
4468
4469#if 0
4470 // adjust stack handling
4471 // Other 'special' options this should handle
4472 // "region" "list" "version"
4473 // It does not do "exit" however as due to its side-effect requirements
4474#endif
4475#if 0
4476 if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
4477 MagickExceptionReturn(OptionError,"InvalidUseOfOption",option);
4478#endif
4479
4480#undef image_info
4481#undef images
4482#undef exception
4483}