blob: 140cf6f9bbe99226c740b1203af264c5ce0b8df5 [file] [log] [blame]
anthony805a2d42011-09-25 08:25:12 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% OOO PPPP EEEE RRRR AA TTTTTT III OOO N N %
7% O O P P E R R A A TT I O O NN N %
8% O O PPPP EEE RRRR AAAA TT I O O N N N %
9% O O P E R R A A TT I O O N NN %
10% OOO P EEEE R RR A A TT III OOO N N %
11% %
12% %
13% MagickWand Module Methods %
14% %
15% Software Design %
16% John Cristy %
17% September 2011 %
18% %
19% %
20% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21% 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
37% the given image(s) according to the current "image_info" and "draw_info"
38% settings.
39%
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%
44% Anthony Thyssen, Sept 2011
45*/
46
47/*
48 Include declarations.
49*/
50#include "MagickWand/studio.h"
51#include "MagickWand/MagickWand.h"
52#include "MagickWand/mogrify-private.h"
53#include "MagickCore/monitor-private.h"
54#include "MagickCore/thread-private.h"
55#include "MagickCore/string-private.h"
56
57/*
58 Define declarations.
59*/
60#define UndefinedCompressionQuality 0UL
61/*
62 Constant declaration. (temporary exports)
63*/
64static const char
65 BackgroundColor[] = "#fff", /* white */
66 BorderColor[] = "#dfdfdf", /* gray */
67 MatteColor[] = "#bdbdbd"; /* gray */
68
69/*
70** Function to report on the progress of image operations
71*/
72static MagickBooleanType MonitorProgress(const char *text,
73 const MagickOffsetType offset,const MagickSizeType extent,
74 void *wand_unused(client_data))
75{
76 char
77 message[MaxTextExtent],
78 tag[MaxTextExtent];
79
80 const char
81 *locale_message;
82
83 register char
84 *p;
85
86 if (extent < 2)
87 return(MagickTrue);
88 (void) CopyMagickMemory(tag,text,MaxTextExtent);
89 p=strrchr(tag,'/');
90 if (p != (char *) NULL)
91 *p='\0';
92 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
93 locale_message=GetLocaleMessage(message);
94 if (locale_message == message)
95 locale_message=tag;
96 if (p == (char *) NULL)
97 (void) FormatLocaleFile(stderr,"%s: %ld of %lu, %02ld%% complete\r",
98 locale_message,(long) offset,(unsigned long) extent,(long)
99 (100L*offset/(extent-1)));
100 else
101 (void) FormatLocaleFile(stderr,"%s[%s]: %ld of %lu, %02ld%% complete\r",
102 locale_message,p+1,(long) offset,(unsigned long) extent,(long)
103 (100L*offset/(extent-1)));
104 if (offset == (MagickOffsetType) (extent-1))
105 (void) FormatLocaleFile(stderr,"\n");
106 (void) fflush(stderr);
107 return(MagickTrue);
108}
109
110/*
111** GetImageCache() will read an image into a image cache if not already
112** present then return the image that is in the cache under that filename.
113*/
114static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
115 ExceptionInfo *exception)
116{
117 char
118 key[MaxTextExtent];
119
120 ExceptionInfo
121 *sans_exception;
122
123 Image
124 *image;
125
126 ImageInfo
127 *read_info;
128
129 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",path);
130 sans_exception=AcquireExceptionInfo();
131 image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
132 sans_exception=DestroyExceptionInfo(sans_exception);
133 if (image != (Image *) NULL)
134 return(image);
135 read_info=CloneImageInfo(image_info);
136 (void) CopyMagickString(read_info->filename,path,MaxTextExtent);
137 image=ReadImage(read_info,exception);
138 read_info=DestroyImageInfo(read_info);
139 if (image != (Image *) NULL)
140 (void) SetImageRegistry(ImageRegistryType,key,image,exception);
141 return(image);
142}
143
144/*
145** SparseColorOption() parse the complex -sparse-color argument into an
146** an array of floating point values than call SparseColorImage().
147** Argument is a complex mix of floating-point pixel coodinates, and color
148** specifications (or direct floating point numbers). The number of floats
149** needed to represent a color varies depending on teh current channel
150** setting.
151*/
152static Image *SparseColorOption(const Image *image,
153 const SparseColorMethod method,const char *arguments,
154 const MagickBooleanType color_from_image,ExceptionInfo *exception)
155{
156 char
157 token[MaxTextExtent];
158
159 const char
160 *p;
161
162 double
163 *sparse_arguments;
164
165 Image
166 *sparse_image;
167
168 PixelInfo
169 color;
170
171 MagickBooleanType
172 error;
173
174 register size_t
175 x;
176
177 size_t
178 number_arguments,
179 number_colors;
180
181 assert(image != (Image *) NULL);
182 assert(image->signature == MagickSignature);
183 if (image->debug != MagickFalse)
184 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
185 assert(exception != (ExceptionInfo *) NULL);
186 assert(exception->signature == MagickSignature);
187 /*
188 Limit channels according to image - and add up number of color channel.
189 */
190 number_colors=0;
191 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
192 number_colors++;
193 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
194 number_colors++;
195 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
196 number_colors++;
197 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
198 (image->colorspace == CMYKColorspace))
199 number_colors++;
200 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
201 (image->matte != MagickFalse))
202 number_colors++;
203
204 /*
205 Read string, to determine number of arguments needed,
206 */
207 p=arguments;
208 x=0;
209 while( *p != '\0' )
210 {
211 GetMagickToken(p,&p,token);
212 if ( token[0] == ',' ) continue;
213 if ( isalpha((int) token[0]) || token[0] == '#' ) {
214 if ( color_from_image ) {
215 (void) ThrowMagickException(exception,GetMagickModule(),
216 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
217 "Color arg given, when colors are coming from image");
218 return( (Image *)NULL);
219 }
220 x += number_colors; /* color argument */
221 }
222 else {
223 x++; /* floating point argument */
224 }
225 }
226 error=MagickTrue;
227 if ( color_from_image ) {
228 /* just the control points are being given */
229 error = ( x % 2 != 0 ) ? MagickTrue : MagickFalse;
230 number_arguments=(x/2)*(2+number_colors);
231 }
232 else {
233 /* control points and color values */
234 error = ( x % (2+number_colors) != 0 ) ? MagickTrue : MagickFalse;
235 number_arguments=x;
236 }
237 if ( error ) {
238 (void) ThrowMagickException(exception,GetMagickModule(),
239 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
240 "Invalid number of Arguments");
241 return( (Image *)NULL);
242 }
243
244 /* Allocate and fill in the floating point arguments */
245 sparse_arguments=(double *) AcquireQuantumMemory(number_arguments,
246 sizeof(*sparse_arguments));
247 if (sparse_arguments == (double *) NULL) {
248 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
249 "MemoryAllocationFailed","%s","SparseColorOption");
250 return( (Image *)NULL);
251 }
252 (void) ResetMagickMemory(sparse_arguments,0,number_arguments*
253 sizeof(*sparse_arguments));
254 p=arguments;
255 x=0;
256 while( *p != '\0' && x < number_arguments ) {
257 /* X coordinate */
258 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
259 if ( token[0] == '\0' ) break;
260 if ( isalpha((int) token[0]) || token[0] == '#' ) {
261 (void) ThrowMagickException(exception,GetMagickModule(),
262 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
263 "Color found, instead of X-coord");
264 error = MagickTrue;
265 break;
266 }
267 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
268 /* Y coordinate */
269 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
270 if ( token[0] == '\0' ) break;
271 if ( isalpha((int) token[0]) || token[0] == '#' ) {
272 (void) ThrowMagickException(exception,GetMagickModule(),
273 OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
274 "Color found, instead of Y-coord");
275 error = MagickTrue;
276 break;
277 }
278 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
279 /* color values for this control point */
280#if 0
281 if ( (color_from_image ) {
282 /* get color from image */
283 /* HOW??? */
284 }
285 else
286#endif
287 {
288 /* color name or function given in string argument */
289 token[0]=','; while ( token[0] == ',' ) GetMagickToken(p,&p,token);
290 if ( token[0] == '\0' ) break;
291 if ( isalpha((int) token[0]) || token[0] == '#' ) {
292 /* Color string given */
293 (void) QueryMagickColor(token,&color,exception);
294 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
295 sparse_arguments[x++] = QuantumScale*color.red;
296 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
297 sparse_arguments[x++] = QuantumScale*color.green;
298 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
299 sparse_arguments[x++] = QuantumScale*color.blue;
300 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
301 (image->colorspace == CMYKColorspace))
302 sparse_arguments[x++] = QuantumScale*color.black;
303 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
304 (image->matte != MagickFalse))
305 sparse_arguments[x++] = QuantumScale*color.alpha;
306 }
307 else {
308 /* Colors given as a set of floating point values - experimental */
309 /* NB: token contains the first floating point value to use! */
310 if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
311 {
312 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
313 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
314 break;
315 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
316 token[0] = ','; /* used this token - get another */
317 }
318 if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
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++]=InterpretLocaleValue(token,(char **) NULL);
324 token[0] = ','; /* used this token - get another */
325 }
326 if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
327 {
328 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
329 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
330 break;
331 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
332 token[0] = ','; /* used this token - get another */
333 }
334 if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
335 (image->colorspace == CMYKColorspace))
336 {
337 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
338 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
339 break;
340 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
341 token[0] = ','; /* used this token - get another */
342 }
343 if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
344 (image->matte != MagickFalse))
345 {
346 while ( token[0] == ',' ) GetMagickToken(p,&p,token);
347 if ( token[0] == '\0' || isalpha((int)token[0]) || token[0] == '#' )
348 break;
349 sparse_arguments[x++]=InterpretLocaleValue(token,(char **) NULL);
350 token[0] = ','; /* used this token - get another */
351 }
352 }
353 }
354 }
355 if ( number_arguments != x && !error ) {
356 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
357 "InvalidArgument","`%s': %s","sparse-color","Argument Parsing Error");
358 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
359 return( (Image *)NULL);
360 }
361 if ( error )
362 return( (Image *)NULL);
363
364 /* Call the Interpolation function with the parsed arguments */
365 sparse_image=SparseColorImage(image,method,number_arguments,sparse_arguments,
366 exception);
367 sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
368 return( sparse_image );
369}
370
371/*
372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373% %
374% %
375% %
376+ S e t t i n g s O p t i o n I n f o %
377% %
378% %
379% %
380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381%
382% SettingsOptionInfo() saves the given single settings argv[0] into a
383% ImageInfo structure for later use by various image processing operations.
384%
385% The format of the SettingsOptionInfo method is:
386%
387% MagickBooleanType SettingsOptionInfo(ImageInfo *image_info,
388% const int argc, const char **argv,ExceptionInfo *exception)
389%
390% A description of each parameter follows:
391%
392% o image_info: the image info..
393%
394% o argc: Specifies a pointer to an integer describing the number of
395% elements in the argument vector.
396%
397% o argv: Specifies a pointer to a text array containing the command line
398% arguments.
399%
400% o exception: return any errors or warnings in this structure.
401%
402*/
403WandExport MagickBooleanType SettingsOptionInfo(ImageInfo *image_info,
404 const int wand_unused(argc),const char **argv,ExceptionInfo *exception)
405{
406 GeometryInfo
407 geometry_info;
408
409 /*
410 Initialize method variables.
411 */
412 assert(image_info != (ImageInfo *) NULL);
413 assert(image_info->signature == MagickSignature);
414 if (image_info->debug != MagickFalse)
415 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
416 image_info->filename);
417 if (argc < 0)
418 return(MagickTrue);
419 /*
420 Set the image settings for one image.
421 */
422 switch (*(argv[0]+1))
423 {
424 case 'a':
425 {
426 if (LocaleCompare("adjoin",argv[0]+1) == 0)
427 {
428 image_info->adjoin=(*argv[0] == '-') ? MagickTrue : MagickFalse;
429 break;
430 }
431 if (LocaleCompare("antialias",argv[0]+1) == 0)
432 {
433 image_info->antialias=(*argv[0] == '-') ? MagickTrue : MagickFalse;
434 break;
435 }
436 if (LocaleCompare("attenuate",argv[0]+1) == 0)
437 {
438 if (*argv[0] == '+')
439 {
440 (void) DeleteImageOption(image_info,argv[0]+1);
441 break;
442 }
443 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
444 break;
445 }
446 if (LocaleCompare("authenticate",argv[0]+1) == 0)
447 {
448 if (*argv[0] == '+')
449 (void) CloneString(&image_info->authenticate,(char *) NULL);
450 else
451 (void) CloneString(&image_info->authenticate,argv[1]);
452 break;
453 }
454 break;
455 }
456 case 'b':
457 {
458 if (LocaleCompare("background",argv[0]+1) == 0)
459 {
460 if (*argv[0] == '+')
461 {
462 (void) DeleteImageOption(image_info,argv[0]+1);
463 (void) QueryColorDatabase(BackgroundColor,
464 &image_info->background_color,exception);
465 break;
466 }
467 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
468 (void) QueryColorDatabase(argv[1],&image_info->background_color,
469 exception);
470 break;
471 }
472 if (LocaleCompare("bias",argv[0]+1) == 0)
473 {
474 if (*argv[0] == '+')
475 {
476 (void) SetImageOption(image_info,argv[0]+1,"0.0");
477 break;
478 }
479 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
480 break;
481 }
482 if (LocaleCompare("black-point-compensation",argv[0]+1) == 0)
483 {
484 if (*argv[0] == '+')
485 {
486 (void) SetImageOption(image_info,argv[0]+1,"false");
487 break;
488 }
489 (void) SetImageOption(image_info,argv[0]+1,"true");
490 break;
491 }
492 if (LocaleCompare("blue-primary",argv[0]+1) == 0)
493 {
494 if (*argv[0] == '+')
495 {
496 (void) SetImageOption(image_info,argv[0]+1,"0.0");
497 break;
498 }
499 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
500 break;
501 }
502 if (LocaleCompare("bordercolor",argv[0]+1) == 0)
503 {
504 if (*argv[0] == '+')
505 {
506 (void) DeleteImageOption(image_info,argv[0]+1);
507 (void) QueryColorDatabase(BorderColor,&image_info->border_color,
508 exception);
509 break;
510 }
511 (void) QueryColorDatabase(argv[1],&image_info->border_color,
512 exception);
513 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
514 break;
515 }
516 if (LocaleCompare("box",argv[0]+1) == 0)
517 {
518 if (*argv[0] == '+')
519 {
520 (void) SetImageOption(image_info,"undercolor","none");
521 break;
522 }
523 (void) SetImageOption(image_info,"undercolor",argv[1]);
524 break;
525 }
526 break;
527 }
528 case 'c':
529 {
530 if (LocaleCompare("cache",argv[0]+1) == 0)
531 {
532 MagickSizeType
533 limit;
534
535 limit=MagickResourceInfinity;
536 if (LocaleCompare("unlimited",argv[1]) != 0)
537 limit=(MagickSizeType) SiPrefixToDouble(argv[1],100.0);
538 (void) SetMagickResourceLimit(MemoryResource,limit);
539 (void) SetMagickResourceLimit(MapResource,2*limit);
540 break;
541 }
542 if (LocaleCompare("caption",argv[0]+1) == 0)
543 {
544 if (*argv[0] == '+')
545 {
546 (void) DeleteImageOption(image_info,argv[0]+1);
547 break;
548 }
549 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
550 break;
551 }
552 if (LocaleCompare("channel",argv[0]+1) == 0)
553 {
554 if (*argv[0] == '+')
555 {
556 image_info->channel=DefaultChannels;
557 break;
558 }
559 image_info->channel=(ChannelType) ParseChannelOption(argv[1]);
560 break;
561 }
562 if (LocaleCompare("colors",argv[0]+1) == 0)
563 {
564 image_info->colors=StringToUnsignedLong(argv[1]);
565 break;
566 }
567 if (LocaleCompare("colorspace",argv[0]+1) == 0)
568 {
569 if (*argv[0] == '+')
570 {
571 image_info->colorspace=UndefinedColorspace;
572 (void) SetImageOption(image_info,argv[0]+1,"undefined");
573 break;
574 }
575 image_info->colorspace=(ColorspaceType) ParseCommandOption(
576 MagickColorspaceOptions,MagickFalse,argv[1]);
577 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
578 break;
579 }
580 if (LocaleCompare("comment",argv[0]+1) == 0)
581 {
582 if (*argv[0] == '+')
583 {
584 (void) DeleteImageOption(image_info,argv[0]+1);
585 break;
586 }
587 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
588 break;
589 }
590 if (LocaleCompare("compose",argv[0]+1) == 0)
591 {
592 if (*argv[0] == '+')
593 {
594 (void) SetImageOption(image_info,argv[0]+1,"undefined");
595 break;
596 }
597 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
598 break;
599 }
600 if (LocaleCompare("compress",argv[0]+1) == 0)
601 {
602 if (*argv[0] == '+')
603 {
604 image_info->compression=UndefinedCompression;
605 (void) SetImageOption(image_info,argv[0]+1,"undefined");
606 break;
607 }
608 image_info->compression=(CompressionType) ParseCommandOption(
609 MagickCompressOptions,MagickFalse,argv[1]);
610 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
611 break;
612 }
613 break;
614 }
615 case 'd':
616 {
617 if (LocaleCompare("debug",argv[0]+1) == 0)
618 {
619 if (*argv[0] == '+')
620 (void) SetLogEventMask("none");
621 else
622 (void) SetLogEventMask(argv[1]);
623 image_info->debug=IsEventLogging();
624 break;
625 }
626 if (LocaleCompare("define",argv[0]+1) == 0)
627 {
628 if (*argv[0] == '+')
629 {
630 if (LocaleNCompare(argv[1],"registry:",9) == 0)
631 (void) DeleteImageRegistry(argv[1]+9);
632 else
633 (void) DeleteImageOption(image_info,argv[1]);
634 break;
635 }
636 if (LocaleNCompare(argv[1],"registry:",9) == 0)
637 {
638 (void) DefineImageRegistry(StringRegistryType,argv[1]+9,
639 exception);
640 break;
641 }
642 (void) DefineImageOption(image_info,argv[1]);
643 break;
644 }
645 if (LocaleCompare("delay",argv[0]+1) == 0)
646 {
647 if (*argv[0] == '+')
648 {
649 (void) SetImageOption(image_info,argv[0]+1,"0");
650 break;
651 }
652 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
653 break;
654 }
655 if (LocaleCompare("density",argv[0]+1) == 0)
656 {
657 /*
658 Set image density.
659 */
660 if (*argv[0] == '+')
661 {
662 if (image_info->density != (char *) NULL)
663 image_info->density=DestroyString(image_info->density);
664 (void) SetImageOption(image_info,argv[0]+1,"72");
665 break;
666 }
667 (void) CloneString(&image_info->density,argv[1]);
668 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
669 break;
670 }
671 if (LocaleCompare("depth",argv[0]+1) == 0)
672 {
673 if (*argv[0] == '+')
674 {
675 image_info->depth=MAGICKCORE_QUANTUM_DEPTH;
676 break;
677 }
678 image_info->depth=StringToUnsignedLong(argv[1]);
679 break;
680 }
681 if (LocaleCompare("direction",argv[0]+1) == 0)
682 {
683 if (*argv[0] == '+')
684 {
685 (void) SetImageOption(image_info,argv[0]+1,"undefined");
686 break;
687 }
688 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
689 break;
690 }
691 if (LocaleCompare("display",argv[0]+1) == 0)
692 {
693 if (*argv[0] == '+')
694 {
695 if (image_info->server_name != (char *) NULL)
696 image_info->server_name=DestroyString(
697 image_info->server_name);
698 break;
699 }
700 (void) CloneString(&image_info->server_name,argv[1]);
701 break;
702 }
703 if (LocaleCompare("dispose",argv[0]+1) == 0)
704 {
705 if (*argv[0] == '+')
706 {
707 (void) SetImageOption(image_info,argv[0]+1,"undefined");
708 break;
709 }
710 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
711 break;
712 }
713 if (LocaleCompare("dither",argv[0]+1) == 0)
714 {
715 if (*argv[0] == '+')
716 {
717 image_info->dither=MagickFalse;
718 (void) SetImageOption(image_info,argv[0]+1,"none");
719 break;
720 }
721 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
722 image_info->dither=MagickTrue;
723 break;
724 }
725 break;
726 }
727 case 'e':
728 {
729 if (LocaleCompare("encoding",argv[0]+1) == 0)
730 {
731 if (*argv[0] == '+')
732 {
733 (void) SetImageOption(image_info,argv[0]+1,"undefined");
734 break;
735 }
736 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
737 break;
738 }
739 if (LocaleCompare("endian",argv[0]+1) == 0)
740 {
741 if (*argv[0] == '+')
742 {
743 image_info->endian=UndefinedEndian;
744 (void) SetImageOption(image_info,argv[0]+1,"undefined");
745 break;
746 }
747 image_info->endian=(EndianType) ParseCommandOption(
748 MagickEndianOptions,MagickFalse,argv[1]);
749 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
750 break;
751 }
752 if (LocaleCompare("extract",argv[0]+1) == 0)
753 {
754 /*
755 Set image extract geometry.
756 */
757 if (*argv[0] == '+')
758 {
759 if (image_info->extract != (char *) NULL)
760 image_info->extract=DestroyString(image_info->extract);
761 break;
762 }
763 (void) CloneString(&image_info->extract,argv[1]);
764 break;
765 }
766 break;
767 }
768 case 'f':
769 {
770 if (LocaleCompare("fill",argv[0]+1) == 0)
771 {
772 if (*argv[0] == '+')
773 {
774 (void) SetImageOption(image_info,argv[0]+1,"none");
775 break;
776 }
777 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
778 break;
779 }
780 if (LocaleCompare("filter",argv[0]+1) == 0)
781 {
782 if (*argv[0] == '+')
783 {
784 (void) SetImageOption(image_info,argv[0]+1,"undefined");
785 break;
786 }
787 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
788 break;
789 }
790 if (LocaleCompare("font",argv[0]+1) == 0)
791 {
792 if (*argv[0] == '+')
793 {
794 if (image_info->font != (char *) NULL)
795 image_info->font=DestroyString(image_info->font);
796 break;
797 }
798 (void) CloneString(&image_info->font,argv[1]);
799 break;
800 }
801 if (LocaleCompare("format",argv[0]+1) == 0)
802 {
803 register const char
804 *q;
805
806 for (q=strchr(argv[1],'%'); q != (char *) NULL; q=strchr(q+1,'%'))
807 if (strchr("Agkrz@[#",*(q+1)) != (char *) NULL)
808 image_info->ping=MagickFalse;
809 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
810 break;
811 }
812 if (LocaleCompare("fuzz",argv[0]+1) == 0)
813 {
814 if (*argv[0] == '+')
815 {
816 image_info->fuzz=0.0;
817 (void) SetImageOption(image_info,argv[0]+1,"0");
818 break;
819 }
820 image_info->fuzz=SiPrefixToDouble(argv[1],(double) QuantumRange+
821 1.0);
822 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
823 break;
824 }
825 break;
826 }
827 case 'g':
828 {
829 if (LocaleCompare("gravity",argv[0]+1) == 0)
830 {
831 if (*argv[0] == '+')
832 {
833 (void) SetImageOption(image_info,argv[0]+1,"undefined");
834 break;
835 }
836 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
837 break;
838 }
839 if (LocaleCompare("green-primary",argv[0]+1) == 0)
840 {
841 if (*argv[0] == '+')
842 {
843 (void) SetImageOption(image_info,argv[0]+1,"0.0");
844 break;
845 }
846 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
847 break;
848 }
849 break;
850 }
851 case 'i':
852 {
853 if (LocaleCompare("intent",argv[0]+1) == 0)
854 {
855 if (*argv[0] == '+')
856 {
857 (void) SetImageOption(image_info,argv[0]+1,"undefined");
858 break;
859 }
860 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
861 break;
862 }
863 if (LocaleCompare("interlace",argv[0]+1) == 0)
864 {
865 if (*argv[0] == '+')
866 {
867 image_info->interlace=UndefinedInterlace;
868 (void) SetImageOption(image_info,argv[0]+1,"undefined");
869 break;
870 }
871 image_info->interlace=(InterlaceType) ParseCommandOption(
872 MagickInterlaceOptions,MagickFalse,argv[1]);
873 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
874 break;
875 }
876 if (LocaleCompare("interline-spacing",argv[0]+1) == 0)
877 {
878 if (*argv[0] == '+')
879 {
880 (void) SetImageOption(image_info,argv[0]+1,"undefined");
881 break;
882 }
883 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
884 break;
885 }
886 if (LocaleCompare("interpolate",argv[0]+1) == 0)
887 {
888 if (*argv[0] == '+')
889 {
890 (void) SetImageOption(image_info,argv[0]+1,"undefined");
891 break;
892 }
893 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
894 break;
895 }
896 if (LocaleCompare("interword-spacing",argv[0]+1) == 0)
897 {
898 if (*argv[0] == '+')
899 {
900 (void) SetImageOption(image_info,argv[0]+1,"undefined");
901 break;
902 }
903 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
904 break;
905 }
906 break;
907 }
908 case 'k':
909 {
910 if (LocaleCompare("kerning",argv[0]+1) == 0)
911 {
912 if (*argv[0] == '+')
913 {
914 (void) SetImageOption(image_info,argv[0]+1,"undefined");
915 break;
916 }
917 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
918 break;
919 }
920 break;
921 }
922 case 'l':
923 {
924 if (LocaleCompare("label",argv[0]+1) == 0)
925 {
926 if (*argv[0] == '+')
927 {
928 (void) DeleteImageOption(image_info,argv[0]+1);
929 break;
930 }
931 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
932 break;
933 }
934 if (LocaleCompare("limit",argv[0]+1) == 0)
935 {
936 MagickSizeType
937 limit;
938
939 ResourceType
940 type;
941
942 if (*argv[0] == '+')
943 break;
944 type=(ResourceType) ParseCommandOption(MagickResourceOptions,
945 MagickFalse,argv[1]);
946 limit=MagickResourceInfinity;
947 if (LocaleCompare("unlimited",argv[2]) != 0)
948 limit=(MagickSizeType) SiPrefixToDouble(argv[2],100.0);
949 (void) SetMagickResourceLimit(type,limit);
950 break;
951 }
952 if (LocaleCompare("list",argv[0]+1) == 0)
953 {
954 ssize_t
955 list;
956
957 /*
958 Display configuration list.
959 */
960 list=ParseCommandOption(MagickListOptions,MagickFalse,argv[1]);
961 switch (list)
962 {
963 case MagickCoderOptions:
964 {
965 (void) ListCoderInfo((FILE *) NULL,exception);
966 break;
967 }
968 case MagickColorOptions:
969 {
970 (void) ListColorInfo((FILE *) NULL,exception);
971 break;
972 }
973 case MagickConfigureOptions:
974 {
975 (void) ListConfigureInfo((FILE *) NULL,exception);
976 break;
977 }
978 case MagickDelegateOptions:
979 {
980 (void) ListDelegateInfo((FILE *) NULL,exception);
981 break;
982 }
983 case MagickFontOptions:
984 {
985 (void) ListTypeInfo((FILE *) NULL,exception);
986 break;
987 }
988 case MagickFormatOptions:
989 {
990 (void) ListMagickInfo((FILE *) NULL,exception);
991 break;
992 }
993 case MagickLocaleOptions:
994 {
995 (void) ListLocaleInfo((FILE *) NULL,exception);
996 break;
997 }
998 case MagickLogOptions:
999 {
1000 (void) ListLogInfo((FILE *) NULL,exception);
1001 break;
1002 }
1003 case MagickMagicOptions:
1004 {
1005 (void) ListMagicInfo((FILE *) NULL,exception);
1006 break;
1007 }
1008 case MagickMimeOptions:
1009 {
1010 (void) ListMimeInfo((FILE *) NULL,exception);
1011 break;
1012 }
1013 case MagickModuleOptions:
1014 {
1015 (void) ListModuleInfo((FILE *) NULL,exception);
1016 break;
1017 }
1018 case MagickPolicyOptions:
1019 {
1020 (void) ListPolicyInfo((FILE *) NULL,exception);
1021 break;
1022 }
1023 case MagickResourceOptions:
1024 {
1025 (void) ListMagickResourceInfo((FILE *) NULL,exception);
1026 break;
1027 }
1028 case MagickThresholdOptions:
1029 {
1030 (void) ListThresholdMaps((FILE *) NULL,exception);
1031 break;
1032 }
1033 default:
1034 {
1035 (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
1036 exception);
1037 break;
1038 }
1039 }
1040 break;
1041 }
1042 if (LocaleCompare("log",argv[0]+1) == 0)
1043 {
1044 if (*argv[0] == '+')
1045 break;
1046 (void) SetLogFormat(argv[1]);
1047 break;
1048 }
1049 if (LocaleCompare("loop",argv[0]+1) == 0)
1050 {
1051 if (*argv[0] == '+')
1052 {
1053 (void) SetImageOption(image_info,argv[0]+1,"0");
1054 break;
1055 }
1056 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1057 break;
1058 }
1059 break;
1060 }
1061 case 'm':
1062 {
1063 if (LocaleCompare("matte",argv[0]+1) == 0)
1064 {
1065 if (*argv[0] == '+')
1066 {
1067 (void) SetImageOption(image_info,argv[0]+1,"false");
1068 break;
1069 }
1070 (void) SetImageOption(image_info,argv[0]+1,"true");
1071 break;
1072 }
1073 if (LocaleCompare("mattecolor",argv[0]+1) == 0)
1074 {
1075 if (*argv[0] == '+')
1076 {
1077 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1078 (void) QueryColorDatabase(MatteColor,&image_info->matte_color,
1079 exception);
1080 break;
1081 }
1082 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1083 (void) QueryColorDatabase(argv[1],&image_info->matte_color,
1084 exception);
1085 break;
1086 }
1087 if (LocaleCompare("monitor",argv[0]+1) == 0)
1088 {
1089 (void) SetImageInfoProgressMonitor(image_info,MonitorProgress,
1090 (void *) NULL);
1091 break;
1092 }
1093 if (LocaleCompare("monochrome",argv[0]+1) == 0)
1094 {
1095 image_info->monochrome=(*argv[0] == '-') ? MagickTrue : MagickFalse;
1096 break;
1097 }
1098 break;
1099 }
1100 case 'o':
1101 {
1102 if (LocaleCompare("orient",argv[0]+1) == 0)
1103 {
1104 if (*argv[0] == '+')
1105 {
1106 image_info->orientation=UndefinedOrientation;
1107 (void) SetImageOption(image_info,argv[0]+1,"undefined");
1108 break;
1109 }
1110 image_info->orientation=(OrientationType) ParseCommandOption(
1111 MagickOrientationOptions,MagickFalse,argv[1]);
1112 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1113 break;
1114 }
1115 }
1116 case 'p':
1117 {
1118 if (LocaleCompare("page",argv[0]+1) == 0)
1119 {
1120 char
1121 *canonical_page,
1122 page[MaxTextExtent];
1123
1124 const char
1125 *image_option;
1126
1127 MagickStatusType
1128 flags;
1129
1130 RectangleInfo
1131 geometry;
1132
1133 if (*argv[0] == '+')
1134 {
1135 (void) DeleteImageOption(image_info,argv[0]+1);
1136 (void) CloneString(&image_info->page,(char *) NULL);
1137 break;
1138 }
1139 (void) ResetMagickMemory(&geometry,0,sizeof(geometry));
1140 image_option=GetImageOption(image_info,"page");
1141 if (image_option != (const char *) NULL)
1142 flags=ParseAbsoluteGeometry(image_option,&geometry);
1143 canonical_page=GetPageGeometry(argv[1]);
1144 flags=ParseAbsoluteGeometry(canonical_page,&geometry);
1145 canonical_page=DestroyString(canonical_page);
1146 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu",
1147 (unsigned long) geometry.width,(unsigned long) geometry.height);
1148 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
1149 (void) FormatLocaleString(page,MaxTextExtent,"%lux%lu%+ld%+ld",
1150 (unsigned long) geometry.width,(unsigned long) geometry.height,
1151 (long) geometry.x,(long) geometry.y);
1152 (void) SetImageOption(image_info,argv[0]+1,page);
1153 (void) CloneString(&image_info->page,page);
1154 break;
1155 }
1156 if (LocaleCompare("pen",argv[0]+1) == 0)
1157 {
1158 if (*argv[0] == '+')
1159 {
1160 (void) SetImageOption(image_info,argv[0]+1,"none");
1161 break;
1162 }
1163 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1164 break;
1165 }
1166 if (LocaleCompare("ping",argv[0]+1) == 0)
1167 {
1168 image_info->ping=(*argv[0] == '-') ? MagickTrue : MagickFalse;
1169 break;
1170 }
1171 if (LocaleCompare("pointsize",argv[0]+1) == 0)
1172 {
1173 if (*argv[0] == '+')
1174 geometry_info.rho=0.0;
1175 else
1176 (void) ParseGeometry(argv[1],&geometry_info);
1177 image_info->pointsize=geometry_info.rho;
1178 break;
1179 }
1180 if (LocaleCompare("precision",argv[0]+1) == 0)
1181 {
1182 (void) SetMagickPrecision(StringToInteger(argv[1]));
1183 break;
1184 }
1185 if (LocaleCompare("preview",argv[0]+1) == 0)
1186 {
1187 /*
1188 Preview image.
1189 */
1190 if (*argv[0] == '+')
1191 {
1192 image_info->preview_type=UndefinedPreview;
1193 break;
1194 }
1195 image_info->preview_type=(PreviewType) ParseCommandOption(
1196 MagickPreviewOptions,MagickFalse,argv[1]);
1197 break;
1198 }
1199 break;
1200 }
1201 case 'q':
1202 {
1203 if (LocaleCompare("quality",argv[0]+1) == 0)
1204 {
1205 /*
1206 Set image compression quality.
1207 */
1208 if (*argv[0] == '+')
1209 {
1210 image_info->quality=UndefinedCompressionQuality;
1211 (void) SetImageOption(image_info,argv[0]+1,"0");
1212 break;
1213 }
1214 image_info->quality=StringToUnsignedLong(argv[1]);
1215 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1216 break;
1217 }
1218 if (LocaleCompare("quiet",argv[0]+1) == 0)
1219 {
1220 static WarningHandler
1221 warning_handler = (WarningHandler) NULL;
1222
1223 if (*argv[0] == '+')
1224 {
1225 /*
1226 Restore error or warning messages.
1227 */
1228 warning_handler=SetWarningHandler(warning_handler);
1229 break;
1230 }
1231 /*
1232 Suppress error or warning messages.
1233 */
1234 warning_handler=SetWarningHandler((WarningHandler) NULL);
1235 break;
1236 }
1237 break;
1238 }
1239 case 'r':
1240 {
1241 if (LocaleCompare("red-primary",argv[0]+1) == 0)
1242 {
1243 if (*argv[0] == '+')
1244 {
1245 (void) SetImageOption(image_info,argv[0]+1,"0.0");
1246 break;
1247 }
1248 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1249 break;
1250 }
1251 break;
1252 }
1253 case 's':
1254 {
1255 if (LocaleCompare("sampling-factor",argv[0]+1) == 0)
1256 {
1257 /*
1258 Set image sampling factor.
1259 */
1260 if (*argv[0] == '+')
1261 {
1262 if (image_info->sampling_factor != (char *) NULL)
1263 image_info->sampling_factor=DestroyString(
1264 image_info->sampling_factor);
1265 break;
1266 }
1267 (void) CloneString(&image_info->sampling_factor,argv[1]);
1268 break;
1269 }
1270 if (LocaleCompare("scene",argv[0]+1) == 0)
1271 {
1272 /*
1273 Set image scene.
1274 */
1275 if (*argv[0] == '+')
1276 {
1277 image_info->scene=0;
1278 (void) SetImageOption(image_info,argv[0]+1,"0");
1279 break;
1280 }
1281 image_info->scene=StringToUnsignedLong(argv[1]);
1282 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1283 break;
1284 }
1285 if (LocaleCompare("seed",argv[0]+1) == 0)
1286 {
1287 size_t
1288 seed;
1289
1290 if (*argv[0] == '+')
1291 {
1292 seed=(size_t) time((time_t *) NULL);
1293 SeedPseudoRandomGenerator(seed);
1294 break;
1295 }
1296 seed=StringToUnsignedLong(argv[1]);
1297 SeedPseudoRandomGenerator(seed);
1298 break;
1299 }
1300 if (LocaleCompare("size",argv[0]+1) == 0)
1301 {
1302 if (*argv[0] == '+')
1303 {
1304 if (image_info->size != (char *) NULL)
1305 image_info->size=DestroyString(image_info->size);
1306 break;
1307 }
1308 (void) CloneString(&image_info->size,argv[1]);
1309 break;
1310 }
1311 if (LocaleCompare("stroke",argv[0]+1) == 0)
1312 {
1313 if (*argv[0] == '+')
1314 {
1315 (void) SetImageOption(image_info,argv[0]+1,"none");
1316 break;
1317 }
1318 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1319 break;
1320 }
1321 if (LocaleCompare("strokewidth",argv[0]+1) == 0)
1322 {
1323 if (*argv[0] == '+')
1324 {
1325 (void) SetImageOption(image_info,argv[0]+1,"0");
1326 break;
1327 }
1328 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1329 break;
1330 }
1331 if (LocaleCompare("synchronize",argv[0]+1) == 0)
1332 {
1333 if (*argv[0] == '+')
1334 {
1335 image_info->synchronize=MagickFalse;
1336 break;
1337 }
1338 image_info->synchronize=MagickTrue;
1339 break;
1340 }
1341 break;
1342 }
1343 case 't':
1344 {
1345 if (LocaleCompare("taint",argv[0]+1) == 0)
1346 {
1347 if (*argv[0] == '+')
1348 {
1349 (void) SetImageOption(image_info,argv[0]+1,"false");
1350 break;
1351 }
1352 (void) SetImageOption(image_info,argv[0]+1,"true");
1353 break;
1354 }
1355 if (LocaleCompare("texture",argv[0]+1) == 0)
1356 {
1357 if (*argv[0] == '+')
1358 {
1359 if (image_info->texture != (char *) NULL)
1360 image_info->texture=DestroyString(image_info->texture);
1361 break;
1362 }
1363 (void) CloneString(&image_info->texture,argv[1]);
1364 break;
1365 }
1366 if (LocaleCompare("tile-offset",argv[0]+1) == 0)
1367 {
1368 if (*argv[0] == '+')
1369 {
1370 (void) SetImageOption(image_info,argv[0]+1,"0");
1371 break;
1372 }
1373 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1374 break;
1375 }
1376 if (LocaleCompare("transparent-color",argv[0]+1) == 0)
1377 {
1378 if (*argv[0] == '+')
1379 {
1380 (void) QueryColorDatabase("none",&image_info->transparent_color, exception);
1381 (void) SetImageOption(image_info,argv[0]+1,"none");
1382 break;
1383 }
1384 (void) QueryColorDatabase(argv[1],&image_info->transparent_color,
1385 exception);
1386 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1387 break;
1388 }
1389 if (LocaleCompare("type",argv[0]+1) == 0)
1390 {
1391 if (*argv[0] == '+')
1392 {
1393 image_info->type=UndefinedType;
1394 (void) SetImageOption(image_info,argv[0]+1,"undefined");
1395 break;
1396 }
1397 image_info->type=(ImageType) ParseCommandOption(MagickTypeOptions,
1398 MagickFalse,argv[1]);
1399 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1400 break;
1401 }
1402 break;
1403 }
1404 case 'u':
1405 {
1406 if (LocaleCompare("undercolor",argv[0]+1) == 0)
1407 {
1408 if (*argv[0] == '+')
1409 {
1410 (void) DeleteImageOption(image_info,argv[0]+1);
1411 break;
1412 }
1413 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1414 break;
1415 }
1416 if (LocaleCompare("units",argv[0]+1) == 0)
1417 {
1418 if (*argv[0] == '+')
1419 {
1420 image_info->units=UndefinedResolution;
1421 (void) SetImageOption(image_info,argv[0]+1,"undefined");
1422 break;
1423 }
1424 image_info->units=(ResolutionType) ParseCommandOption(
1425 MagickResolutionOptions,MagickFalse,argv[1]);
1426 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1427 break;
1428 }
1429 break;
1430 }
1431 case 'v':
1432 {
1433 if (LocaleCompare("verbose",argv[0]+1) == 0)
1434 {
1435 if (*argv[0] == '+')
1436 {
1437 image_info->verbose=MagickFalse;
1438 break;
1439 }
1440 image_info->verbose=MagickTrue;
1441 image_info->ping=MagickFalse;
1442 break;
1443 }
1444 if (LocaleCompare("view",argv[0]+1) == 0)
1445 {
1446 if (*argv[0] == '+')
1447 {
1448 if (image_info->view != (char *) NULL)
1449 image_info->view=DestroyString(image_info->view);
1450 break;
1451 }
1452 (void) CloneString(&image_info->view,argv[1]);
1453 break;
1454 }
1455 if (LocaleCompare("virtual-pixel",argv[0]+1) == 0)
1456 {
1457 if (*argv[0] == '+')
1458 {
1459 image_info->virtual_pixel_method=UndefinedVirtualPixelMethod;
1460 (void) SetImageOption(image_info,argv[0]+1,"undefined");
1461 break;
1462 }
1463 image_info->virtual_pixel_method=(VirtualPixelMethod)
1464 ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,argv[1]);
1465 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1466 break;
1467 }
1468 break;
1469 }
1470 case 'w':
1471 {
1472 if (LocaleCompare("white-point",argv[0]+1) == 0)
1473 {
1474 if (*argv[0] == '+')
1475 {
1476 (void) SetImageOption(image_info,argv[0]+1,"0.0");
1477 break;
1478 }
1479 (void) SetImageOption(image_info,argv[0]+1,argv[1]);
1480 break;
1481 }
1482 break;
1483 }
1484 default:
1485 break;
1486 }
1487 return(MagickTrue);
1488}
1489
1490/*
1491%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1492% %
1493% %
1494% %
1495+ S i m p l e O p e r a t i o n I m a g e %
1496% %
1497% %
1498% %
1499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1500%
1501% SimpleOperationImage() apply one simple operation on one image.
1502% The image however may be part of a longer list of images.
1503%
1504% The image in the list may be modified in three different ways...
1505%
1506% * directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
1507% * replaced by a new image (EG: -spread, -resize, -rotate, -morphology)
1508% * replace by a list of images (-separate and -crop only!)
1509%
1510% In each case the result is returned into the list, and the pointer to the
1511% modified image (last image added if replaced by a list of images) is
1512% returned. As the image pointed to may be replaced, the first image in the
1513% list may also change. GetFirstImageInList() should be used by caller if
1514% they wish return the Image pointer to the first image in list.
1515%
1516% The format of the SimpleOperationImage method is:
1517%
1518% MagickBooleanType SimpleOperationImage(ImageInfo *image_info,
1519% const int argc,const char **argv,Image **image)
1520%
1521% A description of each parameter follows:
1522%
1523% o image_info: the image info..
1524%
1525% o argc: Specifies a pointer to an integer describing the number of
1526% elements in the argument vector.
1527%
1528% o argv: Specifies a pointer to a text array containing the command line
1529% arguments.
1530%
1531% o image: the image.
1532%
1533% o exception: return any errors or warnings in this structure.
1534%
1535*/
1536MagickExport MagickBooleanType SimpleOperationImage(ImageInfo *image_info,
1537 const int wand_unused(argc), const char **argv,Image **image,
1538 ExceptionInfo *exception)
1539{
1540 Image *
1541 new_image;
1542
1543 ChannelType
1544 channel;
1545
1546 const char
1547 *format;
1548
1549 DrawInfo
1550 *draw_info;
1551
1552 GeometryInfo
1553 geometry_info;
1554
1555 RectangleInfo
1556 geometry;
1557
1558 MagickStatusType
1559 status;
1560
1561 PixelInfo
1562 fill;
1563
1564 MagickStatusType
1565 flags;
1566
1567 QuantizeInfo
1568 *quantize_info;
1569
1570 assert(image_info != (const ImageInfo *) NULL);
1571 assert(image_info->signature == MagickSignature);
1572 assert(image != (Image **) NULL);
1573 assert((*image)->signature == MagickSignature);
1574 if ((*image)->debug != MagickFalse)
1575 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1576
1577 draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
1578 quantize_info=AcquireQuantizeInfo(image_info);
1579 SetGeometryInfo(&geometry_info);
1580 GetPixelInfo(*image,&fill);
1581 SetPixelInfoPacket(*image,&(*image)->background_color,&fill);
1582 channel=image_info->channel;
1583 format=GetImageOption(image_info,"format");
1584
1585 new_image = (Image *)NULL;
1586
1587 switch (*(argv[0]+1))
1588 {
1589 case 'a':
1590 {
1591 if (LocaleCompare("adaptive-blur",argv[0]+1) == 0)
1592 {
1593 /*
1594 Adaptive blur image.
1595 */
1596 (void) SyncImageSettings(image_info,*image);
1597 flags=ParseGeometry(argv[1],&geometry_info);
1598 if ((flags & SigmaValue) == 0)
1599 geometry_info.sigma=1.0;
1600 if ((flags & XiValue) == 0)
1601 geometry_info.xi=0.0;
1602 new_image=AdaptiveBlurImage(*image,geometry_info.rho,
1603 geometry_info.sigma,geometry_info.xi,exception);
1604 break;
1605 }
1606 if (LocaleCompare("adaptive-resize",argv[0]+1) == 0)
1607 {
1608 /*
1609 Adaptive resize image.
1610 */
1611 (void) SyncImageSettings(image_info,*image);
1612 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
1613 new_image=AdaptiveResizeImage(*image,geometry.width,
1614 geometry.height,exception);
1615 break;
1616 }
1617 if (LocaleCompare("adaptive-sharpen",argv[0]+1) == 0)
1618 {
1619 /*
1620 Adaptive sharpen image.
1621 */
1622 (void) SyncImageSettings(image_info,*image);
1623 flags=ParseGeometry(argv[1],&geometry_info);
1624 if ((flags & SigmaValue) == 0)
1625 geometry_info.sigma=1.0;
1626 if ((flags & XiValue) == 0)
1627 geometry_info.xi=0.0;
1628 new_image=AdaptiveSharpenImage(*image,geometry_info.rho,
1629 geometry_info.sigma,geometry_info.xi,exception);
1630 break;
1631 }
1632 if (LocaleCompare("affine",argv[0]+1) == 0)
1633 {
1634 /*
1635 Affine matrix.
1636 */
1637 if (*argv[0] == '+')
1638 {
1639 GetAffineMatrix(&draw_info->affine);
1640 break;
1641 }
1642 (void) ParseAffineGeometry(argv[1],&draw_info->affine,exception);
1643 break;
1644 }
1645 if (LocaleCompare("alpha",argv[0]+1) == 0)
1646 {
1647 AlphaChannelType
1648 alpha_type;
1649
1650 (void) SyncImageSettings(image_info,*image);
1651 alpha_type=(AlphaChannelType) ParseCommandOption(MagickAlphaOptions,
1652 MagickFalse,argv[1]);
1653 (void) SetImageAlphaChannel(*image,alpha_type,exception);
1654 break;
1655 }
1656 if (LocaleCompare("annotate",argv[0]+1) == 0)
1657 {
1658 char
1659 *text,
1660 geometry[MaxTextExtent];
1661
1662 /*
1663 Annotate image.
1664 */
1665 (void) SyncImageSettings(image_info,*image);
1666 SetGeometryInfo(&geometry_info);
1667 flags=ParseGeometry(argv[1],&geometry_info);
1668 if ((flags & SigmaValue) == 0)
1669 geometry_info.sigma=geometry_info.rho;
1670 text=InterpretImageProperties(image_info,*image,argv[2],
1671 exception);
1672 if (text == (char *) NULL)
1673 break;
1674 (void) CloneString(&draw_info->text,text);
1675 text=DestroyString(text);
1676 (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
1677 geometry_info.xi,geometry_info.psi);
1678 (void) CloneString(&draw_info->geometry,geometry);
1679 draw_info->affine.sx=cos(DegreesToRadians(
1680 fmod(geometry_info.rho,360.0)));
1681 draw_info->affine.rx=sin(DegreesToRadians(
1682 fmod(geometry_info.rho,360.0)));
1683 draw_info->affine.ry=(-sin(DegreesToRadians(
1684 fmod(geometry_info.sigma,360.0))));
1685 draw_info->affine.sy=cos(DegreesToRadians(
1686 fmod(geometry_info.sigma,360.0)));
1687 (void) AnnotateImage(*image,draw_info,exception);
1688 break;
1689 }
1690 if (LocaleCompare("antialias",argv[0]+1) == 0)
1691 {
1692 draw_info->stroke_antialias=(*argv[0] == '-') ? MagickTrue :
1693 MagickFalse;
1694 draw_info->text_antialias=(*argv[0] == '-') ? MagickTrue :
1695 MagickFalse;
1696 break;
1697 }
1698 if (LocaleCompare("auto-gamma",argv[0]+1) == 0)
1699 {
1700 /*
1701 Auto Adjust Gamma of image based on its mean
1702 */
1703 (void) SyncImageSettings(image_info,*image);
1704 (void) AutoGammaImage(*image,exception);
1705 break;
1706 }
1707 if (LocaleCompare("auto-level",argv[0]+1) == 0)
1708 {
1709 /*
1710 Perfectly Normalize (max/min stretch) the image
1711 */
1712 (void) SyncImageSettings(image_info,*image);
1713 (void) AutoLevelImage(*image,exception);
1714 break;
1715 }
1716 if (LocaleCompare("auto-orient",argv[0]+1) == 0)
1717 {
1718 (void) SyncImageSettings(image_info,*image);
1719 switch ((*image)->orientation)
1720 {
1721 case TopRightOrientation:
1722 {
1723 new_image=FlopImage(*image,exception);
1724 break;
1725 }
1726 case BottomRightOrientation:
1727 {
1728 new_image=RotateImage(*image,180.0,exception);
1729 break;
1730 }
1731 case BottomLeftOrientation:
1732 {
1733 new_image=FlipImage(*image,exception);
1734 break;
1735 }
1736 case LeftTopOrientation:
1737 {
1738 new_image=TransposeImage(*image,exception);
1739 break;
1740 }
1741 case RightTopOrientation:
1742 {
1743 new_image=RotateImage(*image,90.0,exception);
1744 break;
1745 }
1746 case RightBottomOrientation:
1747 {
1748 new_image=TransverseImage(*image,exception);
1749 break;
1750 }
1751 case LeftBottomOrientation:
1752 {
1753 new_image=RotateImage(*image,270.0,exception);
1754 break;
1755 }
1756 default:
1757 break;
1758 }
1759 if (new_image != (Image *) NULL)
1760 new_image->orientation=TopLeftOrientation;
1761 break;
1762 }
1763 break;
1764 }
1765 case 'b':
1766 {
1767 if (LocaleCompare("black-threshold",argv[0]+1) == 0)
1768 {
1769 /*
1770 Black threshold image.
1771 */
1772 (void) SyncImageSettings(image_info,*image);
1773 (void) BlackThresholdImage(*image,argv[1],exception);
1774 InheritException(exception,&(*image)->exception);
1775 break;
1776 }
1777 if (LocaleCompare("blue-shift",argv[0]+1) == 0)
1778 {
1779 /*
1780 Blue shift image.
1781 */
1782 (void) SyncImageSettings(image_info,*image);
1783 geometry_info.rho=1.5;
1784 if (*argv[0] == '-')
1785 flags=ParseGeometry(argv[1],&geometry_info);
1786 new_image=BlueShiftImage(*image,geometry_info.rho,exception);
1787 break;
1788 }
1789 if (LocaleCompare("blur",argv[0]+1) == 0)
1790 {
1791 /*
1792 Two pass gaussian blur of image.
1793 */
1794 (void) SyncImageSettings(image_info,*image);
1795 flags=ParseGeometry(argv[1],&geometry_info);
1796 if ((flags & SigmaValue) == 0)
1797 geometry_info.sigma=1.0;
1798 if ((flags & XiValue) == 0)
1799 geometry_info.xi=0.0;
1800 new_image=BlurImage(*image,geometry_info.rho,
1801 geometry_info.sigma,geometry_info.xi,exception);
1802 break;
1803 }
1804 if (LocaleCompare("border",argv[0]+1) == 0)
1805 {
1806 /*
1807 Surround image with a border of solid color.
1808 */
1809 (void) SyncImageSettings(image_info,*image);
1810 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
1811 if ((flags & SigmaValue) == 0)
1812 geometry.height=geometry.width;
1813 new_image=BorderImage(*image,&geometry,exception);
1814 break;
1815 }
1816 if (LocaleCompare("bordercolor",argv[0]+1) == 0)
1817 {
1818 if (*argv[0] == '+')
1819 {
1820 (void) QueryColorDatabase(BorderColor,&draw_info->border_color,
1821 exception);
1822 break;
1823 }
1824 (void) QueryColorDatabase(argv[1],&draw_info->border_color,
1825 exception);
1826 break;
1827 }
1828 if (LocaleCompare("box",argv[0]+1) == 0)
1829 {
1830 (void) QueryColorDatabase(argv[1],&draw_info->undercolor,
1831 exception);
1832 break;
1833 }
1834 if (LocaleCompare("brightness-contrast",argv[0]+1) == 0)
1835 {
1836 double
1837 brightness,
1838 contrast;
1839
1840 GeometryInfo
1841 geometry_info;
1842
1843 MagickStatusType
1844 flags;
1845
1846 /*
1847 Brightness / contrast image.
1848 */
1849 (void) SyncImageSettings(image_info,*image);
1850 flags=ParseGeometry(argv[1],&geometry_info);
1851 brightness=geometry_info.rho;
1852 contrast=0.0;
1853 if ((flags & SigmaValue) != 0)
1854 contrast=geometry_info.sigma;
1855 (void) BrightnessContrastImage(*image,brightness,contrast,
1856 exception);
1857 InheritException(exception,&(*image)->exception);
1858 break;
1859 }
1860 break;
1861 }
1862 case 'c':
1863 {
1864 if (LocaleCompare("cdl",argv[0]+1) == 0)
1865 {
1866 char
1867 *color_correction_collection;
1868
1869 /*
1870 Color correct with a color decision list.
1871 */
1872 (void) SyncImageSettings(image_info,*image);
1873 color_correction_collection=FileToString(argv[1],~0,exception);
1874 if (color_correction_collection == (char *) NULL)
1875 break;
1876 (void) ColorDecisionListImage(*image,color_correction_collection,
1877 exception);
1878 InheritException(exception,&(*image)->exception);
1879 break;
1880 }
1881 if (LocaleCompare("channel",argv[0]+1) == 0)
1882 {
1883 if (*argv[0] == '+')
1884 channel=DefaultChannels;
1885 else
1886 channel=(ChannelType) ParseChannelOption(argv[1]);
1887 SetPixelChannelMap(*image,channel);
1888 break;
1889 }
1890 if (LocaleCompare("charcoal",argv[0]+1) == 0)
1891 {
1892 /*
1893 Charcoal image.
1894 */
1895 (void) SyncImageSettings(image_info,*image);
1896 flags=ParseGeometry(argv[1],&geometry_info);
1897 if ((flags & SigmaValue) == 0)
1898 geometry_info.sigma=1.0;
1899 if ((flags & XiValue) == 0)
1900 geometry_info.xi=1.0;
1901 new_image=CharcoalImage(*image,geometry_info.rho,
1902 geometry_info.sigma,geometry_info.xi,exception);
1903 break;
1904 }
1905 if (LocaleCompare("chop",argv[0]+1) == 0)
1906 {
1907 /*
1908 Chop the image.
1909 */
1910 (void) SyncImageSettings(image_info,*image);
1911 (void) ParseGravityGeometry(*image,argv[1],&geometry,exception);
1912 new_image=ChopImage(*image,&geometry,exception);
1913 break;
1914 }
1915 if (LocaleCompare("clamp",argv[0]+1) == 0)
1916 {
1917 /*
1918 Clamp image.
1919 */
1920 (void) SyncImageSettings(image_info,*image);
1921 (void) ClampImage(*image);
1922 InheritException(exception,&(*image)->exception);
1923 break;
1924 }
1925 if (LocaleCompare("clip",argv[0]+1) == 0)
1926 {
1927 (void) SyncImageSettings(image_info,*image);
1928 if (*argv[0] == '+')
1929 {
1930 (void) SetImageClipMask(*image,(Image *) NULL,exception);
1931 break;
1932 }
1933 (void) ClipImage(*image,exception);
1934 break;
1935 }
1936 if (LocaleCompare("clip-mask",argv[0]+1) == 0)
1937 {
1938 CacheView
1939 *mask_view;
1940
1941 Image
1942 *mask_image;
1943
1944 register Quantum
1945 *restrict q;
1946
1947 register ssize_t
1948 x;
1949
1950 ssize_t
1951 y;
1952
1953 (void) SyncImageSettings(image_info,*image);
1954 if (*argv[0] == '+')
1955 {
1956 /*
1957 Remove a mask.
1958 */
1959 (void) SetImageMask(*image,(Image *) NULL,exception);
1960 break;
1961 }
1962 mask_image=GetImageCache(image_info,argv[1],exception);
1963 if (mask_image == (Image *) NULL)
1964 break;
1965 if (SetImageStorageClass(mask_image,DirectClass,exception) == MagickFalse)
1966 return(MagickFalse);
1967 mask_view=AcquireCacheView(mask_image);
1968 for (y=0; y < (ssize_t) mask_image->rows; y++)
1969 {
1970 q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1971 exception);
1972 if (q == (Quantum *) NULL)
1973 break;
1974 for (x=0; x < (ssize_t) mask_image->columns; x++)
1975 {
1976 if (mask_image->matte == MagickFalse)
1977 SetPixelAlpha(mask_image,GetPixelIntensity(mask_image,q),q);
1978 SetPixelRed(mask_image,GetPixelAlpha(mask_image,q),q);
1979 SetPixelGreen(mask_image,GetPixelAlpha(mask_image,q),q);
1980 SetPixelBlue(mask_image,GetPixelAlpha(mask_image,q),q);
1981 q+=GetPixelChannels(mask_image);
1982 }
1983 if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1984 break;
1985 }
1986 mask_view=DestroyCacheView(mask_view);
1987 mask_image->matte=MagickTrue;
1988 (void) SetImageClipMask(*image,mask_image);
1989 mask_image=DestroyImage(mask_image);
1990 InheritException(exception,&(*image)->exception);
1991 break;
1992 }
1993 if (LocaleCompare("clip-path",argv[0]+1) == 0)
1994 {
1995 (void) SyncImageSettings(image_info,*image);
1996 (void) ClipImagePath(*image,argv[1],*argv[0] == '-' ? MagickTrue :
1997 MagickFalse,exception);
1998 break;
1999 }
2000 if (LocaleCompare("colorize",argv[0]+1) == 0)
2001 {
2002 /*
2003 Colorize the image.
2004 */
2005 (void) SyncImageSettings(image_info,*image);
2006 new_image=ColorizeImage(*image,argv[1],draw_info->fill,
2007 exception);
2008 break;
2009 }
2010 if (LocaleCompare("color-matrix",argv[0]+1) == 0)
2011 {
2012 KernelInfo
2013 *kernel;
2014
2015 (void) SyncImageSettings(image_info,*image);
2016 kernel=AcquireKernelInfo(argv[1]);
2017 if (kernel == (KernelInfo *) NULL)
2018 break;
2019 new_image=ColorMatrixImage(*image,kernel,exception);
2020 kernel=DestroyKernelInfo(kernel);
2021 break;
2022 }
2023 if (LocaleCompare("colors",argv[0]+1) == 0)
2024 {
2025 /*
2026 Reduce the number of colors in the image.
2027 */
2028 (void) SyncImageSettings(image_info,*image);
2029 quantize_info->number_colors=StringToUnsignedLong(argv[1]);
2030 if (quantize_info->number_colors == 0)
2031 break;
2032 if (((*image)->storage_class == DirectClass) ||
2033 (*image)->colors > quantize_info->number_colors)
2034 (void) QuantizeImage(quantize_info,*image,exception);
2035 else
2036 (void) CompressImageColormap(*image,exception);
2037 break;
2038 }
2039 if (LocaleCompare("colorspace",argv[0]+1) == 0)
2040 {
2041 ColorspaceType
2042 colorspace;
2043
2044 (void) SyncImageSettings(image_info,*image);
2045 if (*argv[0] == '+')
2046 {
2047 (void) TransformImageColorspace(*image,RGBColorspace);
2048 InheritException(exception,&(*image)->exception);
2049 break;
2050 }
2051 colorspace=(ColorspaceType) ParseCommandOption(
2052 MagickColorspaceOptions,MagickFalse,argv[1]);
2053 (void) TransformImageColorspace(*image,colorspace);
2054 InheritException(exception,&(*image)->exception);
2055 break;
2056 }
2057 if (LocaleCompare("contrast",argv[0]+1) == 0)
2058 {
2059 (void) SyncImageSettings(image_info,*image);
2060 (void) ContrastImage(*image,(*argv[0] == '-') ? MagickTrue :
2061 MagickFalse,exception);
2062 break;
2063 }
2064 if (LocaleCompare("contrast-stretch",argv[0]+1) == 0)
2065 {
2066 double
2067 black_point,
2068 white_point;
2069
2070 MagickStatusType
2071 flags;
2072
2073 /*
2074 Contrast stretch image.
2075 */
2076 (void) SyncImageSettings(image_info,*image);
2077 flags=ParseGeometry(argv[1],&geometry_info);
2078 black_point=geometry_info.rho;
2079 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
2080 black_point;
2081 if ((flags & PercentValue) != 0)
2082 {
2083 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
2084 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
2085 }
2086 white_point=(MagickRealType) (*image)->columns*(*image)->rows-
2087 white_point;
2088 (void) ContrastStretchImage(*image,black_point,white_point,
2089 exception);
2090 InheritException(exception,&(*image)->exception);
2091 break;
2092 }
2093 if (LocaleCompare("convolve",argv[0]+1) == 0)
2094 {
2095 KernelInfo
2096 *kernel_info;
2097
2098 (void) SyncImageSettings(image_info,*image);
2099 kernel_info=AcquireKernelInfo(argv[1]);
2100 if (kernel_info == (KernelInfo *) NULL)
2101 break;
2102 kernel_info->bias=(*image)->bias;
2103 new_image=ConvolveImage(*image,kernel_info,exception);
2104 kernel_info=DestroyKernelInfo(kernel_info);
2105 break;
2106 }
2107 if (LocaleCompare("crop",argv[0]+1) == 0)
2108 {
2109 /*
2110 Crop a image to a smaller size
2111 */
2112 (void) SyncImageSettings(image_info,*image);
2113 new_image=CropImageToTiles(*image,argv[1],exception);
2114 break;
2115 }
2116 if (LocaleCompare("cycle",argv[0]+1) == 0)
2117 {
2118 /*
2119 Cycle an image colormap.
2120 */
2121 (void) SyncImageSettings(image_info,*image);
2122 (void) CycleColormapImage(*image,(ssize_t) StringToLong(argv[1]),
2123 exception);
2124 break;
2125 }
2126 break;
2127 }
2128 case 'd':
2129 {
2130 if (LocaleCompare("decipher",argv[0]+1) == 0)
2131 {
2132 StringInfo
2133 *passkey;
2134
2135 /*
2136 Decipher pixels.
2137 */
2138 (void) SyncImageSettings(image_info,*image);
2139 passkey=FileToStringInfo(argv[1],~0,exception);
2140 if (passkey != (StringInfo *) NULL)
2141 {
2142 (void) PasskeyDecipherImage(*image,passkey,exception);
2143 passkey=DestroyStringInfo(passkey);
2144 }
2145 break;
2146 }
2147 if (LocaleCompare("density",argv[0]+1) == 0)
2148 {
2149 /*
2150 Set image density.
2151 */
2152 (void) CloneString(&draw_info->density,argv[1]);
2153 break;
2154 }
2155 if (LocaleCompare("depth",argv[0]+1) == 0)
2156 {
2157 (void) SyncImageSettings(image_info,*image);
2158 if (*argv[0] == '+')
2159 {
2160 (void) SetImageDepth(*image,MAGICKCORE_QUANTUM_DEPTH);
2161 break;
2162 }
2163 (void) SetImageDepth(*image,StringToUnsignedLong(argv[1]));
2164 break;
2165 }
2166 if (LocaleCompare("deskew",argv[0]+1) == 0)
2167 {
2168 double
2169 threshold;
2170
2171 /*
2172 Straighten the image.
2173 */
2174 (void) SyncImageSettings(image_info,*image);
2175 if (*argv[0] == '+')
2176 threshold=40.0*QuantumRange/100.0;
2177 else
2178 threshold=SiPrefixToDouble(argv[1],QuantumRange);
2179 new_image=DeskewImage(*image,threshold,exception);
2180 break;
2181 }
2182 if (LocaleCompare("despeckle",argv[0]+1) == 0)
2183 {
2184 /*
2185 Reduce the speckles within an image.
2186 */
2187 (void) SyncImageSettings(image_info,*image);
2188 new_image=DespeckleImage(*image,exception);
2189 break;
2190 }
2191 if (LocaleCompare("display",argv[0]+1) == 0)
2192 {
2193 (void) CloneString(&draw_info->server_name,argv[1]);
2194 break;
2195 }
2196 if (LocaleCompare("distort",argv[0]+1) == 0)
2197 {
2198 char
2199 *args,
2200 token[MaxTextExtent];
2201
2202 const char
2203 *p;
2204
2205 DistortImageMethod
2206 method;
2207
2208 double
2209 *arguments;
2210
2211 register ssize_t
2212 x;
2213
2214 size_t
2215 number_arguments;
2216
2217 /*
2218 Distort image.
2219 */
2220 (void) SyncImageSettings(image_info,*image);
2221 method=(DistortImageMethod) ParseCommandOption(MagickDistortOptions,
2222 MagickFalse,argv[1]);
2223 if ( method == ResizeDistortion )
2224 {
2225 /* Special Case - Argument is actually a resize geometry!
2226 ** Convert that to an appropriate distortion argument array.
2227 */
2228 double
2229 resize_args[2];
2230 (void) ParseRegionGeometry(*image,argv[2],&geometry,
2231 exception);
2232 resize_args[0]=(double)geometry.width;
2233 resize_args[1]=(double)geometry.height;
2234 new_image=DistortImage(*image,method,(size_t)2,
2235 resize_args,MagickTrue,exception);
2236 break;
2237 }
2238 args=InterpretImageProperties(image_info,*image,argv[2],
2239 exception);
2240 if (args == (char *) NULL)
2241 break;
2242 p=(char *) args;
2243 for (x=0; *p != '\0'; x++)
2244 {
2245 GetMagickToken(p,&p,token);
2246 if (*token == ',')
2247 GetMagickToken(p,&p,token);
2248 }
2249 number_arguments=(size_t) x;
2250 arguments=(double *) AcquireQuantumMemory(number_arguments,
2251 sizeof(*arguments));
2252 if (arguments == (double *) NULL)
2253 ThrowWandFatalException(ResourceLimitFatalError,
2254 "MemoryAllocationFailed",(*image)->filename);
2255 (void) ResetMagickMemory(arguments,0,number_arguments*
2256 sizeof(*arguments));
2257 p=(char *) args;
2258 for (x=0; (x < (ssize_t) number_arguments) && (*p != '\0'); x++)
2259 {
2260 GetMagickToken(p,&p,token);
2261 if (*token == ',')
2262 GetMagickToken(p,&p,token);
2263 arguments[x]=InterpretLocaleValue(token,(char **) NULL);
2264 }
2265 args=DestroyString(args);
2266 new_image=DistortImage(*image,method,number_arguments,arguments,
2267 (*argv[0] == '+') ? MagickTrue : MagickFalse,exception);
2268 arguments=(double *) RelinquishMagickMemory(arguments);
2269 break;
2270 }
2271 if (LocaleCompare("dither",argv[0]+1) == 0)
2272 {
2273 if (*argv[0] == '+')
2274 {
2275 quantize_info->dither=MagickFalse;
2276 break;
2277 }
2278 quantize_info->dither=MagickTrue;
2279 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
2280 MagickDitherOptions,MagickFalse,argv[1]);
2281 if (quantize_info->dither_method == NoDitherMethod)
2282 quantize_info->dither=MagickFalse;
2283 break;
2284 }
2285 if (LocaleCompare("draw",argv[0]+1) == 0)
2286 {
2287 /*
2288 Draw image.
2289 */
2290 (void) SyncImageSettings(image_info,*image);
2291 (void) CloneString(&draw_info->primitive,argv[1]);
2292 (void) DrawImage(*image,draw_info,exception);
2293 break;
2294 }
2295 break;
2296 }
2297 case 'e':
2298 {
2299 if (LocaleCompare("edge",argv[0]+1) == 0)
2300 {
2301 /*
2302 Enhance edges in the image.
2303 */
2304 (void) SyncImageSettings(image_info,*image);
2305 flags=ParseGeometry(argv[1],&geometry_info);
2306 if ((flags & SigmaValue) == 0)
2307 geometry_info.sigma=1.0;
2308 new_image=EdgeImage(*image,geometry_info.rho,
2309 geometry_info.sigma,exception);
2310 break;
2311 }
2312 if (LocaleCompare("emboss",argv[0]+1) == 0)
2313 {
2314 /*
2315 Gaussian embossen image.
2316 */
2317 (void) SyncImageSettings(image_info,*image);
2318 flags=ParseGeometry(argv[1],&geometry_info);
2319 if ((flags & SigmaValue) == 0)
2320 geometry_info.sigma=1.0;
2321 new_image=EmbossImage(*image,geometry_info.rho,
2322 geometry_info.sigma,exception);
2323 break;
2324 }
2325 if (LocaleCompare("encipher",argv[0]+1) == 0)
2326 {
2327 StringInfo
2328 *passkey;
2329
2330 /*
2331 Encipher pixels.
2332 */
2333 (void) SyncImageSettings(image_info,*image);
2334 passkey=FileToStringInfo(argv[1],~0,exception);
2335 if (passkey != (StringInfo *) NULL)
2336 {
2337 (void) PasskeyEncipherImage(*image,passkey,exception);
2338 passkey=DestroyStringInfo(passkey);
2339 }
2340 break;
2341 }
2342 if (LocaleCompare("encoding",argv[0]+1) == 0)
2343 {
2344 (void) CloneString(&draw_info->encoding,argv[1]);
2345 break;
2346 }
2347 if (LocaleCompare("enhance",argv[0]+1) == 0)
2348 {
2349 /*
2350 Enhance image.
2351 */
2352 (void) SyncImageSettings(image_info,*image);
2353 new_image=EnhanceImage(*image,exception);
2354 break;
2355 }
2356 if (LocaleCompare("equalize",argv[0]+1) == 0)
2357 {
2358 /*
2359 Equalize image.
2360 */
2361 (void) SyncImageSettings(image_info,*image);
2362 (void) EqualizeImage(*image,exception);
2363 break;
2364 }
2365 if (LocaleCompare("evaluate",argv[0]+1) == 0)
2366 {
2367 double
2368 constant;
2369
2370 MagickEvaluateOperator
2371 op;
2372
2373 (void) SyncImageSettings(image_info,*image);
2374 op=(MagickEvaluateOperator) ParseCommandOption(
2375 MagickEvaluateOptions,MagickFalse,argv[1]);
2376 constant=SiPrefixToDouble(argv[2],QuantumRange);
2377 (void) EvaluateImage(*image,op,constant,exception);
2378 break;
2379 }
2380 if (LocaleCompare("extent",argv[0]+1) == 0)
2381 {
2382 /*
2383 Set the image extent.
2384 */
2385 (void) SyncImageSettings(image_info,*image);
2386 flags=ParseGravityGeometry(*image,argv[1],&geometry,exception);
2387 if (geometry.width == 0)
2388 geometry.width=(*image)->columns;
2389 if (geometry.height == 0)
2390 geometry.height=(*image)->rows;
2391 new_image=ExtentImage(*image,&geometry,exception);
2392 break;
2393 }
2394 break;
2395 }
2396 case 'f':
2397 {
2398 if (LocaleCompare("family",argv[0]+1) == 0)
2399 {
2400 if (*argv[0] == '+')
2401 {
2402 if (draw_info->family != (char *) NULL)
2403 draw_info->family=DestroyString(draw_info->family);
2404 break;
2405 }
2406 (void) CloneString(&draw_info->family,argv[1]);
2407 break;
2408 }
2409 if (LocaleCompare("features",argv[0]+1) == 0)
2410 {
2411 if (*argv[0] == '+')
2412 {
2413 (void) DeleteImageArtifact(*image,"identify:features");
2414 break;
2415 }
2416 (void) SetImageArtifact(*image,"identify:features",argv[1]);
2417 break;
2418 }
2419 if (LocaleCompare("fill",argv[0]+1) == 0)
2420 {
2421 ExceptionInfo
2422 *sans;
2423
2424 GetPixelInfo(*image,&fill);
2425 if (*argv[0] == '+')
2426 {
2427 (void) QueryMagickColor("none",&fill,exception);
2428 (void) QueryColorDatabase("none",&draw_info->fill,exception);
2429 if (draw_info->fill_pattern != (Image *) NULL)
2430 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
2431 break;
2432 }
2433 sans=AcquireExceptionInfo();
2434 (void) QueryMagickColor(argv[1],&fill,sans);
2435 status=QueryColorDatabase(argv[1],&draw_info->fill,sans);
2436 sans=DestroyExceptionInfo(sans);
2437 if (status == MagickFalse)
2438 draw_info->fill_pattern=GetImageCache(image_info,argv[1],
2439 exception);
2440 break;
2441 }
2442 if (LocaleCompare("flip",argv[0]+1) == 0)
2443 {
2444 /*
2445 Flip image scanlines.
2446 */
2447 (void) SyncImageSettings(image_info,*image);
2448 new_image=FlipImage(*image,exception);
2449 break;
2450 }
2451 if (LocaleCompare("flop",argv[0]+1) == 0)
2452 {
2453 /*
2454 Flop image scanlines.
2455 */
2456 (void) SyncImageSettings(image_info,*image);
2457 new_image=FlopImage(*image,exception);
2458 break;
2459 }
2460 if (LocaleCompare("floodfill",argv[0]+1) == 0)
2461 {
2462 PixelInfo
2463 target;
2464
2465 /*
2466 Floodfill image.
2467 */
2468 (void) SyncImageSettings(image_info,*image);
2469 (void) ParsePageGeometry(*image,argv[1],&geometry,exception);
2470 (void) QueryMagickColor(argv[2],&target,exception);
2471 (void) FloodfillPaintImage(*image,draw_info,&target,geometry.x,
2472 geometry.y,*argv[0] == '-' ? MagickFalse : MagickTrue,exception);
2473 break;
2474 }
2475 if (LocaleCompare("font",argv[0]+1) == 0)
2476 {
2477 if (*argv[0] == '+')
2478 {
2479 if (draw_info->font != (char *) NULL)
2480 draw_info->font=DestroyString(draw_info->font);
2481 break;
2482 }
2483 (void) CloneString(&draw_info->font,argv[1]);
2484 break;
2485 }
2486 if (LocaleCompare("format",argv[0]+1) == 0)
2487 {
2488 format=argv[1];
2489 break;
2490 }
2491 if (LocaleCompare("frame",argv[0]+1) == 0)
2492 {
2493 FrameInfo
2494 frame_info;
2495
2496 /*
2497 Surround image with an ornamental border.
2498 */
2499 (void) SyncImageSettings(image_info,*image);
2500 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
2501 frame_info.width=geometry.width;
2502 frame_info.height=geometry.height;
2503 if ((flags & HeightValue) == 0)
2504 frame_info.height=geometry.width;
2505 frame_info.outer_bevel=geometry.x;
2506 frame_info.inner_bevel=geometry.y;
2507 frame_info.x=(ssize_t) frame_info.width;
2508 frame_info.y=(ssize_t) frame_info.height;
2509 frame_info.width=(*image)->columns+2*frame_info.width;
2510 frame_info.height=(*image)->rows+2*frame_info.height;
2511 new_image=FrameImage(*image,&frame_info,exception);
2512 break;
2513 }
2514 if (LocaleCompare("function",argv[0]+1) == 0)
2515 {
2516 char
2517 *arguments,
2518 token[MaxTextExtent];
2519
2520 const char
2521 *p;
2522
2523 double
2524 *parameters;
2525
2526 MagickFunction
2527 function;
2528
2529 register ssize_t
2530 x;
2531
2532 size_t
2533 number_parameters;
2534
2535 /*
2536 Function Modify Image Values
2537 */
2538 (void) SyncImageSettings(image_info,*image);
2539 function=(MagickFunction) ParseCommandOption(MagickFunctionOptions,
2540 MagickFalse,argv[1]);
2541 arguments=InterpretImageProperties(image_info,*image,argv[2],
2542 exception);
2543 if (arguments == (char *) NULL)
2544 break;
2545 p=(char *) arguments;
2546 for (x=0; *p != '\0'; x++)
2547 {
2548 GetMagickToken(p,&p,token);
2549 if (*token == ',')
2550 GetMagickToken(p,&p,token);
2551 }
2552 number_parameters=(size_t) x;
2553 parameters=(double *) AcquireQuantumMemory(number_parameters,
2554 sizeof(*parameters));
2555 if (parameters == (double *) NULL)
2556 ThrowWandFatalException(ResourceLimitFatalError,
2557 "MemoryAllocationFailed",(*image)->filename);
2558 (void) ResetMagickMemory(parameters,0,number_parameters*
2559 sizeof(*parameters));
2560 p=(char *) arguments;
2561 for (x=0; (x < (ssize_t) number_parameters) && (*p != '\0'); x++)
2562 {
2563 GetMagickToken(p,&p,token);
2564 if (*token == ',')
2565 GetMagickToken(p,&p,token);
2566 parameters[x]=InterpretLocaleValue(token,(char **) NULL);
2567 }
2568 arguments=DestroyString(arguments);
2569 (void) FunctionImage(*image,function,number_parameters,parameters,
2570 exception);
2571 parameters=(double *) RelinquishMagickMemory(parameters);
2572 break;
2573 }
2574 break;
2575 }
2576 case 'g':
2577 {
2578 if (LocaleCompare("gamma",argv[0]+1) == 0)
2579 {
2580 /*
2581 Gamma image.
2582 */
2583 (void) SyncImageSettings(image_info,*image);
2584 if (*argv[0] == '+')
2585 (*image)->gamma=InterpretLocaleValue(argv[1],(char **) NULL);
2586 else
2587 (void) GammaImage(*image,InterpretLocaleValue(argv[1],
2588 (char **) NULL),exception);
2589 break;
2590 }
2591 if ((LocaleCompare("gaussian-blur",argv[0]+1) == 0) ||
2592 (LocaleCompare("gaussian",argv[0]+1) == 0))
2593 {
2594 /*
2595 Gaussian blur image.
2596 */
2597 (void) SyncImageSettings(image_info,*image);
2598 flags=ParseGeometry(argv[1],&geometry_info);
2599 if ((flags & SigmaValue) == 0)
2600 geometry_info.sigma=1.0;
2601 if ((flags & XiValue) == 0)
2602 geometry_info.xi=0.0;
2603 new_image=GaussianBlurImage(*image,geometry_info.rho,
2604 geometry_info.sigma,geometry_info.xi,exception);
2605 break;
2606 }
2607 if (LocaleCompare("geometry",argv[0]+1) == 0)
2608 {
2609 /*
2610 Record Image offset, Resize last image.
2611 */
2612 (void) SyncImageSettings(image_info,*image);
2613 if (*argv[0] == '+')
2614 {
2615 if ((*image)->geometry != (char *) NULL)
2616 (*image)->geometry=DestroyString((*image)->geometry);
2617 break;
2618 }
2619 flags=ParseRegionGeometry(*image,argv[1],&geometry,exception);
2620 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
2621 (void) CloneString(&(*image)->geometry,argv[1]);
2622 else
2623 new_image=ResizeImage(*image,geometry.width,geometry.height,
2624 (*image)->filter,(*image)->blur,exception);
2625 break;
2626 }
2627 if (LocaleCompare("gravity",argv[0]+1) == 0)
2628 {
2629 if (*argv[0] == '+')
2630 {
2631 draw_info->gravity=UndefinedGravity;
2632 break;
2633 }
2634 draw_info->gravity=(GravityType) ParseCommandOption(
2635 MagickGravityOptions,MagickFalse,argv[1]);
2636 break;
2637 }
2638 break;
2639 }
2640 case 'h':
2641 {
2642 if (LocaleCompare("highlight-color",argv[0]+1) == 0)
2643 {
2644 (void) SetImageArtifact(*image,argv[0]+1,argv[1]);
2645 break;
2646 }
2647 break;
2648 }
2649 case 'i':
2650 {
2651 if (LocaleCompare("identify",argv[0]+1) == 0)
2652 {
2653 char
2654 *text;
2655
2656 (void) SyncImageSettings(image_info,*image);
2657 if (format == (char *) NULL)
2658 {
2659 (void) IdentifyImage(*image,stdout,image_info->verbose,
2660 exception);
2661 break;
2662 }
2663 text=InterpretImageProperties(image_info,*image,format,
2664 exception);
2665 if (text == (char *) NULL)
2666 break;
2667 (void) fputs(text,stdout);
2668 (void) fputc('\n',stdout);
2669 text=DestroyString(text);
2670 break;
2671 }
2672 if (LocaleCompare("implode",argv[0]+1) == 0)
2673 {
2674 /*
2675 Implode image.
2676 */
2677 (void) SyncImageSettings(image_info,*image);
2678 (void) ParseGeometry(argv[1],&geometry_info);
2679 new_image=ImplodeImage(*image,geometry_info.rho,exception);
2680 break;
2681 }
2682 if (LocaleCompare("interline-spacing",argv[0]+1) == 0)
2683 {
2684 if (*argv[0] == '+')
2685 (void) ParseGeometry("0",&geometry_info);
2686 else
2687 (void) ParseGeometry(argv[1],&geometry_info);
2688 draw_info->interline_spacing=geometry_info.rho;
2689 break;
2690 }
2691 if (LocaleCompare("interword-spacing",argv[0]+1) == 0)
2692 {
2693 if (*argv[0] == '+')
2694 (void) ParseGeometry("0",&geometry_info);
2695 else
2696 (void) ParseGeometry(argv[1],&geometry_info);
2697 draw_info->interword_spacing=geometry_info.rho;
2698 break;
2699 }
2700 break;
2701 }
2702 case 'k':
2703 {
2704 if (LocaleCompare("kerning",argv[0]+1) == 0)
2705 {
2706 if (*argv[0] == '+')
2707 (void) ParseGeometry("0",&geometry_info);
2708 else
2709 (void) ParseGeometry(argv[1],&geometry_info);
2710 draw_info->kerning=geometry_info.rho;
2711 break;
2712 }
2713 break;
2714 }
2715 case 'l':
2716 {
2717 if (LocaleCompare("lat",argv[0]+1) == 0)
2718 {
2719 /*
2720 Local adaptive threshold image.
2721 */
2722 (void) SyncImageSettings(image_info,*image);
2723 flags=ParseGeometry(argv[1],&geometry_info);
2724 if ((flags & PercentValue) != 0)
2725 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
2726 new_image=AdaptiveThresholdImage(*image,(size_t)
2727 geometry_info.rho,(size_t) geometry_info.sigma,(double)
2728 geometry_info.xi,exception);
2729 break;
2730 }
2731 if (LocaleCompare("level",argv[0]+1) == 0)
2732 {
2733 MagickRealType
2734 black_point,
2735 gamma,
2736 white_point;
2737
2738 MagickStatusType
2739 flags;
2740
2741 /*
2742 Parse levels.
2743 */
2744 (void) SyncImageSettings(image_info,*image);
2745 flags=ParseGeometry(argv[1],&geometry_info);
2746 black_point=geometry_info.rho;
2747 white_point=(MagickRealType) QuantumRange;
2748 if ((flags & SigmaValue) != 0)
2749 white_point=geometry_info.sigma;
2750 gamma=1.0;
2751 if ((flags & XiValue) != 0)
2752 gamma=geometry_info.xi;
2753 if ((flags & PercentValue) != 0)
2754 {
2755 black_point*=(MagickRealType) (QuantumRange/100.0);
2756 white_point*=(MagickRealType) (QuantumRange/100.0);
2757 }
2758 if ((flags & SigmaValue) == 0)
2759 white_point=(MagickRealType) QuantumRange-black_point;
2760 if ((*argv[0] == '+') || ((flags & AspectValue) != 0))
2761 (void) LevelizeImage(*image,black_point,white_point,gamma,
2762 exception);
2763 else
2764 (void) LevelImage(*image,black_point,white_point,gamma,
2765 exception);
2766 InheritException(exception,&(*image)->exception);
2767 break;
2768 }
2769 if (LocaleCompare("level-colors",argv[0]+1) == 0)
2770 {
2771 char
2772 token[MaxTextExtent];
2773
2774 const char
2775 *p;
2776
2777 PixelInfo
2778 black_point,
2779 white_point;
2780
2781 p=(const char *) argv[1];
2782 GetMagickToken(p,&p,token); /* get black point color */
2783 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2784 (void) QueryMagickColor(token,&black_point,exception);
2785 else
2786 (void) QueryMagickColor("#000000",&black_point,exception);
2787 if (isalpha((int) token[0]) || (token[0] == '#'))
2788 GetMagickToken(p,&p,token);
2789 if (*token == '\0')
2790 white_point=black_point; /* set everything to that color */
2791 else
2792 {
2793 if ((isalpha((int) *token) == 0) && ((*token == '#') == 0))
2794 GetMagickToken(p,&p,token); /* Get white point color. */
2795 if ((isalpha((int) *token) != 0) || ((*token == '#') != 0))
2796 (void) QueryMagickColor(token,&white_point,exception);
2797 else
2798 (void) QueryMagickColor("#ffffff",&white_point,exception);
2799 }
2800 (void) LevelImageColors(*image,&black_point,&white_point,
2801 *argv[0] == '+' ? MagickTrue : MagickFalse,exception);
2802 break;
2803 }
2804 if (LocaleCompare("linear-stretch",argv[0]+1) == 0)
2805 {
2806 double
2807 black_point,
2808 white_point;
2809
2810 MagickStatusType
2811 flags;
2812
2813 (void) SyncImageSettings(image_info,*image);
2814 flags=ParseGeometry(argv[1],&geometry_info);
2815 black_point=geometry_info.rho;
2816 white_point=(MagickRealType) (*image)->columns*(*image)->rows;
2817 if ((flags & SigmaValue) != 0)
2818 white_point=geometry_info.sigma;
2819 if ((flags & PercentValue) != 0)
2820 {
2821 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
2822 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
2823 }
2824 if ((flags & SigmaValue) == 0)
2825 white_point=(MagickRealType) (*image)->columns*(*image)->rows-
2826 black_point;
2827 (void) LinearStretchImage(*image,black_point,white_point,exception);
2828 InheritException(exception,&(*image)->exception);
2829 break;
2830 }
2831 if (LocaleCompare("linewidth",argv[0]+1) == 0)
2832 {
2833 draw_info->stroke_width=InterpretLocaleValue(argv[1],
2834 (char **) NULL);
2835 break;
2836 }
2837 if (LocaleCompare("liquid-rescale",argv[0]+1) == 0)
2838 {
2839 /*
2840 Liquid rescale image.
2841 */
2842 (void) SyncImageSettings(image_info,*image);
2843 flags=ParseRegionGeometry(*image,argv[1],&geometry,exception);
2844 if ((flags & XValue) == 0)
2845 geometry.x=1;
2846 if ((flags & YValue) == 0)
2847 geometry.y=0;
2848 new_image=LiquidRescaleImage(*image,geometry.width,
2849 geometry.height,1.0*geometry.x,1.0*geometry.y,exception);
2850 break;
2851 }
2852 if (LocaleCompare("lowlight-color",argv[0]+1) == 0)
2853 {
2854 (void) SetImageArtifact(*image,argv[0]+1,argv[1]);
2855 break;
2856 }
2857 break;
2858 }
2859 case 'm':
2860 {
2861 if (LocaleCompare("map",argv[0]+1) == 0)
2862 {
2863 Image
2864 *remap_image;
2865
2866 /*
2867 Transform image colors to match this set of colors.
2868 */
2869 (void) SyncImageSettings(image_info,*image);
2870 if (*argv[0] == '+')
2871 break;
2872 remap_image=GetImageCache(image_info,argv[1],exception);
2873 if (remap_image == (Image *) NULL)
2874 break;
2875 (void) RemapImage(quantize_info,*image,remap_image,exception);
2876 remap_image=DestroyImage(remap_image);
2877 break;
2878 }
2879 if (LocaleCompare("mask",argv[0]+1) == 0)
2880 {
2881 Image
2882 *mask;
2883
2884 (void) SyncImageSettings(image_info,*image);
2885 if (*argv[0] == '+')
2886 {
2887 /*
2888 Remove a mask.
2889 */
2890 (void) SetImageMask(*image,(Image *) NULL,exception);
2891 break;
2892 }
2893 /*
2894 Set the image mask.
2895 */
2896 mask=GetImageCache(image_info,argv[1],exception);
2897 if (mask == (Image *) NULL)
2898 break;
2899 (void) SetImageMask(*image,mask,exception);
2900 mask=DestroyImage(mask);
2901 break;
2902 }
2903 if (LocaleCompare("matte",argv[0]+1) == 0)
2904 {
2905 (void) SetImageAlphaChannel(*image,(*argv[0] == '-') ?
2906 SetAlphaChannel : DeactivateAlphaChannel,exception);
2907 break;
2908 }
2909 if (LocaleCompare("median",argv[0]+1) == 0)
2910 {
2911 /*
2912 Median filter image.
2913 */
2914 (void) SyncImageSettings(image_info,*image);
2915 flags=ParseGeometry(argv[1],&geometry_info);
2916 if ((flags & SigmaValue) == 0)
2917 geometry_info.sigma=geometry_info.rho;
2918 new_image=StatisticImage(*image,MedianStatistic,(size_t)
2919 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2920 break;
2921 }
2922 if (LocaleCompare("mode",argv[0]+1) == 0)
2923 {
2924 /*
2925 Mode image.
2926 */
2927 (void) SyncImageSettings(image_info,*image);
2928 flags=ParseGeometry(argv[1],&geometry_info);
2929 if ((flags & SigmaValue) == 0)
2930 geometry_info.sigma=geometry_info.rho;
2931 new_image=StatisticImage(*image,ModeStatistic,(size_t)
2932 geometry_info.rho,(size_t) geometry_info.sigma,exception);
2933 break;
2934 }
2935 if (LocaleCompare("modulate",argv[0]+1) == 0)
2936 {
2937 (void) SyncImageSettings(image_info,*image);
2938 (void) ModulateImage(*image,argv[1],exception);
2939 break;
2940 }
2941 if (LocaleCompare("monitor",argv[0]+1) == 0)
2942 {
2943 if (*argv[0] == '+')
2944 {
2945 (void) SetImageProgressMonitor(*image,
2946 (MagickProgressMonitor) NULL,(void *) NULL);
2947 break;
2948 }
2949 (void) SetImageProgressMonitor(*image,MonitorProgress,
2950 (void *) NULL);
2951 break;
2952 }
2953 if (LocaleCompare("monochrome",argv[0]+1) == 0)
2954 {
2955 (void) SyncImageSettings(image_info,*image);
2956 (void) SetImageType(*image,BilevelType,exception);
2957 break;
2958 }
2959 if (LocaleCompare("morphology",argv[0]+1) == 0)
2960 {
2961 char
2962 token[MaxTextExtent];
2963
2964 const char
2965 *p;
2966
2967 KernelInfo
2968 *kernel;
2969
2970 MorphologyMethod
2971 method;
2972
2973 ssize_t
2974 iterations;
2975
2976 /*
2977 Morphological Image Operation
2978 */
2979 (void) SyncImageSettings(image_info,*image);
2980 p=argv[1];
2981 GetMagickToken(p,&p,token);
2982 method=(MorphologyMethod) ParseCommandOption(
2983 MagickMorphologyOptions,MagickFalse,token);
2984 iterations=1L;
2985 GetMagickToken(p,&p,token);
2986 if ((*p == ':') || (*p == ','))
2987 GetMagickToken(p,&p,token);
2988 if ((*p != '\0'))
2989 iterations=(ssize_t) StringToLong(p);
2990 kernel=AcquireKernelInfo(argv[2]);
2991 if (kernel == (KernelInfo *) NULL)
2992 {
2993 (void) ThrowMagickException(exception,GetMagickModule(),
2994 OptionError,"UnabletoParseKernel","morphology");
2995 status=MagickFalse;
2996 break;
2997 }
2998 new_image=MorphologyImage(*image,method,iterations,kernel,
2999 exception);
3000 kernel=DestroyKernelInfo(kernel);
3001 break;
3002 }
3003 if (LocaleCompare("motion-blur",argv[0]+1) == 0)
3004 {
3005 /*
3006 Motion blur image.
3007 */
3008 (void) SyncImageSettings(image_info,*image);
3009 flags=ParseGeometry(argv[1],&geometry_info);
3010 if ((flags & SigmaValue) == 0)
3011 geometry_info.sigma=1.0;
3012 new_image=MotionBlurImage(*image,geometry_info.rho,
3013 geometry_info.sigma,geometry_info.xi,geometry_info.psi,
3014 exception);
3015 break;
3016 }
3017 break;
3018 }
3019 case 'n':
3020 {
3021 if (LocaleCompare("negate",argv[0]+1) == 0)
3022 {
3023 (void) SyncImageSettings(image_info,*image);
3024 (void) NegateImage(*image,*argv[0] == '+' ? MagickTrue :
3025 MagickFalse,exception);
3026 break;
3027 }
3028 if (LocaleCompare("noise",argv[0]+1) == 0)
3029 {
3030 (void) SyncImageSettings(image_info,*image);
3031 if (*argv[0] == '-')
3032 {
3033 flags=ParseGeometry(argv[1],&geometry_info);
3034 if ((flags & SigmaValue) == 0)
3035 geometry_info.sigma=geometry_info.rho;
3036 new_image=StatisticImage(*image,NonpeakStatistic,(size_t)
3037 geometry_info.rho,(size_t) geometry_info.sigma,exception);
3038 }
3039 else
3040 {
3041 NoiseType
3042 noise;
3043
3044 noise=(NoiseType) ParseCommandOption(MagickNoiseOptions,
3045 MagickFalse,argv[1]);
3046 new_image=AddNoiseImage(*image,noise,exception);
3047 }
3048 break;
3049 }
3050 if (LocaleCompare("normalize",argv[0]+1) == 0)
3051 {
3052 (void) SyncImageSettings(image_info,*image);
3053 (void) NormalizeImage(*image,exception);
3054 break;
3055 }
3056 break;
3057 }
3058 case 'o':
3059 {
3060 if (LocaleCompare("opaque",argv[0]+1) == 0)
3061 {
3062 PixelInfo
3063 target;
3064
3065 (void) SyncImageSettings(image_info,*image);
3066 (void) QueryMagickColor(argv[1],&target,exception);
3067 (void) OpaquePaintImage(*image,&target,&fill,*argv[0] == '-' ?
3068 MagickFalse : MagickTrue,exception);
3069 break;
3070 }
3071 if (LocaleCompare("ordered-dither",argv[0]+1) == 0)
3072 {
3073 (void) SyncImageSettings(image_info,*image);
3074 (void) OrderedPosterizeImage(*image,argv[1],exception);
3075 break;
3076 }
3077 break;
3078 }
3079 case 'p':
3080 {
3081 if (LocaleCompare("paint",argv[0]+1) == 0)
3082 {
3083 (void) SyncImageSettings(image_info,*image);
3084 (void) ParseGeometry(argv[1],&geometry_info);
3085 new_image=OilPaintImage(*image,geometry_info.rho,
3086 geometry_info.sigma,exception);
3087 break;
3088 }
3089 if (LocaleCompare("pen",argv[0]+1) == 0)
3090 {
3091 if (*argv[0] == '+')
3092 {
3093 (void) QueryColorDatabase("none",&draw_info->fill,exception);
3094 break;
3095 }
3096 (void) QueryColorDatabase(argv[1],&draw_info->fill,exception);
3097 break;
3098 }
3099 if (LocaleCompare("pointsize",argv[0]+1) == 0)
3100 {
3101 if (*argv[0] == '+')
3102 (void) ParseGeometry("12",&geometry_info);
3103 else
3104 (void) ParseGeometry(argv[1],&geometry_info);
3105 draw_info->pointsize=geometry_info.rho;
3106 break;
3107 }
3108 if (LocaleCompare("polaroid",argv[0]+1) == 0)
3109 {
3110 double
3111 angle;
3112
3113 RandomInfo
3114 *random_info;
3115
3116 /*
3117 Simulate a Polaroid picture.
3118 */
3119 (void) SyncImageSettings(image_info,*image);
3120 random_info=AcquireRandomInfo();
3121 angle=22.5*(GetPseudoRandomValue(random_info)-0.5);
3122 random_info=DestroyRandomInfo(random_info);
3123 if (*argv[0] == '-')
3124 {
3125 SetGeometryInfo(&geometry_info);
3126 flags=ParseGeometry(argv[1],&geometry_info);
3127 angle=geometry_info.rho;
3128 }
3129 new_image=PolaroidImage(*image,draw_info,angle,
3130 interpolate_method,exception);
3131 break;
3132 }
3133 if (LocaleCompare("posterize",argv[0]+1) == 0)
3134 {
3135 /*
3136 Posterize image.
3137 */
3138 (void) SyncImageSettings(image_info,*image);
3139 (void) PosterizeImage(*image,StringToUnsignedLong(argv[1]),
3140 quantize_info->dither,exception);
3141 break;
3142 }
3143 if (LocaleCompare("preview",argv[0]+1) == 0)
3144 {
3145 PreviewType
3146 preview_type;
3147
3148 /*
3149 Preview image.
3150 */
3151 (void) SyncImageSettings(image_info,*image);
3152 if (*argv[0] == '+')
3153 preview_type=UndefinedPreview;
3154 else
3155 preview_type=(PreviewType) ParseCommandOption(
3156 MagickPreviewOptions,MagickFalse,argv[1]);
3157 new_image=PreviewImage(*image,preview_type,exception);
3158 break;
3159 }
3160 if (LocaleCompare("profile",argv[0]+1) == 0)
3161 {
3162 const char
3163 *name;
3164
3165 const StringInfo
3166 *profile;
3167
3168 Image
3169 *profile_image;
3170
3171 ImageInfo
3172 *profile_info;
3173
3174 (void) SyncImageSettings(image_info,*image);
3175 if (*argv[0] == '+')
3176 {
3177 /*
3178 Remove a profile from the image.
3179 */
3180 (void) ProfileImage(*image,argv[1],(const unsigned char *)
3181 NULL,0,MagickTrue);
3182 InheritException(exception,&(*image)->exception);
3183 break;
3184 }
3185 /*
3186 Associate a profile with the image.
3187 */
3188 profile_info=CloneImageInfo(image_info);
3189 profile=GetImageProfile(*image,"iptc");
3190 if (profile != (StringInfo *) NULL)
3191 profile_info->profile=(void *) CloneStringInfo(profile);
3192 profile_image=GetImageCache(profile_info,argv[1],exception);
3193 profile_info=DestroyImageInfo(profile_info);
3194 if (profile_image == (Image *) NULL)
3195 {
3196 StringInfo
3197 *profile;
3198
3199 profile_info=CloneImageInfo(image_info);
3200 (void) CopyMagickString(profile_info->filename,argv[1],
3201 MaxTextExtent);
3202 profile=FileToStringInfo(profile_info->filename,~0UL,exception);
3203 if (profile != (StringInfo *) NULL)
3204 {
3205 (void) ProfileImage(*image,profile_info->magick,
3206 GetStringInfoDatum(profile),(size_t)
3207 GetStringInfoLength(profile),MagickFalse);
3208 profile=DestroyStringInfo(profile);
3209 }
3210 profile_info=DestroyImageInfo(profile_info);
3211 break;
3212 }
3213 ResetImageProfileIterator(profile_image);
3214 name=GetNextImageProfile(profile_image);
3215 while (name != (const char *) NULL)
3216 {
3217 profile=GetImageProfile(profile_image,name);
3218 if (profile != (StringInfo *) NULL)
3219 (void) ProfileImage(*image,name,GetStringInfoDatum(profile),
3220 (size_t) GetStringInfoLength(profile),MagickFalse);
3221 name=GetNextImageProfile(profile_image);
3222 }
3223 profile_image=DestroyImage(profile_image);
3224 break;
3225 }
3226 break;
3227 }
3228 case 'q':
3229 {
3230 if (LocaleCompare("quantize",argv[0]+1) == 0)
3231 {
3232 if (*argv[0] == '+')
3233 {
3234 quantize_info->colorspace=UndefinedColorspace;
3235 break;
3236 }
3237 quantize_info->colorspace=(ColorspaceType) ParseCommandOption(
3238 MagickColorspaceOptions,MagickFalse,argv[1]);
3239 break;
3240 }
3241 break;
3242 }
3243 case 'r':
3244 {
3245 if (LocaleCompare("radial-blur",argv[0]+1) == 0)
3246 {
3247 /*
3248 Radial blur image.
3249 */
3250 (void) SyncImageSettings(image_info,*image);
3251 flags=ParseGeometry(argv[1],&geometry_info);
3252 new_image=RadialBlurImage(*image,geometry_info.rho,
3253 geometry_info.sigma,exception);
3254 break;
3255 }
3256 if (LocaleCompare("raise",argv[0]+1) == 0)
3257 {
3258 /*
3259 Surround image with a raise of solid color.
3260 */
3261 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
3262 if ((flags & SigmaValue) == 0)
3263 geometry.height=geometry.width;
3264 (void) RaiseImage(*image,&geometry,*argv[0] == '-' ? MagickTrue :
3265 MagickFalse,exception);
3266 break;
3267 }
3268 if (LocaleCompare("random-threshold",argv[0]+1) == 0)
3269 {
3270 /*
3271 Threshold image.
3272 */
3273 (void) SyncImageSettings(image_info,*image);
3274 (void) RandomThresholdImage(*image,argv[1],exception);
3275 break;
3276 }
3277 if (LocaleCompare("recolor",argv[0]+1) == 0)
3278 {
3279 KernelInfo
3280 *kernel;
3281
3282 (void) SyncImageSettings(image_info,*image);
3283 kernel=AcquireKernelInfo(argv[1]);
3284 if (kernel == (KernelInfo *) NULL)
3285 break;
3286 new_image=ColorMatrixImage(*image,kernel,exception);
3287 kernel=DestroyKernelInfo(kernel);
3288 break;
3289 }
3290 if (LocaleCompare("render",argv[0]+1) == 0)
3291 {
3292 (void) SyncImageSettings(image_info,*image);
3293 draw_info->render=(*argv[0] == '+') ? MagickTrue : MagickFalse;
3294 break;
3295 }
3296 if (LocaleCompare("remap",argv[0]+1) == 0)
3297 {
3298 Image
3299 *remap_image;
3300
3301 /*
3302 Transform image colors to match this set of colors.
3303 */
3304 (void) SyncImageSettings(image_info,*image);
3305 if (*argv[0] == '+')
3306 break;
3307 remap_image=GetImageCache(image_info,argv[1],exception);
3308 if (remap_image == (Image *) NULL)
3309 break;
3310 (void) RemapImage(quantize_info,*image,remap_image,exception);
3311 remap_image=DestroyImage(remap_image);
3312 break;
3313 }
3314 if (LocaleCompare("repage",argv[0]+1) == 0)
3315 {
3316 if (*argv[0] == '+')
3317 {
3318 (void) ParseAbsoluteGeometry("0x0+0+0",&(*image)->page);
3319 break;
3320 }
3321 (void) ResetImagePage(*image,argv[1]);
3322 InheritException(exception,&(*image)->exception);
3323 break;
3324 }
3325 if (LocaleCompare("resample",argv[0]+1) == 0)
3326 {
3327 /*
3328 Resample image.
3329 */
3330 (void) SyncImageSettings(image_info,*image);
3331 flags=ParseGeometry(argv[1],&geometry_info);
3332 if ((flags & SigmaValue) == 0)
3333 geometry_info.sigma=geometry_info.rho;
3334 new_image=ResampleImage(*image,geometry_info.rho,
3335 geometry_info.sigma,(*image)->filter,(*image)->blur,exception);
3336 break;
3337 }
3338 if (LocaleCompare("resize",argv[0]+1) == 0)
3339 {
3340 /*
3341 Resize image.
3342 */
3343 (void) SyncImageSettings(image_info,*image);
3344 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3345 new_image=ResizeImage(*image,geometry.width,geometry.height,
3346 (*image)->filter,(*image)->blur,exception);
3347 break;
3348 }
3349 if (LocaleCompare("roll",argv[0]+1) == 0)
3350 {
3351 /*
3352 Roll image.
3353 */
3354 (void) SyncImageSettings(image_info,*image);
3355 (void) ParsePageGeometry(*image,argv[1],&geometry,exception);
3356 new_image=RollImage(*image,geometry.x,geometry.y,exception);
3357 break;
3358 }
3359 if (LocaleCompare("rotate",argv[0]+1) == 0)
3360 {
3361 char
3362 *geometry;
3363
3364 /*
3365 Check for conditional image rotation.
3366 */
3367 (void) SyncImageSettings(image_info,*image);
3368 if (strchr(argv[1],'>') != (char *) NULL)
3369 if ((*image)->columns <= (*image)->rows)
3370 break;
3371 if (strchr(argv[1],'<') != (char *) NULL)
3372 if ((*image)->columns >= (*image)->rows)
3373 break;
3374 /*
3375 Rotate image.
3376 */
3377 geometry=ConstantString(argv[1]);
3378 (void) SubstituteString(&geometry,">","");
3379 (void) SubstituteString(&geometry,"<","");
3380 (void) ParseGeometry(geometry,&geometry_info);
3381 geometry=DestroyString(geometry);
3382 new_image=RotateImage(*image,geometry_info.rho,exception);
3383 break;
3384 }
3385 break;
3386 }
3387 case 's':
3388 {
3389 if (LocaleCompare("sample",argv[0]+1) == 0)
3390 {
3391 /*
3392 Sample image with pixel replication.
3393 */
3394 (void) SyncImageSettings(image_info,*image);
3395 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3396 new_image=SampleImage(*image,geometry.width,geometry.height,
3397 exception);
3398 break;
3399 }
3400 if (LocaleCompare("scale",argv[0]+1) == 0)
3401 {
3402 /*
3403 Resize image.
3404 */
3405 (void) SyncImageSettings(image_info,*image);
3406 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3407 new_image=ScaleImage(*image,geometry.width,geometry.height,
3408 exception);
3409 break;
3410 }
3411 if (LocaleCompare("selective-blur",argv[0]+1) == 0)
3412 {
3413 /*
3414 Selectively blur pixels within a contrast threshold.
3415 */
3416 (void) SyncImageSettings(image_info,*image);
3417 flags=ParseGeometry(argv[1],&geometry_info);
3418 if ((flags & PercentValue) != 0)
3419 geometry_info.xi=(double) QuantumRange*geometry_info.xi/100.0;
3420 new_image=SelectiveBlurImage(*image,geometry_info.rho,
3421 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3422 break;
3423 }
3424 if (LocaleCompare("separate",argv[0]+1) == 0)
3425 {
3426 /*
3427 Break channels into separate images.
3428 WARNING: This can generate multiple images!
3429 */
3430 (void) SyncImageSettings(image_info,*image);
3431 new_image=SeparateImages(*image,exception);
3432 break;
3433 }
3434 if (LocaleCompare("sepia-tone",argv[0]+1) == 0)
3435 {
3436 double
3437 threshold;
3438
3439 /*
3440 Sepia-tone image.
3441 */
3442 (void) SyncImageSettings(image_info,*image);
3443 threshold=SiPrefixToDouble(argv[1],QuantumRange);
3444 new_image=SepiaToneImage(*image,threshold,exception);
3445 break;
3446 }
3447 if (LocaleCompare("segment",argv[0]+1) == 0)
3448 {
3449 /*
3450 Segment image.
3451 */
3452 (void) SyncImageSettings(image_info,*image);
3453 flags=ParseGeometry(argv[1],&geometry_info);
3454 if ((flags & SigmaValue) == 0)
3455 geometry_info.sigma=1.0;
3456 (void) SegmentImage(*image,(*image)->colorspace,
3457 image_info->verbose,geometry_info.rho,geometry_info.sigma,
3458 exception);
3459 break;
3460 }
3461 if (LocaleCompare("set",argv[0]+1) == 0)
3462 {
3463 char
3464 *value;
3465
3466 /*
3467 Set image argv[0].
3468 */
3469 if (*argv[0] == '+')
3470 {
3471 if (LocaleNCompare(argv[1],"registry:",9) == 0)
3472 (void) DeleteImageRegistry(argv[1]+9);
3473 else
3474 if (LocaleNCompare(argv[1],"argv[0]:",7) == 0)
3475 {
3476 (void) DeleteImageOption(image_info,argv[1]+7);
3477 (void) DeleteImageArtifact(*image,argv[1]+7);
3478 }
3479 else
3480 (void) DeleteImageProperty(*image,argv[1]);
3481 break;
3482 }
3483 value=InterpretImageProperties(image_info,*image,argv[2],
3484 exception);
3485 if (value == (char *) NULL)
3486 break;
3487 if (LocaleNCompare(argv[1],"registry:",9) == 0)
3488 (void) SetImageRegistry(StringRegistryType,argv[1]+9,value,
3489 exception);
3490 else
3491 if (LocaleNCompare(argv[1],"argv[0]:",7) == 0)
3492 {
3493 (void) SetImageOption(image_info,argv[1]+7,value);
3494 (void) SetImageOption(image_info,argv[1]+7,value);
3495 (void) SetImageArtifact(*image,argv[1]+7,value);
3496 }
3497 else
3498 (void) SetImageProperty(*image,argv[1],value);
3499 value=DestroyString(value);
3500 break;
3501 }
3502 if (LocaleCompare("shade",argv[0]+1) == 0)
3503 {
3504 /*
3505 Shade image.
3506 */
3507 (void) SyncImageSettings(image_info,*image);
3508 flags=ParseGeometry(argv[1],&geometry_info);
3509 if ((flags & SigmaValue) == 0)
3510 geometry_info.sigma=1.0;
3511 new_image=ShadeImage(*image,(*argv[0] == '-') ? MagickTrue :
3512 MagickFalse,geometry_info.rho,geometry_info.sigma,exception);
3513 break;
3514 }
3515 if (LocaleCompare("shadow",argv[0]+1) == 0)
3516 {
3517 /*
3518 Shadow image.
3519 */
3520 (void) SyncImageSettings(image_info,*image);
3521 flags=ParseGeometry(argv[1],&geometry_info);
3522 if ((flags & SigmaValue) == 0)
3523 geometry_info.sigma=1.0;
3524 if ((flags & XiValue) == 0)
3525 geometry_info.xi=4.0;
3526 if ((flags & PsiValue) == 0)
3527 geometry_info.psi=4.0;
3528 new_image=ShadowImage(*image,geometry_info.rho,
3529 geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3530 ceil(geometry_info.psi-0.5),exception);
3531 break;
3532 }
3533 if (LocaleCompare("sharpen",argv[0]+1) == 0)
3534 {
3535 /*
3536 Sharpen image.
3537 */
3538 (void) SyncImageSettings(image_info,*image);
3539 flags=ParseGeometry(argv[1],&geometry_info);
3540 if ((flags & SigmaValue) == 0)
3541 geometry_info.sigma=1.0;
3542 if ((flags & XiValue) == 0)
3543 geometry_info.xi=0.0;
3544 new_image=SharpenImage(*image,geometry_info.rho,
3545 geometry_info.sigma,geometry_info.xi,exception);
3546 break;
3547 }
3548 if (LocaleCompare("shave",argv[0]+1) == 0)
3549 {
3550 /*
3551 Shave the image edges.
3552 */
3553 (void) SyncImageSettings(image_info,*image);
3554 flags=ParsePageGeometry(*image,argv[1],&geometry,exception);
3555 new_image=ShaveImage(*image,&geometry,exception);
3556 break;
3557 }
3558 if (LocaleCompare("shear",argv[0]+1) == 0)
3559 {
3560 /*
3561 Shear image.
3562 */
3563 (void) SyncImageSettings(image_info,*image);
3564 flags=ParseGeometry(argv[1],&geometry_info);
3565 if ((flags & SigmaValue) == 0)
3566 geometry_info.sigma=geometry_info.rho;
3567 new_image=ShearImage(*image,geometry_info.rho,
3568 geometry_info.sigma,exception);
3569 break;
3570 }
3571 if (LocaleCompare("sigmoidal-contrast",argv[0]+1) == 0)
3572 {
3573 /*
3574 Sigmoidal non-linearity contrast control.
3575 */
3576 (void) SyncImageSettings(image_info,*image);
3577 flags=ParseGeometry(argv[1],&geometry_info);
3578 if ((flags & SigmaValue) == 0)
3579 geometry_info.sigma=(double) QuantumRange/2.0;
3580 if ((flags & PercentValue) != 0)
3581 geometry_info.sigma=(double) QuantumRange*geometry_info.sigma/
3582 100.0;
3583 (void) SigmoidalContrastImage(*image,(*argv[0] == '-') ?
3584 MagickTrue : MagickFalse,geometry_info.rho,geometry_info.sigma,
3585 exception);
3586 break;
3587 }
3588 if (LocaleCompare("sketch",argv[0]+1) == 0)
3589 {
3590 /*
3591 Sketch image.
3592 */
3593 (void) SyncImageSettings(image_info,*image);
3594 flags=ParseGeometry(argv[1],&geometry_info);
3595 if ((flags & SigmaValue) == 0)
3596 geometry_info.sigma=1.0;
3597 new_image=SketchImage(*image,geometry_info.rho,
3598 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3599 break;
3600 }
3601 if (LocaleCompare("solarize",argv[0]+1) == 0)
3602 {
3603 double
3604 threshold;
3605
3606 (void) SyncImageSettings(image_info,*image);
3607 threshold=SiPrefixToDouble(argv[1],QuantumRange);
3608 (void) SolarizeImage(*image,threshold,exception);
3609 break;
3610 }
3611 if (LocaleCompare("sparse-color",argv[0]+1) == 0)
3612 {
3613 SparseColorMethod
3614 method;
3615
3616 char
3617 *arguments;
3618
3619 /*
3620 Sparse Color Interpolated Gradient
3621 */
3622 (void) SyncImageSettings(image_info,*image);
3623 method=(SparseColorMethod) ParseCommandOption(
3624 MagickSparseColorOptions,MagickFalse,argv[1]);
3625 arguments=InterpretImageProperties(image_info,*image,argv[2],
3626 exception);
3627 if (arguments == (char *) NULL)
3628 break;
3629 new_image=SparseColorOption(*image,method,arguments,
3630 argv[0][0] == '+' ? MagickTrue : MagickFalse,exception);
3631 arguments=DestroyString(arguments);
3632 break;
3633 }
3634 if (LocaleCompare("splice",argv[0]+1) == 0)
3635 {
3636 /*
3637 Splice a solid color into the image.
3638 */
3639 (void) SyncImageSettings(image_info,*image);
3640 (void) ParseGravityGeometry(*image,argv[1],&geometry,exception);
3641 new_image=SpliceImage(*image,&geometry,exception);
3642 break;
3643 }
3644 if (LocaleCompare("spread",argv[0]+1) == 0)
3645 {
3646 /*
3647 Spread an image.
3648 */
3649 (void) SyncImageSettings(image_info,*image);
3650 (void) ParseGeometry(argv[1],&geometry_info);
3651 new_image=SpreadImage(*image,geometry_info.rho,
3652 interpolate_method,exception);
3653 break;
3654 }
3655 if (LocaleCompare("statistic",argv[0]+1) == 0)
3656 {
3657 StatisticType
3658 type;
3659
3660 (void) SyncImageSettings(image_info,*image);
3661 type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
3662 MagickFalse,argv[1]);
3663 (void) ParseGeometry(argv[2],&geometry_info);
3664 new_image=StatisticImage(*image,type,(size_t) geometry_info.rho,
3665 (size_t) geometry_info.sigma,exception);
3666 break;
3667 }
3668 if (LocaleCompare("stretch",argv[0]+1) == 0)
3669 {
3670 if (*argv[0] == '+')
3671 {
3672 draw_info->stretch=UndefinedStretch;
3673 break;
3674 }
3675 draw_info->stretch=(StretchType) ParseCommandOption(
3676 MagickStretchOptions,MagickFalse,argv[1]);
3677 break;
3678 }
3679 if (LocaleCompare("strip",argv[0]+1) == 0)
3680 {
3681 /*
3682 Strip image of profiles and comments.
3683 */
3684 (void) SyncImageSettings(image_info,*image);
3685 (void) StripImage(*image);
3686 InheritException(exception,&(*image)->exception);
3687 break;
3688 }
3689 if (LocaleCompare("stroke",argv[0]+1) == 0)
3690 {
3691 ExceptionInfo
3692 *sans;
3693
3694 if (*argv[0] == '+')
3695 {
3696 (void) QueryColorDatabase("none",&draw_info->stroke,exception);
3697 if (draw_info->stroke_pattern != (Image *) NULL)
3698 draw_info->stroke_pattern=DestroyImage(
3699 draw_info->stroke_pattern);
3700 break;
3701 }
3702 sans=AcquireExceptionInfo();
3703 status=QueryColorDatabase(argv[1],&draw_info->stroke,sans);
3704 sans=DestroyExceptionInfo(sans);
3705 if (status == MagickFalse)
3706 draw_info->stroke_pattern=GetImageCache(image_info,argv[1],
3707 exception);
3708 break;
3709 }
3710 if (LocaleCompare("strokewidth",argv[0]+1) == 0)
3711 {
3712 draw_info->stroke_width=InterpretLocaleValue(argv[1],
3713 (char **) NULL);
3714 break;
3715 }
3716 if (LocaleCompare("style",argv[0]+1) == 0)
3717 {
3718 if (*argv[0] == '+')
3719 {
3720 draw_info->style=UndefinedStyle;
3721 break;
3722 }
3723 draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
3724 MagickFalse,argv[1]);
3725 break;
3726 }
3727 if (LocaleCompare("swirl",argv[0]+1) == 0)
3728 {
3729 /*
3730 Swirl image.
3731 */
3732 (void) SyncImageSettings(image_info,*image);
3733 (void) ParseGeometry(argv[1],&geometry_info);
3734 new_image=SwirlImage(*image,geometry_info.rho,
3735 interpolate_method,exception);
3736 break;
3737 }
3738 break;
3739 }
3740 case 't':
3741 {
3742 if (LocaleCompare("threshold",argv[0]+1) == 0)
3743 {
3744 double
3745 threshold;
3746
3747 /*
3748 Threshold image.
3749 */
3750 (void) SyncImageSettings(image_info,*image);
3751 if (*argv[0] == '+')
3752 threshold=(double) QuantumRange/2;
3753 else
3754 threshold=SiPrefixToDouble(argv[1],QuantumRange);
3755 (void) BilevelImage(*image,threshold);
3756 InheritException(exception,&(*image)->exception);
3757 break;
3758 }
3759 if (LocaleCompare("thumbnail",argv[0]+1) == 0)
3760 {
3761 /*
3762 Thumbnail image.
3763 */
3764 (void) SyncImageSettings(image_info,*image);
3765 (void) ParseRegionGeometry(*image,argv[1],&geometry,exception);
3766 new_image=ThumbnailImage(*image,geometry.width,geometry.height,
3767 exception);
3768 break;
3769 }
3770 if (LocaleCompare("tile",argv[0]+1) == 0)
3771 {
3772 if (*argv[0] == '+')
3773 {
3774 if (draw_info->fill_pattern != (Image *) NULL)
3775 draw_info->fill_pattern=DestroyImage(draw_info->fill_pattern);
3776 break;
3777 }
3778 draw_info->fill_pattern=GetImageCache(image_info,argv[1],
3779 exception);
3780 break;
3781 }
3782 if (LocaleCompare("tint",argv[0]+1) == 0)
3783 {
3784 /*
3785 Tint the image.
3786 */
3787 (void) SyncImageSettings(image_info,*image);
3788 new_image=TintImage(*image,argv[1],&fill,exception);
3789 break;
3790 }
3791 if (LocaleCompare("transform",argv[0]+1) == 0)
3792 {
3793 /*
3794 Affine transform image.
3795 */
3796 (void) SyncImageSettings(image_info,*image);
3797 new_image=AffineTransformImage(*image,&draw_info->affine,
3798 exception);
3799 break;
3800 }
3801 if (LocaleCompare("transparent",argv[0]+1) == 0)
3802 {
3803 PixelInfo
3804 target;
3805
3806 (void) SyncImageSettings(image_info,*image);
3807 (void) QueryMagickColor(argv[1],&target,exception);
3808 (void) TransparentPaintImage(*image,&target,(Quantum)
3809 TransparentAlpha,*argv[0] == '-' ? MagickFalse : MagickTrue,
3810 &(*image)->exception);
3811 break;
3812 }
3813 if (LocaleCompare("transpose",argv[0]+1) == 0)
3814 {
3815 /*
3816 Transpose image scanlines.
3817 */
3818 (void) SyncImageSettings(image_info,*image);
3819 new_image=TransposeImage(*image,exception);
3820 break;
3821 }
3822 if (LocaleCompare("transverse",argv[0]+1) == 0)
3823 {
3824 /*
3825 Transverse image scanlines.
3826 */
3827 (void) SyncImageSettings(image_info,*image);
3828 new_image=TransverseImage(*image,exception);
3829 break;
3830 }
3831 if (LocaleCompare("treedepth",argv[0]+1) == 0)
3832 {
3833 quantize_info->tree_depth=StringToUnsignedLong(argv[1]);
3834 break;
3835 }
3836 if (LocaleCompare("trim",argv[0]+1) == 0)
3837 {
3838 /*
3839 Trim image.
3840 */
3841 (void) SyncImageSettings(image_info,*image);
3842 new_image=TrimImage(*image,exception);
3843 break;
3844 }
3845 if (LocaleCompare("type",argv[0]+1) == 0)
3846 {
3847 ImageType
3848 type;
3849
3850 (void) SyncImageSettings(image_info,*image);
3851 if (*argv[0] == '+')
3852 type=UndefinedType;
3853 else
3854 type=(ImageType) ParseCommandOption(MagickTypeOptions,MagickFalse,
3855 argv[1]);
3856 (*image)->type=UndefinedType;
3857 (void) SetImageType(*image,type,exception);
3858 break;
3859 }
3860 break;
3861 }
3862 case 'u':
3863 {
3864 if (LocaleCompare("undercolor",argv[0]+1) == 0)
3865 {
3866 (void) QueryColorDatabase(argv[1],&draw_info->undercolor,
3867 exception);
3868 break;
3869 }
3870 if (LocaleCompare("unique",argv[0]+1) == 0)
3871 {
3872 if (*argv[0] == '+')
3873 {
3874 (void) DeleteImageArtifact(*image,"identify:unique-colors");
3875 break;
3876 }
3877 (void) SetImageArtifact(*image,"identify:unique-colors","true");
3878 (void) SetImageArtifact(*image,"verbose","true");
3879 break;
3880 }
3881 if (LocaleCompare("unique-colors",argv[0]+1) == 0)
3882 {
3883 /*
3884 Unique image colors.
3885 */
3886 (void) SyncImageSettings(image_info,*image);
3887 new_image=UniqueImageColors(*image,exception);
3888 break;
3889 }
3890 if (LocaleCompare("unsharp",argv[0]+1) == 0)
3891 {
3892 /*
3893 Unsharp mask image.
3894 */
3895 (void) SyncImageSettings(image_info,*image);
3896 flags=ParseGeometry(argv[1],&geometry_info);
3897 if ((flags & SigmaValue) == 0)
3898 geometry_info.sigma=1.0;
3899 if ((flags & XiValue) == 0)
3900 geometry_info.xi=1.0;
3901 if ((flags & PsiValue) == 0)
3902 geometry_info.psi=0.05;
3903 new_image=UnsharpMaskImage(*image,geometry_info.rho,
3904 geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
3905 break;
3906 }
3907 break;
3908 }
3909 case 'v':
3910 {
3911 if (LocaleCompare("verbose",argv[0]+1) == 0)
3912 {
3913 (void) SetImageArtifact(*image,argv[0]+1,
3914 *argv[0] == '+' ? "false" : "true");
3915 break;
3916 }
3917 if (LocaleCompare("vignette",argv[0]+1) == 0)
3918 {
3919 /*
3920 Vignette image.
3921 */
3922 (void) SyncImageSettings(image_info,*image);
3923 flags=ParseGeometry(argv[1],&geometry_info);
3924 if ((flags & SigmaValue) == 0)
3925 geometry_info.sigma=1.0;
3926 if ((flags & XiValue) == 0)
3927 geometry_info.xi=0.1*(*image)->columns;
3928 if ((flags & PsiValue) == 0)
3929 geometry_info.psi=0.1*(*image)->rows;
3930 new_image=VignetteImage(*image,geometry_info.rho,
3931 geometry_info.sigma,(ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
3932 ceil(geometry_info.psi-0.5),exception);
3933 break;
3934 }
3935 if (LocaleCompare("virtual-pixel",argv[0]+1) == 0)
3936 {
3937 if (*argv[0] == '+')
3938 {
3939 (void) SetImageVirtualPixelMethod(*image,
3940 UndefinedVirtualPixelMethod);
3941 break;
3942 }
3943 (void) SetImageVirtualPixelMethod(*image,(VirtualPixelMethod)
3944 ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
3945 argv[1]));
3946 break;
3947 }
3948 break;
3949 }
3950 case 'w':
3951 {
3952 if (LocaleCompare("wave",argv[0]+1) == 0)
3953 {
3954 /*
3955 Wave image.
3956 */
3957 (void) SyncImageSettings(image_info,*image);
3958 flags=ParseGeometry(argv[1],&geometry_info);
3959 if ((flags & SigmaValue) == 0)
3960 geometry_info.sigma=1.0;
3961 new_image=WaveImage(*image,geometry_info.rho,
3962 geometry_info.sigma,exception);
3963 break;
3964 }
3965 if (LocaleCompare("weight",argv[0]+1) == 0)
3966 {
3967 draw_info->weight=StringToUnsignedLong(argv[1]);
3968 if (LocaleCompare(argv[1],"all") == 0)
3969 draw_info->weight=0;
3970 if (LocaleCompare(argv[1],"bold") == 0)
3971 draw_info->weight=700;
3972 if (LocaleCompare(argv[1],"bolder") == 0)
3973 if (draw_info->weight <= 800)
3974 draw_info->weight+=100;
3975 if (LocaleCompare(argv[1],"lighter") == 0)
3976 if (draw_info->weight >= 100)
3977 draw_info->weight-=100;
3978 if (LocaleCompare(argv[1],"normal") == 0)
3979 draw_info->weight=400;
3980 break;
3981 }
3982 if (LocaleCompare("white-threshold",argv[0]+1) == 0)
3983 {
3984 /*
3985 White threshold image.
3986 */
3987 (void) SyncImageSettings(image_info,*image);
3988 (void) WhiteThresholdImage(*image,argv[1],exception);
3989 InheritException(exception,&(*image)->exception);
3990 break;
3991 }
3992 break;
3993 }
3994 default:
3995 break;
3996 }
3997 /*
3998 Replace current image with any image that was generated
3999 */
4000 if (new_image != (Image *) NULL)
4001 ReplaceImageInListReturnLast(image,new_image);
4002
4003 /*
4004 Free resources.
4005 */
4006 quantize_info=DestroyQuantizeInfo(quantize_info);
4007 draw_info=DestroyDrawInfo(draw_info);
4008 status=(*image)->exception.severity == UndefinedException ? 1 : 0;
4009
4010 return(status);
4011}
4012
4013/*
4014%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4015% %
4016% %
4017% %
4018+ S e q u e n c e O p e r a t i o n I m a g e s %
4019% %
4020% %
4021% %
4022%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4023%
4024% SequenceOperationImages() applies a single operation that apply to the
4025% entire image list (e.g. -append, -layers, -coalesce, etc.).
4026%
4027% The format of the MogrifyImage method is:
4028%
4029% MagickBooleanType SequenceOperationImages(ImageInfo *image_info,
4030% const int argc, const char **argv,Image **images,
4031% ExceptionInfo *exception)
4032%
4033% A description of each parameter follows:
4034%
4035% o image_info: the image info..
4036%
4037% o argc: Specifies a pointer to an integer describing the number of
4038% elements in the argument vector.
4039%
4040% o argv: Specifies a pointer to a text array containing the command line
4041% arguments.
4042%
4043% o images: pointer to pointer of the first image in image list.
4044%
4045% o exception: return any errors or warnings in this structure.
4046%
4047*/
4048WandExport MagickBooleanType SequenceOperationImages(ImageInfo *image_info,
4049 const int argc,const char **argv,Image **images,ExceptionInfo *exception)
4050{
4051
4052 MagickStatusType
4053 status;
4054
4055 QuantizeInfo
4056 *quantize_info;
4057
4058 assert(image_info != (ImageInfo *) NULL);
4059 assert(image_info->signature == MagickSignature);
4060 assert(images != (Image **) NULL);
4061 assert((*images)->previous == (Image *) NULL);
4062 assert((*images)->signature == MagickSignature);
4063 if ((*images)->debug != MagickFalse)
4064 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4065 (*images)->filename);
4066
4067 quantize_info=AcquireQuantizeInfo(image_info);
4068 channel=image_info->channel;
4069
4070 status=MagickTrue;
4071
4072 switch (*(argv[0]+1))
4073 {
4074 case 'a':
4075 {
4076 if (LocaleCompare("affinity",argv[0]+1) == 0)
4077 {
4078 (void) SyncImagesSettings(image_info,*images);
4079 if (*argv[0] == '+')
4080 {
4081 (void) RemapImages(quantize_info,*images,(Image *) NULL,
4082 exception);
4083 break;
4084 }
4085 break;
4086 }
4087 if (LocaleCompare("append",argv[0]+1) == 0)
4088 {
4089 Image
4090 *append_image;
4091
4092 (void) SyncImagesSettings(image_info,*images);
4093 append_image=AppendImages(*images,*argv[0] == '-' ? MagickTrue :
4094 MagickFalse,exception);
4095 if (append_image == (Image *) NULL)
4096 {
4097 status=MagickFalse;
4098 break;
4099 }
4100 *images=DestroyImageList(*images);
4101 *images=append_image;
4102 break;
4103 }
4104 if (LocaleCompare("average",argv[0]+1) == 0)
4105 {
4106 Image
4107 *average_image;
4108
4109 /*
4110 Average an image sequence (deprecated).
4111 */
4112 (void) SyncImagesSettings(image_info,*images);
4113 average_image=EvaluateImages(*images,MeanEvaluateOperator,
4114 exception);
4115 if (average_image == (Image *) NULL)
4116 {
4117 status=MagickFalse;
4118 break;
4119 }
4120 *images=DestroyImageList(*images);
4121 *images=average_image;
4122 break;
4123 }
4124 break;
4125 }
4126 case 'c':
4127 {
4128 if (LocaleCompare("channel",argv[0]+1) == 0)
4129 {
4130 ChannelType
4131 channel;
4132
4133 if (*argv[0] == '+')
4134 {
4135 channel=DefaultChannels;
4136 break;
4137 }
4138 channel=(ChannelType) ParseChannelOption(argv[1]);
4139 SetPixelChannelMap(*images,channel);
4140 break;
4141 }
4142 if (LocaleCompare("clut",argv[0]+1) == 0)
4143 {
4144 Image
4145 *clut_image,
4146 *image;
4147
4148 (void) SyncImagesSettings(image_info,*images);
4149 image=RemoveFirstImageFromList(images);
4150 clut_image=RemoveFirstImageFromList(images);
4151 if (clut_image == (Image *) NULL)
4152 {
4153 status=MagickFalse;
4154 break;
4155 }
4156 (void) ClutImageChannel(image,channel,clut_image);
4157 clut_image=DestroyImage(clut_image);
4158 *images=DestroyImageList(*images);
4159 *images=image;
4160 break;
4161 }
4162 if (LocaleCompare("coalesce",argv[0]+1) == 0)
4163 {
4164 Image
4165 *coalesce_image;
4166
4167 (void) SyncImagesSettings(image_info,*images);
4168 coalesce_image=CoalesceImages(*images,exception);
4169 if (coalesce_image == (Image *) NULL)
4170 {
4171 status=MagickFalse;
4172 break;
4173 }
4174 *images=DestroyImageList(*images);
4175 *images=coalesce_image;
4176 break;
4177 }
4178 if (LocaleCompare("combine",argv[0]+1) == 0)
4179 {
4180 Image
4181 *combine_image;
4182
4183 (void) SyncImagesSettings(image_info,*images);
4184 combine_image=CombineImages(*images,exception);
4185 if (combine_image == (Image *) NULL)
4186 {
4187 status=MagickFalse;
4188 break;
4189 }
4190 *images=DestroyImageList(*images);
4191 *images=combine_image;
4192 break;
4193 }
4194 if (LocaleCompare("composite",argv[0]+1) == 0)
4195 {
4196 Image
4197 *mask_image,
4198 *composite_image,
4199 *image;
4200
4201 RectangleInfo
4202 geometry;
4203
4204 (void) SyncImagesSettings(image_info,*images);
4205 image=RemoveFirstImageFromList(images);
4206 composite_image=RemoveFirstImageFromList(images);
4207 if (composite_image == (Image *) NULL)
4208 {
4209 status=MagickFalse;
4210 break;
4211 }
4212 (void) TransformImage(&composite_image,(char *) NULL,
4213 composite_image->geometry);
4214 SetGeometry(composite_image,&geometry);
4215 (void) ParseAbsoluteGeometry(composite_image->geometry,&geometry);
4216 GravityAdjustGeometry(image->columns,image->rows,image->gravity,
4217 &geometry);
4218 mask_image=RemoveFirstImageFromList(images);
4219 if (mask_image != (Image *) NULL)
4220 {
4221 if ((image->compose == DisplaceCompositeOp) ||
4222 (image->compose == DistortCompositeOp))
4223 {
4224 /*
4225 Merge Y displacement into X displacement image.
4226 */
4227 (void) CompositeImage(composite_image,CopyGreenCompositeOp,
4228 mask_image,0,0);
4229 mask_image=DestroyImage(mask_image);
4230 }
4231 else
4232 {
4233 /*
4234 Set a blending mask for the composition.
4235 Posible error, what if image->mask already set.
4236 */
4237 image->mask=mask_image;
4238 (void) NegateImage(image->mask,MagickFalse,exception);
4239 }
4240 }
4241 (void) CompositeImage(image,image->compose,composite_image,
4242 geometry.x,geometry.y);
4243 if (mask_image != (Image *) NULL)
4244 mask_image=image->mask=DestroyImage(image->mask);
4245 composite_image=DestroyImage(composite_image);
4246 InheritException(exception,&image->exception);
4247 *images=DestroyImageList(*images);
4248 *images=image;
4249 break;
4250 }
4251 break;
4252 }
4253 case 'd':
4254 {
4255 if (LocaleCompare("deconstruct",argv[0]+1) == 0)
4256 {
4257 Image
4258 *deconstruct_image;
4259
4260 (void) SyncImagesSettings(image_info,*images);
4261 deconstruct_image=CompareImagesLayers(*images,CompareAnyLayer,
4262 exception);
4263 if (deconstruct_image == (Image *) NULL)
4264 {
4265 status=MagickFalse;
4266 break;
4267 }
4268 *images=DestroyImageList(*images);
4269 *images=deconstruct_image;
4270 break;
4271 }
4272 if (LocaleCompare("delete",argv[0]+1) == 0)
4273 {
4274 if (*argv[0] == '+')
4275 DeleteImages(images,"-1",exception);
4276 else
4277 DeleteImages(images,argv[1],exception);
4278 break;
4279 }
4280 if (LocaleCompare("dither",argv[0]+1) == 0)
4281 {
4282 if (*argv[0] == '+')
4283 {
4284 quantize_info->dither=MagickFalse;
4285 break;
4286 }
4287 quantize_info->dither=MagickTrue;
4288 quantize_info->dither_method=(DitherMethod) ParseCommandOption(
4289 MagickDitherOptions,MagickFalse,argv[1]);
4290 break;
4291 }
4292 if (LocaleCompare("duplicate",argv[0]+1) == 0)
4293 {
4294 Image
4295 *duplicate_images;
4296
4297 if (*argv[0] == '+')
4298 duplicate_images=DuplicateImages(*images,1,"-1",exception);
4299 else
4300 {
4301 const char
4302 *p;
4303
4304 size_t
4305 number_duplicates;
4306
4307 number_duplicates=(size_t) StringToLong(argv[1]);
4308 p=strchr(argv[1],',');
4309 if (p == (const char *) NULL)
4310 duplicate_images=DuplicateImages(*images,number_duplicates,
4311 "-1",exception);
4312 else
4313 duplicate_images=DuplicateImages(*images,number_duplicates,p,
4314 exception);
4315 }
4316 AppendImageToList(images, duplicate_images);
4317 (void) SyncImagesSettings(image_info,*images);
4318 break;
4319 }
4320 break;
4321 }
4322 case 'e':
4323 {
4324 if (LocaleCompare("evaluate-sequence",argv[0]+1) == 0)
4325 {
4326 Image
4327 *evaluate_image;
4328
4329 MagickEvaluateOperator
4330 op;
4331
4332 (void) SyncImageSettings(image_info,*images);
4333 op=(MagickEvaluateOperator) ParseCommandOption(
4334 MagickEvaluateOptions,MagickFalse,argv[1]);
4335 evaluate_image=EvaluateImages(*images,op,exception);
4336 if (evaluate_image == (Image *) NULL)
4337 {
4338 status=MagickFalse;
4339 break;
4340 }
4341 *images=DestroyImageList(*images);
4342 *images=evaluate_image;
4343 break;
4344 }
4345 break;
4346 }
4347 case 'f':
4348 {
4349 if (LocaleCompare("fft",argv[0]+1) == 0)
4350 {
4351 Image
4352 *fourier_image;
4353
4354 /*
4355 Implements the discrete Fourier transform (DFT).
4356 */
4357 (void) SyncImageSettings(image_info,*images);
4358 fourier_image=ForwardFourierTransformImage(*images,*argv[0] == '-' ?
4359 MagickTrue : MagickFalse,exception);
4360 if (fourier_image == (Image *) NULL)
4361 break;
4362 *images=DestroyImage(*images);
4363 *images=fourier_image;
4364 break;
4365 }
4366 if (LocaleCompare("flatten",argv[0]+1) == 0)
4367 {
4368 Image
4369 *flatten_image;
4370
4371 (void) SyncImagesSettings(image_info,*images);
4372 flatten_image=MergeImageLayers(*images,FlattenLayer,exception);
4373 if (flatten_image == (Image *) NULL)
4374 break;
4375 *images=DestroyImageList(*images);
4376 *images=flatten_image;
4377 break;
4378 }
4379 if (LocaleCompare("fx",argv[0]+1) == 0)
4380 {
4381 Image
4382 *fx_image;
4383
4384 (void) SyncImagesSettings(image_info,*images);
4385 fx_image=FxImage(*images,argv[1],exception);
4386 if (fx_image == (Image *) NULL)
4387 {
4388 status=MagickFalse;
4389 break;
4390 }
4391 *images=DestroyImageList(*images);
4392 *images=fx_image;
4393 break;
4394 }
4395 break;
4396 }
4397 case 'h':
4398 {
4399 if (LocaleCompare("hald-clut",argv[0]+1) == 0)
4400 {
4401 Image
4402 *hald_image,
4403 *image;
4404
4405 (void) SyncImagesSettings(image_info,*images);
4406 image=RemoveFirstImageFromList(images);
4407 hald_image=RemoveFirstImageFromList(images);
4408 if (hald_image == (Image *) NULL)
4409 {
4410 status=MagickFalse;
4411 break;
4412 }
4413 (void) HaldClutImage(image,hald_image,exception);
4414 hald_image=DestroyImage(hald_image);
4415 if (*images != (Image *) NULL)
4416 *images=DestroyImageList(*images);
4417 *images=image;
4418 break;
4419 }
4420 break;
4421 }
4422 case 'i':
4423 {
4424 if (LocaleCompare("ift",argv[0]+1) == 0)
4425 {
4426 Image
4427 *fourier_image,
4428 *magnitude_image,
4429 *phase_image;
4430
4431 /*
4432 Implements the inverse fourier discrete Fourier transform (DFT).
4433 */
4434 (void) SyncImagesSettings(image_info,*images);
4435 magnitude_image=RemoveFirstImageFromList(images);
4436 phase_image=RemoveFirstImageFromList(images);
4437 if (phase_image == (Image *) NULL)
4438 {
4439 status=MagickFalse;
4440 break;
4441 }
4442 fourier_image=InverseFourierTransformImage(magnitude_image,
4443 phase_image,*argv[0] == '-' ? MagickTrue : MagickFalse,exception);
4444 if (fourier_image == (Image *) NULL)
4445 break;
4446 if (*images != (Image *) NULL)
4447 *images=DestroyImage(*images);
4448 *images=fourier_image;
4449 break;
4450 }
4451 if (LocaleCompare("insert",argv[0]+1) == 0)
4452 {
4453 Image
4454 *p,
4455 *q;
4456
4457 index=0;
4458 if (*argv[0] != '+')
4459 index=(ssize_t) StringToLong(argv[1]);
4460 p=RemoveLastImageFromList(images);
4461 if (p == (Image *) NULL)
4462 {
4463 (void) ThrowMagickException(exception,GetMagickModule(),
4464 OptionError,"NoSuchImage","`%s'",argv[1]);
4465 status=MagickFalse;
4466 break;
4467 }
4468 q=p;
4469 if (index == 0)
4470 PrependImageToList(images,q);
4471 else
4472 if (index == (ssize_t) GetImageListLength(*images))
4473 AppendImageToList(images,q);
4474 else
4475 {
4476 q=GetImageFromList(*images,index-1);
4477 if (q == (Image *) NULL)
4478 {
4479 (void) ThrowMagickException(exception,GetMagickModule(),
4480 OptionError,"NoSuchImage","`%s'",argv[1]);
4481 status=MagickFalse;
4482 break;
4483 }
4484 InsertImageInList(&q,p);
4485 }
4486 *images=GetFirstImageInList(q);
4487 break;
4488 }
4489 if (LocaleCompare("interpolate",argv[0]+1) == 0)
4490 {
4491 interpolate_method=(PixelInterpolateMethod) ParseCommandOption(
4492 MagickInterpolateOptions,MagickFalse,argv[1]);
4493 break;
4494 }
4495 break;
4496 }
4497 case 'l':
4498 {
4499 if (LocaleCompare("layers",argv[0]+1) == 0)
4500 {
4501 Image
4502 *layers;
4503
4504 ImageLayerMethod
4505 method;
4506
4507 (void) SyncImagesSettings(image_info,*images);
4508 layers=(Image *) NULL;
4509 method=(ImageLayerMethod) ParseCommandOption(MagickLayerOptions,
4510 MagickFalse,argv[1]);
4511 switch (method)
4512 {
4513 case CoalesceLayer:
4514 {
4515 layers=CoalesceImages(*images,exception);
4516 break;
4517 }
4518 case CompareAnyLayer:
4519 case CompareClearLayer:
4520 case CompareOverlayLayer:
4521 default:
4522 {
4523 layers=CompareImagesLayers(*images,method,exception);
4524 break;
4525 }
4526 case MergeLayer:
4527 case FlattenLayer:
4528 case MosaicLayer:
4529 case TrimBoundsLayer:
4530 {
4531 layers=MergeImageLayers(*images,method,exception);
4532 break;
4533 }
4534 case DisposeLayer:
4535 {
4536 layers=DisposeImages(*images,exception);
4537 break;
4538 }
4539 case OptimizeImageLayer:
4540 {
4541 layers=OptimizeImageLayers(*images,exception);
4542 break;
4543 }
4544 case OptimizePlusLayer:
4545 {
4546 layers=OptimizePlusImageLayers(*images,exception);
4547 break;
4548 }
4549 case OptimizeTransLayer:
4550 {
4551 OptimizeImageTransparency(*images,exception);
4552 break;
4553 }
4554 case RemoveDupsLayer:
4555 {
4556 RemoveDuplicateLayers(images,exception);
4557 break;
4558 }
4559 case RemoveZeroLayer:
4560 {
4561 RemoveZeroDelayLayers(images,exception);
4562 break;
4563 }
4564 case OptimizeLayer:
4565 {
4566 /*
4567 General Purpose, GIF Animation Optimizer.
4568 */
4569 layers=CoalesceImages(*images,exception);
4570 if (layers == (Image *) NULL)
4571 {
4572 status=MagickFalse;
4573 break;
4574 }
4575 *images=DestroyImageList(*images);
4576 *images=layers;
4577 layers=OptimizeImageLayers(*images,exception);
4578 if (layers == (Image *) NULL)
4579 {
4580 status=MagickFalse;
4581 break;
4582 }
4583 *images=DestroyImageList(*images);
4584 *images=layers;
4585 layers=(Image *) NULL;
4586 OptimizeImageTransparency(*images,exception);
4587 (void) RemapImages(quantize_info,*images,(Image *) NULL,
4588 exception);
4589 break;
4590 }
4591 case CompositeLayer:
4592 {
4593 CompositeOperator
4594 compose;
4595
4596 Image
4597 *source;
4598
4599 RectangleInfo
4600 geometry;
4601
4602 /*
4603 Split image sequence at the first 'NULL:' image.
4604 */
4605 source=(*images);
4606 while (source != (Image *) NULL)
4607 {
4608 source=GetNextImageInList(source);
4609 if ((source != (Image *) NULL) &&
4610 (LocaleCompare(source->magick,"NULL") == 0))
4611 break;
4612 }
4613 if (source != (Image *) NULL)
4614 {
4615 if ((GetPreviousImageInList(source) == (Image *) NULL) ||
4616 (GetNextImageInList(source) == (Image *) NULL))
4617 source=(Image *) NULL;
4618 else
4619 {
4620 /*
4621 Separate the two lists, junk the null: image.
4622 */
4623 source=SplitImageList(source->previous);
4624 DeleteImageFromList(&source);
4625 }
4626 }
4627 if (source == (Image *) NULL)
4628 {
4629 (void) ThrowMagickException(exception,GetMagickModule(),
4630 OptionError,"MissingNullSeparator","layers Composite");
4631 status=MagickFalse;
4632 break;
4633 }
4634 /*
4635 Adjust offset with gravity and virtual canvas.
4636 */
4637 SetGeometry(*images,&geometry);
4638 (void) ParseAbsoluteGeometry((*images)->geometry,&geometry);
4639 geometry.width=source->page.width != 0 ?
4640 source->page.width : source->columns;
4641 geometry.height=source->page.height != 0 ?
4642 source->page.height : source->rows;
4643 GravityAdjustGeometry((*images)->page.width != 0 ?
4644 (*images)->page.width : (*images)->columns,
4645 (*images)->page.height != 0 ? (*images)->page.height :
4646 (*images)->rows,(*images)->gravity,&geometry);
4647 compose=OverCompositeOp;
4648 argv[0]=GetImageOption(image_info,"compose");
4649 if (argv[0] != (const char *) NULL)
4650 compose=(CompositeOperator) ParseCommandOption(
4651 MagickComposeOptions,MagickFalse,argv[0]);
4652 CompositeLayers(*images,compose,source,geometry.x,geometry.y,
4653 exception);
4654 source=DestroyImageList(source);
4655 break;
4656 }
4657 }
4658 if (layers == (Image *) NULL)
4659 break;
4660 InheritException(exception,&layers->exception);
4661 *images=DestroyImageList(*images);
4662 *images=layers;
4663 break;
4664 }
4665 break;
4666 }
4667 case 'm':
4668 {
4669 if (LocaleCompare("map",argv[0]+1) == 0)
4670 {
4671 (void) SyncImagesSettings(image_info,*images);
4672 if (*argv[0] == '+')
4673 {
4674 (void) RemapImages(quantize_info,*images,(Image *) NULL,
4675 exception);
4676 break;
4677 }
4678 break;
4679 }
4680 if (LocaleCompare("maximum",argv[0]+1) == 0)
4681 {
4682 Image
4683 *maximum_image;
4684
4685 /*
4686 Maximum image sequence (deprecated).
4687 */
4688 (void) SyncImagesSettings(image_info,*images);
4689 maximum_image=EvaluateImages(*images,MaxEvaluateOperator,exception);
4690 if (maximum_image == (Image *) NULL)
4691 {
4692 status=MagickFalse;
4693 break;
4694 }
4695 *images=DestroyImageList(*images);
4696 *images=maximum_image;
4697 break;
4698 }
4699 if (LocaleCompare("minimum",argv[0]+1) == 0)
4700 {
4701 Image
4702 *minimum_image;
4703
4704 /*
4705 Minimum image sequence (deprecated).
4706 */
4707 (void) SyncImagesSettings(image_info,*images);
4708 minimum_image=EvaluateImages(*images,MinEvaluateOperator,exception);
4709 if (minimum_image == (Image *) NULL)
4710 {
4711 status=MagickFalse;
4712 break;
4713 }
4714 *images=DestroyImageList(*images);
4715 *images=minimum_image;
4716 break;
4717 }
4718 if (LocaleCompare("morph",argv[0]+1) == 0)
4719 {
4720 Image
4721 *morph_image;
4722
4723 (void) SyncImagesSettings(image_info,*images);
4724 morph_image=MorphImages(*images,StringToUnsignedLong(argv[1]),
4725 exception);
4726 if (morph_image == (Image *) NULL)
4727 {
4728 status=MagickFalse;
4729 break;
4730 }
4731 *images=DestroyImageList(*images);
4732 *images=morph_image;
4733 break;
4734 }
4735 if (LocaleCompare("mosaic",argv[0]+1) == 0)
4736 {
4737 Image
4738 *mosaic_image;
4739
4740 (void) SyncImagesSettings(image_info,*images);
4741 mosaic_image=MergeImageLayers(*images,MosaicLayer,exception);
4742 if (mosaic_image == (Image *) NULL)
4743 {
4744 status=MagickFalse;
4745 break;
4746 }
4747 *images=DestroyImageList(*images);
4748 *images=mosaic_image;
4749 break;
4750 }
4751 break;
4752 }
4753 case 'p':
4754 {
4755 if (LocaleCompare("print",argv[0]+1) == 0)
4756 {
4757 char
4758 *string;
4759
4760 (void) SyncImagesSettings(image_info,*images);
4761 string=InterpretImageProperties(image_info,*images,argv[1],
4762 exception);
4763 if (string == (char *) NULL)
4764 break;
4765 (void) FormatLocaleFile(stdout,"%s",string);
4766 string=DestroyString(string);
4767 }
4768 if (LocaleCompare("process",argv[0]+1) == 0)
4769 {
4770 char
4771 **arguments;
4772
4773 int
4774 j,
4775 number_arguments;
4776
4777 (void) SyncImagesSettings(image_info,*images);
4778 arguments=StringToArgv(argv[1],&number_arguments);
4779 if (arguments == (char **) NULL)
4780 break;
4781 if ((argc > 1) && (strchr(arguments[1],'=') != (char *) NULL))
4782 {
4783 char
4784 breaker,
4785 quote,
4786 *token;
4787
4788 const char
4789 *arguments;
4790
4791 int
4792 next,
4793 status;
4794
4795 size_t
4796 length;
4797
4798 TokenInfo
4799 *token_info;
4800
4801 /*
4802 Support old style syntax, filter="-option arg".
4803 */
4804 length=strlen(argv[1]);
4805 token=(char *) NULL;
4806 if (~length >= (MaxTextExtent-1))
4807 token=(char *) AcquireQuantumMemory(length+MaxTextExtent,
4808 sizeof(*token));
4809 if (token == (char *) NULL)
4810 break;
4811 next=0;
4812 arguments=argv[1];
4813 token_info=AcquireTokenInfo();
4814 status=Tokenizer(token_info,0,token,length,arguments,"","=",
4815 "\"",'\0',&breaker,&next,&quote);
4816 token_info=DestroyTokenInfo(token_info);
4817 if (status == 0)
4818 {
4819 const char
4820 *argv;
4821
4822 argv=(&(arguments[next]));
4823 (void) InvokeDynamicImageFilter(token,&(*images),1,&argv,
4824 exception);
4825 }
4826 token=DestroyString(token);
4827 break;
4828 }
4829 (void) SubstituteString(&arguments[1],"-","");
4830 (void) InvokeDynamicImageFilter(arguments[1],&(*images),
4831 number_arguments-2,(const char **) arguments+2,exception);
4832 for (j=0; j < number_arguments; j++)
4833 arguments[j]=DestroyString(arguments[j]);
4834 arguments=(char **) RelinquishMagickMemory(arguments);
4835 break;
4836 }
4837 break;
4838 }
4839 case 'r':
4840 {
4841 if (LocaleCompare("reverse",argv[0]+1) == 0)
4842 {
4843 ReverseImageList(images);
4844 InheritException(exception,&(*images)->exception);
4845 break;
4846 }
4847 break;
4848 }
4849 case 's':
4850 {
4851 if (LocaleCompare("smush",argv[0]+1) == 0)
4852 {
4853 Image
4854 *smush_image;
4855
4856 ssize_t
4857 offset;
4858
4859 (void) SyncImagesSettings(image_info,*images);
4860 offset=(ssize_t) StringToLong(argv[1]);
4861 smush_image=SmushImages(*images,*argv[0] == '-' ? MagickTrue :
4862 MagickFalse,offset,exception);
4863 if (smush_image == (Image *) NULL)
4864 {
4865 status=MagickFalse;
4866 break;
4867 }
4868 *images=DestroyImageList(*images);
4869 *images=smush_image;
4870 break;
4871 }
4872 if (LocaleCompare("swap",argv[0]+1) == 0)
4873 {
4874 Image
4875 *p,
4876 *q,
4877 *swap;
4878
4879 ssize_t
4880 swap_index;
4881
4882 index=(-1);
4883 swap_index=(-2);
4884 if (*argv[0] != '+')
4885 {
4886 GeometryInfo
4887 geometry_info;
4888
4889 MagickStatusType
4890 flags;
4891
4892 swap_index=(-1);
4893 flags=ParseGeometry(argv[1],&geometry_info);
4894 index=(ssize_t) geometry_info.rho;
4895 if ((flags & SigmaValue) != 0)
4896 swap_index=(ssize_t) geometry_info.sigma;
4897 }
4898 p=GetImageFromList(*images,index);
4899 q=GetImageFromList(*images,swap_index);
4900 if ((p == (Image *) NULL) || (q == (Image *) NULL))
4901 {
4902 (void) ThrowMagickException(exception,GetMagickModule(),
4903 OptionError,"NoSuchImage","`%s'",(*images)->filename);
4904 status=MagickFalse;
4905 break;
4906 }
4907 if (p == q)
4908 break;
4909 swap=CloneImage(p,0,0,MagickTrue,exception);
4910 ReplaceImageInList(&p,CloneImage(q,0,0,MagickTrue,exception));
4911 ReplaceImageInList(&q,swap);
4912 *images=GetFirstImageInList(q);
4913 break;
4914 }
4915 break;
4916 }
4917 case 'w':
4918 {
4919 if (LocaleCompare("write",argv[0]+1) == 0)
4920 {
4921 char
4922 key[MaxTextExtent];
4923
4924 Image
4925 *write_images;
4926
4927 ImageInfo
4928 *write_info;
4929
4930 (void) SyncImagesSettings(image_info,*images);
4931 (void) FormatLocaleString(key,MaxTextExtent,"cache:%s",argv[1]);
4932 (void) DeleteImageRegistry(key);
4933 write_images=(*images);
4934 if (*argv[0] == '+')
4935 write_images=CloneImageList(*images,exception);
4936 write_info=CloneImageInfo(image_info);
4937 status&=WriteImages(write_info,write_images,argv[1],exception);
4938 write_info=DestroyImageInfo(write_info);
4939 if (*argv[0] == '+')
4940 write_images=DestroyImageList(write_images);
4941 break;
4942 }
4943 break;
4944 }
4945 default:
4946 break;
4947 }
4948 quantize_info=DestroyQuantizeInfo(quantize_info);
4949
4950 return(status != 0 ? MagickTrue : MagickFalse);
4951}
4952