1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % CCCC OOO M M PPPP OOO SSSSS IIIII TTTTT EEEEE %
7 % C O O MM MM P P O O SS I T E %
8 % C O O M M M PPPP O O SSS I T EEE %
9 % C O O M M P O O SS I T E %
10 % CCCC OOO M M P OOO SSSSS IIIII T EEEEE %
11 % %
12 % %
13 % MagickWand Image Composite Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright 1999-2021 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 % https://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 % Use the composite program to overlap one image over another.
37 %
38 */
39
40 /*
41 Include declarations.
42 */
43 #include "wand/studio.h"
44 #include "wand/MagickWand.h"
45 #include "wand/mogrify-private.h"
46 #include "magick/string-private.h"
47
48 /*
49 Typedef declarations.
50 */
51 typedef struct _CompositeOptions
52 {
53 ChannelType
54 channel;
55
56 char
57 *compose_args,
58 *geometry;
59
60 CompositeOperator
61 compose;
62
63 GravityType
64 gravity;
65
66 ssize_t
67 stegano;
68
69 RectangleInfo
70 offset;
71
72 MagickBooleanType
73 stereo,
74 tile;
75 } CompositeOptions;
76
77 /*
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 % %
80 % %
81 % %
82 % C o m p o s i t e I m a g e C o m m a n d %
83 % %
84 % %
85 % %
86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 %
88 % CompositeImageCommand() reads one or more images and an optional mask and
89 % composites them into a new image.
90 %
91 % The format of the CompositeImageCommand method is:
92 %
93 % MagickBooleanType CompositeImageCommand(ImageInfo *image_info,int argc,
94 % char **argv,char **metadata,ExceptionInfo *exception)
95 %
96 % A description of each parameter follows:
97 %
98 % o image_info: the image info.
99 %
100 % o argc: the number of elements in the argument vector.
101 %
102 % o argv: A text array containing the command line arguments.
103 %
104 % o metadata: any metadata is returned here.
105 %
106 % o exception: return any errors or warnings in this structure.
107 %
108 */
109
CompositeImageList(ImageInfo * image_info,Image ** image,Image * composite_image,CompositeOptions * composite_options,ExceptionInfo * exception)110 static MagickBooleanType CompositeImageList(ImageInfo *image_info,Image **image,
111 Image *composite_image,CompositeOptions *composite_options,
112 ExceptionInfo *exception)
113 {
114 MagickStatusType
115 status;
116
117 assert(image_info != (ImageInfo *) NULL);
118 assert(image_info->signature == MagickCoreSignature);
119 assert(image != (Image **) NULL);
120 assert((*image)->signature == MagickCoreSignature);
121 if ((*image)->debug != MagickFalse)
122 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
123 assert(exception != (ExceptionInfo *) NULL);
124 (void) image_info;
125 status=MagickTrue;
126 if (composite_image != (Image *) NULL)
127 {
128 assert(composite_image->signature == MagickCoreSignature);
129 switch( composite_options->compose )
130 {
131 case BlendCompositeOp:
132 case BlurCompositeOp:
133 case DisplaceCompositeOp:
134 case DistortCompositeOp:
135 case DissolveCompositeOp:
136 case ModulateCompositeOp:
137 case ThresholdCompositeOp:
138 {
139 (void) SetImageArtifact(*image,"compose:args",
140 composite_options->compose_args);
141 break;
142 }
143 default:
144 break;
145 }
146 /*
147 Composite image.
148 */
149 if (composite_options->stegano != 0)
150 {
151 Image
152 *stegano_image;
153
154 (*image)->offset=composite_options->stegano-1;
155 stegano_image=SteganoImage(*image,composite_image,exception);
156 if (stegano_image != (Image *) NULL)
157 {
158 *image=DestroyImageList(*image);
159 *image=stegano_image;
160 }
161 }
162 else
163 if (composite_options->stereo != MagickFalse)
164 {
165 Image
166 *stereo_image;
167
168 stereo_image=StereoAnaglyphImage(*image,composite_image,
169 composite_options->offset.x,composite_options->offset.y,
170 exception);
171 if (stereo_image != (Image *) NULL)
172 {
173 *image=DestroyImageList(*image);
174 *image=stereo_image;
175 }
176 }
177 else
178 if (composite_options->tile != MagickFalse)
179 {
180 size_t
181 columns;
182
183 ssize_t
184 x,
185 y;
186
187 /*
188 Tile the composite image.
189 */
190 (void) SetImageArtifact(composite_image,"compose:outside-overlay",
191 "false");
192 columns=composite_image->columns;
193 for (y=0; y < (ssize_t) (*image)->rows; y+=(ssize_t) composite_image->rows)
194 for (x=0; x < (ssize_t) (*image)->columns; x+=(ssize_t) columns)
195 status&=CompositeImageChannel(*image,
196 composite_options->channel,composite_options->compose,
197 composite_image,x,y);
198 GetImageException(*image,exception);
199 }
200 else
201 {
202 RectangleInfo
203 geometry;
204
205 /*
206 Work out gravity Adjustment of Offset
207 */
208 SetGeometry(*image,&geometry);
209 (void) ParseAbsoluteGeometry(composite_options->geometry,
210 &geometry);
211 geometry.width=composite_image->columns;
212 geometry.height=composite_image->rows;
213 GravityAdjustGeometry((*image)->columns,(*image)->rows,
214 composite_options->gravity, &geometry);
215 (*image)->gravity=(GravityType) composite_options->gravity;
216 /*
217 Digitally composite image.
218 */
219 status&=CompositeImageChannel(*image,composite_options->channel,
220 composite_options->compose,composite_image,geometry.x,
221 geometry.y);
222 GetImageException(*image,exception);
223 }
224 }
225 return(status != 0 ? MagickTrue : MagickFalse);
226 }
227
CompositeUsage(void)228 static MagickBooleanType CompositeUsage(void)
229 {
230 static const char
231 miscellaneous[] =
232 " -debug events display copious debugging information\n"
233 " -help print program options\n"
234 " -list type print a list of supported option arguments\n"
235 " -log format format of debugging information\n"
236 " -version print version information",
237 operators[] =
238 " -blend geometry blend images\n"
239 " -border geometry surround image with a border of color\n"
240 " -bordercolor color border color\n"
241 " -colors value preferred number of colors in the image\n"
242 " -decipher filename convert cipher pixels to plain pixels\n"
243 " -displace geometry shift lookup according to a relative displacement map\n"
244 " -dissolve value dissolve the two images a given percent\n"
245 " -distort geometry shift lookup according to a absolute distortion map\n"
246 " -encipher filename convert plain pixels to cipher pixels\n"
247 " -extract geometry extract area from image\n"
248 " -geometry geometry location of the composite image\n"
249 " -identify identify the format and characteristics of the image\n"
250 " -monochrome transform image to black and white\n"
251 " -negate replace every pixel with its complementary color \n"
252 " -profile filename add ICM or IPTC information profile to image\n"
253 " -quantize colorspace reduce colors in this colorspace\n"
254 " -rotate degrees apply Paeth rotation to the image\n"
255 " -resize geometry resize the image\n"
256 " -sharpen geometry sharpen the image\n"
257 " -shave geometry shave pixels from the image edges\n"
258 " -stegano offset hide watermark within an image\n"
259 " -stereo geometry combine two image to create a stereo anaglyph\n"
260 " -strip strip image of all profiles and comments\n"
261 " -thumbnail geometry create a thumbnail of the image\n"
262 " -transform affine transform image\n"
263 " -type type image type\n"
264 " -unsharp geometry sharpen the image\n"
265 " -watermark geometry percent brightness and saturation of a watermark\n"
266 " -write filename write images to this file",
267 settings[] =
268 " -affine matrix affine transform matrix\n"
269 " -alpha option on, activate, off, deactivate, set, opaque, copy\n"
270 " transparent, extract, background, or shape\n"
271 " -authenticate password\n"
272 " decipher image with this password\n"
273 " -blue-primary point chromaticity blue primary point\n"
274 " -channel type apply option to select image channels\n"
275 " -colorspace type alternate image colorspace\n"
276 " -comment string annotate image with comment\n"
277 " -compose operator composite operator\n"
278 " -compress type type of pixel compression when writing the image\n"
279 " -define format:option\n"
280 " define one or more image format options\n"
281 " -depth value image depth\n"
282 " -density geometry horizontal and vertical density of the image\n"
283 " -display server get image or font from this X server\n"
284 " -dispose method layer disposal method\n"
285 " -dither method apply error diffusion to image\n"
286 " -encoding type text encoding type\n"
287 " -endian type endianness (MSB or LSB) of the image\n"
288 " -filter type use this filter when resizing an image\n"
289 " -font name render text with this font\n"
290 " -format \"string\" output formatted image characteristics\n"
291 " -gravity type which direction to gravitate towards\n"
292 " -green-primary point chromaticity green primary point\n"
293 " -interlace type type of image interlacing scheme\n"
294 " -interpolate method pixel color interpolation method\n"
295 " -label string assign a label to an image\n"
296 " -limit type value pixel cache resource limit\n"
297 " -matte store matte channel if the image has one\n"
298 " -monitor monitor progress\n"
299 " -page geometry size and location of an image canvas (setting)\n"
300 " -pointsize value font point size\n"
301 " -quality value JPEG/MIFF/PNG compression level\n"
302 " -quiet suppress all warning messages\n"
303 " -red-primary point chromaticity red primary point\n"
304 " -regard-warnings pay attention to warning messages\n"
305 " -repage geometry size and location of an image canvas (operator)\n"
306 " -respect-parentheses settings remain in effect until parenthesis boundary\n"
307 " -sampling-factor geometry\n"
308 " horizontal and vertical sampling factor\n"
309 " -scene value image scene number\n"
310 " -seed value seed a new sequence of pseudo-random numbers\n"
311 " -size geometry width and height of image\n"
312 " -support factor resize support: > 1.0 is blurry, < 1.0 is sharp\n"
313 " -synchronize synchronize image to storage device\n"
314 " -taint declare the image as modified\n"
315 " -transparent-color color\n"
316 " transparent color\n"
317 " -treedepth value color tree depth\n"
318 " -tile repeat composite operation across and down image\n"
319 " -units type the units of image resolution\n"
320 " -verbose print detailed information about the image\n"
321 " -virtual-pixel method\n"
322 " virtual pixel access method\n"
323 " -white-point point chromaticity white point",
324 stack_operators[] =
325 " -swap indexes swap two images in the image sequence";
326
327 ListMagickVersion(stdout);
328 (void) printf("Usage: %s [options ...] image [options ...] composite\n"
329 " [ [options ...] mask ] [options ...] composite\n",
330 GetClientName());
331 (void) printf("\nImage Settings:\n");
332 (void) puts(settings);
333 (void) printf("\nImage Operators:\n");
334 (void) puts(operators);
335 (void) printf("\nImage Stack Operators:\n");
336 (void) puts(stack_operators);
337 (void) printf("\nMiscellaneous Options:\n");
338 (void) puts(miscellaneous);
339 (void) printf(
340 "\nBy default, the image format of `file' is determined by its magic\n");
341 (void) printf(
342 "number. To specify a particular image format, precede the filename\n");
343 (void) printf(
344 "with an image format name and a colon (i.e. ps:image) or specify the\n");
345 (void) printf(
346 "image type as the filename suffix (i.e. image.ps). Specify 'file' as\n");
347 (void) printf("'-' for standard input or output.\n");
348 return(MagickTrue);
349 }
350
GetCompositeOptions(CompositeOptions * composite_options)351 static void GetCompositeOptions(CompositeOptions *composite_options)
352 {
353 (void) memset(composite_options,0,sizeof(*composite_options));
354 composite_options->channel=DefaultChannels;
355 composite_options->compose=OverCompositeOp;
356 }
357
RelinquishCompositeOptions(CompositeOptions * composite_options)358 static void RelinquishCompositeOptions(CompositeOptions *composite_options)
359 {
360 if (composite_options->compose_args != (char *) NULL)
361 composite_options->compose_args=(char *)
362 RelinquishMagickMemory(composite_options->compose_args);
363 if (composite_options->geometry != (char *) NULL)
364 composite_options->geometry=(char *)
365 RelinquishMagickMemory(composite_options->geometry);
366 }
367
CompositeImageCommand(ImageInfo * image_info,int argc,char ** argv,char ** metadata,ExceptionInfo * exception)368 WandExport MagickBooleanType CompositeImageCommand(ImageInfo *image_info,
369 int argc,char **argv,char **metadata,ExceptionInfo *exception)
370 {
371 #define NotInitialized (unsigned int) (~0)
372 #define DestroyComposite() \
373 { \
374 RelinquishCompositeOptions(&composite_options); \
375 DestroyImageStack(); \
376 for (i=0; i < (ssize_t) argc; i++) \
377 argv[i]=DestroyString(argv[i]); \
378 argv=(char **) RelinquishMagickMemory(argv); \
379 }
380 #define ThrowCompositeException(asperity,tag,option) \
381 { \
382 (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
383 option == (char *) NULL ? GetExceptionMessage(errno) : option); \
384 DestroyComposite(); \
385 return(MagickFalse); \
386 }
387 #define ThrowCompositeInvalidArgumentException(option,argument) \
388 { \
389 (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \
390 "InvalidArgument","`%s': %s",option,argument); \
391 DestroyComposite(); \
392 return(MagickFalse); \
393 }
394
395 char
396 *filename,
397 *option;
398
399 CompositeOptions
400 composite_options;
401
402 const char
403 *format;
404
405 Image
406 *composite_image,
407 *image,
408 *images,
409 *mask_image;
410
411 ImageStack
412 image_stack[MaxImageStackDepth+1];
413
414 MagickBooleanType
415 fire,
416 pend,
417 respect_parenthesis;
418
419 MagickStatusType
420 status;
421
422 ssize_t
423 i;
424
425 ssize_t
426 j,
427 k;
428
429 /*
430 Set default.
431 */
432 assert(image_info != (ImageInfo *) NULL);
433 assert(image_info->signature == MagickCoreSignature);
434 if (image_info->debug != MagickFalse)
435 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
436 assert(exception != (ExceptionInfo *) NULL);
437 if (argc == 2)
438 {
439 option=argv[1];
440 if ((LocaleCompare("version",option+1) == 0) ||
441 (LocaleCompare("-version",option+1) == 0))
442 {
443 ListMagickVersion(stdout);
444 return(MagickTrue);
445 }
446 }
447 if (argc < 4)
448 return(CompositeUsage());
449 GetCompositeOptions(&composite_options);
450 filename=(char *) NULL;
451 format="%w,%h,%m";
452 j=1;
453 k=0;
454 NewImageStack();
455 option=(char *) NULL;
456 pend=MagickFalse;
457 respect_parenthesis=MagickFalse;
458 status=MagickTrue;
459 /*
460 Check command syntax.
461 */
462 composite_image=NewImageList();
463 image=NewImageList();
464 mask_image=NewImageList();
465 ReadCommandlLine(argc,&argv);
466 status=ExpandFilenames(&argc,&argv);
467 if (status == MagickFalse)
468 ThrowCompositeException(ResourceLimitError,"MemoryAllocationFailed",
469 GetExceptionMessage(errno));
470 for (i=1; i < (ssize_t) (argc-1); i++)
471 {
472 option=argv[i];
473 if (LocaleCompare(option,"(") == 0)
474 {
475 FireImageStack(MagickFalse,MagickTrue,pend);
476 if (k == MaxImageStackDepth)
477 ThrowCompositeException(OptionError,"ParenthesisNestedTooDeeply",
478 option);
479 PushImageStack();
480 continue;
481 }
482 if (LocaleCompare(option,")") == 0)
483 {
484 FireImageStack(MagickFalse,MagickTrue,MagickTrue);
485 if (k == 0)
486 ThrowCompositeException(OptionError,"UnableToParseExpression",option);
487 PopImageStack();
488 continue;
489 }
490 if (IsCommandOption(option) == MagickFalse)
491 {
492 Image
493 *images;
494
495 /*
496 Read input image.
497 */
498 FireImageStack(MagickFalse,MagickFalse,pend);
499 filename=argv[i];
500 if ((LocaleCompare(filename,"--") == 0) && (i < (ssize_t) (argc-1)))
501 filename=argv[++i];
502 (void) SetImageOption(image_info,"filename",filename);
503 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
504 images=ReadImages(image_info,exception);
505 status&=(images != (Image *) NULL) &&
506 (exception->severity < ErrorException);
507 if (images == (Image *) NULL)
508 continue;
509 AppendImageStack(images);
510 continue;
511 }
512 pend=image != (Image *) NULL ? MagickTrue : MagickFalse;
513 switch (*(option+1))
514 {
515 case 'a':
516 {
517 if (LocaleCompare("affine",option+1) == 0)
518 {
519 if (*option == '+')
520 break;
521 i++;
522 if (i == (ssize_t) argc)
523 ThrowCompositeException(OptionError,"MissingArgument",option);
524 if (IsGeometry(argv[i]) == MagickFalse)
525 ThrowCompositeInvalidArgumentException(option,argv[i]);
526 break;
527 }
528 if (LocaleCompare("alpha",option+1) == 0)
529 {
530 ssize_t
531 type;
532
533 if (*option == '+')
534 break;
535 i++;
536 if (i == (ssize_t) argc)
537 ThrowCompositeException(OptionError,"MissingArgument",option);
538 type=ParseCommandOption(MagickAlphaOptions,MagickFalse,argv[i]);
539 if (type < 0)
540 ThrowCompositeException(OptionError,
541 "UnrecognizedAlphaChannelType",argv[i]);
542 break;
543 }
544 if (LocaleCompare("authenticate",option+1) == 0)
545 {
546 if (*option == '+')
547 break;
548 i++;
549 if (i == (ssize_t) argc)
550 ThrowCompositeException(OptionError,"MissingArgument",option);
551 break;
552 }
553 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
554 }
555 case 'b':
556 {
557 if (LocaleCompare("background",option+1) == 0)
558 {
559 if (*option == '+')
560 break;
561 i++;
562 if (i == (ssize_t) argc)
563 ThrowCompositeException(OptionError,"MissingArgument",option);
564 break;
565 }
566 if (LocaleCompare("blend",option+1) == 0)
567 {
568 (void) CloneString(&composite_options.compose_args,(char *) NULL);
569 if (*option == '+')
570 break;
571 i++;
572 if (i == (ssize_t) argc)
573 ThrowCompositeException(OptionError,"MissingArgument",option);
574 if (IsGeometry(argv[i]) == MagickFalse)
575 ThrowCompositeInvalidArgumentException(option,argv[i]);
576 (void) CloneString(&composite_options.compose_args,argv[i]);
577 composite_options.compose=BlendCompositeOp;
578 break;
579 }
580 if (LocaleCompare("blur",option+1) == 0)
581 {
582 (void) CloneString(&composite_options.compose_args,(char *) NULL);
583 if (*option == '+')
584 break;
585 i++;
586 if (i == (ssize_t) argc)
587 ThrowCompositeException(OptionError,"MissingArgument",option);
588 if (IsGeometry(argv[i]) == MagickFalse)
589 ThrowCompositeInvalidArgumentException(option,argv[i]);
590 (void) CloneString(&composite_options.compose_args,argv[i]);
591 composite_options.compose=BlurCompositeOp;
592 break;
593 }
594 if (LocaleCompare("blue-primary",option+1) == 0)
595 {
596 if (*option == '+')
597 break;
598 i++;
599 if (i == (ssize_t) argc)
600 ThrowCompositeException(OptionError,"MissingArgument",option);
601 if (IsGeometry(argv[i]) == MagickFalse)
602 ThrowCompositeInvalidArgumentException(option,argv[i]);
603 break;
604 }
605 if (LocaleCompare("border",option+1) == 0)
606 {
607 if (*option == '+')
608 break;
609 i++;
610 if (i == (ssize_t) argc)
611 ThrowCompositeException(OptionError,"MissingArgument",option);
612 if (IsGeometry(argv[i]) == MagickFalse)
613 ThrowCompositeInvalidArgumentException(option,argv[i]);
614 break;
615 }
616 if (LocaleCompare("bordercolor",option+1) == 0)
617 {
618 if (*option == '+')
619 break;
620 i++;
621 if (i == (ssize_t) argc)
622 ThrowCompositeException(OptionError,"MissingArgument",option);
623 break;
624 }
625 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
626 }
627 case 'c':
628 {
629 if (LocaleCompare("cache",option+1) == 0)
630 {
631 if (*option == '+')
632 break;
633 i++;
634 if (i == (ssize_t) argc)
635 ThrowCompositeException(OptionError,"MissingArgument",option);
636 if (IsGeometry(argv[i]) == MagickFalse)
637 ThrowCompositeInvalidArgumentException(option,argv[i]);
638 break;
639 }
640 if (LocaleCompare("channel",option+1) == 0)
641 {
642 ssize_t
643 channel;
644
645 if (*option == '+')
646 {
647 composite_options.channel=DefaultChannels;
648 break;
649 }
650 i++;
651 if (i == (ssize_t) argc)
652 ThrowCompositeException(OptionError,"MissingArgument",option);
653 channel=ParseChannelOption(argv[i]);
654 if (channel < 0)
655 ThrowCompositeException(OptionError,"UnrecognizedChannelType",
656 argv[i]);
657 composite_options.channel=(ChannelType) channel;
658 break;
659 }
660 if (LocaleCompare("colors",option+1) == 0)
661 {
662 if (*option == '+')
663 break;
664 i++;
665 if (i == (ssize_t) argc)
666 ThrowCompositeException(OptionError,"MissingArgument",option);
667 if (IsGeometry(argv[i]) == MagickFalse)
668 ThrowCompositeInvalidArgumentException(option,argv[i]);
669 break;
670 }
671 if (LocaleCompare("colorspace",option+1) == 0)
672 {
673 ssize_t
674 colorspace;
675
676 if (*option == '+')
677 break;
678 i++;
679 if (i == (ssize_t) argc)
680 ThrowCompositeException(OptionError,"MissingArgument",option);
681 colorspace=ParseCommandOption(MagickColorspaceOptions,
682 MagickFalse,argv[i]);
683 if (colorspace < 0)
684 ThrowCompositeException(OptionError,"UnrecognizedColorspace",
685 argv[i]);
686 break;
687 }
688 if (LocaleCompare("comment",option+1) == 0)
689 {
690 if (*option == '+')
691 break;
692 i++;
693 if (i == (ssize_t) argc)
694 ThrowCompositeException(OptionError,"MissingArgument",option);
695 break;
696 }
697 if (LocaleCompare("compose",option+1) == 0)
698 {
699 ssize_t
700 compose;
701
702 composite_options.compose=UndefinedCompositeOp;
703 if (*option == '+')
704 break;
705 i++;
706 if (i == (ssize_t) argc)
707 ThrowCompositeException(OptionError,"MissingArgument",option);
708 compose=ParseCommandOption(MagickComposeOptions,MagickFalse,
709 argv[i]);
710 if (compose < 0)
711 ThrowCompositeException(OptionError,"UnrecognizedComposeOperator",
712 argv[i]);
713 composite_options.compose=(CompositeOperator) compose;
714 break;
715 }
716 if (LocaleCompare("compress",option+1) == 0)
717 {
718 ssize_t
719 compress;
720
721 if (*option == '+')
722 break;
723 i++;
724 if (i == (ssize_t) argc)
725 ThrowCompositeException(OptionError,"MissingArgument",option);
726 compress=ParseCommandOption(MagickCompressOptions,MagickFalse,
727 argv[i]);
728 if (compress < 0)
729 ThrowCompositeException(OptionError,
730 "UnrecognizedImageCompression",argv[i]);
731 break;
732 }
733 if (LocaleCompare("concurrent",option+1) == 0)
734 break;
735 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
736 }
737 case 'd':
738 {
739 if (LocaleCompare("debug",option+1) == 0)
740 {
741 ssize_t
742 event;
743
744 if (*option == '+')
745 break;
746 i++;
747 if (i == (ssize_t) argc)
748 ThrowCompositeException(OptionError,"MissingArgument",option);
749 event=ParseCommandOption(MagickLogEventOptions,MagickFalse,argv[i]);
750 if (event < 0)
751 ThrowCompositeException(OptionError,"UnrecognizedEventType",
752 argv[i]);
753 (void) SetLogEventMask(argv[i]);
754 break;
755 }
756 if (LocaleCompare("decipher",option+1) == 0)
757 {
758 if (*option == '+')
759 break;
760 i++;
761 if (i == (ssize_t) argc)
762 ThrowCompositeException(OptionError,"MissingArgument",option);
763 break;
764 }
765 if (LocaleCompare("define",option+1) == 0)
766 {
767 i++;
768 if (i == (ssize_t) argc)
769 ThrowCompositeException(OptionError,"MissingArgument",option);
770 if (*option == '+')
771 {
772 const char
773 *define;
774
775 define=GetImageOption(image_info,argv[i]);
776 if (define == (const char *) NULL)
777 ThrowCompositeException(OptionError,"NoSuchOption",argv[i]);
778 break;
779 }
780 break;
781 }
782 if (LocaleCompare("density",option+1) == 0)
783 {
784 if (*option == '+')
785 break;
786 i++;
787 if (i == (ssize_t) argc)
788 ThrowCompositeException(OptionError,"MissingArgument",option);
789 if (IsGeometry(argv[i]) == MagickFalse)
790 ThrowCompositeInvalidArgumentException(option,argv[i]);
791 break;
792 }
793 if (LocaleCompare("depth",option+1) == 0)
794 {
795 if (*option == '+')
796 break;
797 i++;
798 if (i == (ssize_t) argc)
799 ThrowCompositeException(OptionError,"MissingArgument",option);
800 if (IsGeometry(argv[i]) == MagickFalse)
801 ThrowCompositeInvalidArgumentException(option,argv[i]);
802 break;
803 }
804 if (LocaleCompare("displace",option+1) == 0)
805 {
806 (void) CloneString(&composite_options.compose_args,(char *) NULL);
807 if (*option == '+')
808 break;
809 i++;
810 if (i == (ssize_t) argc)
811 ThrowCompositeException(OptionError,"MissingArgument",option);
812 if (IsGeometry(argv[i]) == MagickFalse)
813 ThrowCompositeInvalidArgumentException(option,argv[i]);
814 (void) CloneString(&composite_options.compose_args,argv[i]);
815 composite_options.compose=DisplaceCompositeOp;
816 break;
817 }
818 if (LocaleCompare("display",option+1) == 0)
819 {
820 if (*option == '+')
821 break;
822 i++;
823 if (i == (ssize_t) argc)
824 ThrowCompositeException(OptionError,"MissingArgument",option);
825 break;
826 }
827 if (LocaleCompare("dispose",option+1) == 0)
828 {
829 ssize_t
830 dispose;
831
832 if (*option == '+')
833 break;
834 i++;
835 if (i == (ssize_t) argc)
836 ThrowCompositeException(OptionError,"MissingArgument",option);
837 dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse,argv[i]);
838 if (dispose < 0)
839 ThrowCompositeException(OptionError,"UnrecognizedDisposeMethod",
840 argv[i]);
841 break;
842 }
843 if (LocaleCompare("dissolve",option+1) == 0)
844 {
845 (void) CloneString(&composite_options.compose_args,(char *) NULL);
846 if (*option == '+')
847 break;
848 i++;
849 if (i == (ssize_t) argc)
850 ThrowCompositeException(OptionError,"MissingArgument",option);
851 if (IsGeometry(argv[i]) == MagickFalse)
852 ThrowCompositeInvalidArgumentException(option,argv[i]);
853 (void) CloneString(&composite_options.compose_args,argv[i]);
854 composite_options.compose=DissolveCompositeOp;
855 break;
856 }
857 if (LocaleCompare("distort",option+1) == 0)
858 {
859 (void) CloneString(&composite_options.compose_args,(char *) NULL);
860 if (*option == '+')
861 break;
862 i++;
863 if (i == (ssize_t) argc)
864 ThrowCompositeException(OptionError,"MissingArgument",option);
865 if (IsGeometry(argv[i]) == MagickFalse)
866 ThrowCompositeInvalidArgumentException(option,argv[i]);
867 (void) CloneString(&composite_options.compose_args,argv[i]);
868 composite_options.compose=DistortCompositeOp;
869 break;
870 }
871 if (LocaleCompare("dither",option+1) == 0)
872 {
873 ssize_t
874 method;
875
876 if (*option == '+')
877 break;
878 i++;
879 if (i == (ssize_t) argc)
880 ThrowCompositeException(OptionError,"MissingArgument",option);
881 method=ParseCommandOption(MagickDitherOptions,MagickFalse,argv[i]);
882 if (method < 0)
883 ThrowCompositeException(OptionError,"UnrecognizedDitherMethod",
884 argv[i]);
885 break;
886 }
887 if (LocaleCompare("duration",option+1) == 0)
888 {
889 if (*option == '+')
890 break;
891 i++;
892 if (i == (ssize_t) argc)
893 ThrowCompositeException(OptionError,"MissingArgument",option);
894 if (IsGeometry(argv[i]) == MagickFalse)
895 ThrowCompositeInvalidArgumentException(option,argv[i]);
896 break;
897 }
898 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
899 }
900 case 'e':
901 {
902 if (LocaleCompare("encipher",option+1) == 0)
903 {
904 if (*option == '+')
905 break;
906 i++;
907 if (i == (ssize_t) argc)
908 ThrowCompositeException(OptionError,"MissingArgument",option);
909 break;
910 }
911 if (LocaleCompare("encoding",option+1) == 0)
912 {
913 if (*option == '+')
914 break;
915 i++;
916 if (i == (ssize_t) argc)
917 ThrowCompositeException(OptionError,"MissingArgument",option);
918 break;
919 }
920 if (LocaleCompare("endian",option+1) == 0)
921 {
922 ssize_t
923 endian;
924
925 if (*option == '+')
926 break;
927 i++;
928 if (i == (ssize_t) argc)
929 ThrowCompositeException(OptionError,"MissingArgument",option);
930 endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
931 argv[i]);
932 if (endian < 0)
933 ThrowCompositeException(OptionError,"UnrecognizedEndianType",
934 argv[i]);
935 break;
936 }
937 if (LocaleCompare("extract",option+1) == 0)
938 {
939 if (*option == '+')
940 break;
941 i++;
942 if (i == (ssize_t) argc)
943 ThrowCompositeException(OptionError,"MissingArgument",option);
944 if (IsGeometry(argv[i]) == MagickFalse)
945 ThrowCompositeInvalidArgumentException(option,argv[i]);
946 break;
947 }
948 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
949 }
950 case 'f':
951 {
952 if (LocaleCompare("filter",option+1) == 0)
953 {
954 ssize_t
955 filter;
956
957 if (*option == '+')
958 break;
959 i++;
960 if (i == (ssize_t) argc)
961 ThrowCompositeException(OptionError,"MissingArgument",option);
962 filter=ParseCommandOption(MagickFilterOptions,MagickFalse,argv[i]);
963 if (filter < 0)
964 ThrowCompositeException(OptionError,"UnrecognizedImageFilter",
965 argv[i]);
966 break;
967 }
968 if (LocaleCompare("font",option+1) == 0)
969 {
970 if (*option == '+')
971 break;
972 i++;
973 if (i == (ssize_t) argc)
974 ThrowCompositeException(OptionError,"MissingArgument",option);
975 break;
976 }
977 if (LocaleCompare("format",option+1) == 0)
978 {
979 if (*option == '+')
980 break;
981 i++;
982 if (i == (ssize_t) argc)
983 ThrowCompositeException(OptionError,"MissingArgument",option);
984 format=argv[i];
985 break;
986 }
987 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
988 }
989 case 'g':
990 {
991 if (LocaleCompare("geometry",option+1) == 0)
992 {
993 (void) CloneString(&composite_options.geometry,(char *) NULL);
994 if (*option == '+')
995 break;
996 i++;
997 if (i == (ssize_t) argc)
998 ThrowCompositeException(OptionError,"MissingArgument",option);
999 if (IsGeometry(argv[i]) == MagickFalse)
1000 ThrowCompositeInvalidArgumentException(option,argv[i]);
1001 (void) CloneString(&composite_options.geometry,argv[i]);
1002 break;
1003 }
1004 if (LocaleCompare("gravity",option+1) == 0)
1005 {
1006 ssize_t
1007 gravity;
1008
1009 composite_options.gravity=UndefinedGravity;
1010 if (*option == '+')
1011 break;
1012 i++;
1013 if (i == (ssize_t) argc)
1014 ThrowCompositeException(OptionError,"MissingArgument",option);
1015 gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
1016 argv[i]);
1017 if (gravity < 0)
1018 ThrowCompositeException(OptionError,"UnrecognizedGravityType",
1019 argv[i]);
1020 composite_options.gravity=(GravityType) gravity;
1021 break;
1022 }
1023 if (LocaleCompare("green-primary",option+1) == 0)
1024 {
1025 if (*option == '+')
1026 break;
1027 i++;
1028 if (i == (ssize_t) argc)
1029 ThrowCompositeException(OptionError,"MissingArgument",option);
1030 if (IsGeometry(argv[i]) == MagickFalse)
1031 ThrowCompositeInvalidArgumentException(option,argv[i]);
1032 break;
1033 }
1034 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1035 }
1036 case 'h':
1037 {
1038 if ((LocaleCompare("help",option+1) == 0) ||
1039 (LocaleCompare("-help",option+1) == 0))
1040 {
1041 DestroyComposite();
1042 return(CompositeUsage());
1043 }
1044 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1045 }
1046 case 'i':
1047 {
1048 if (LocaleCompare("identify",option+1) == 0)
1049 break;
1050 if (LocaleCompare("interlace",option+1) == 0)
1051 {
1052 ssize_t
1053 interlace;
1054
1055 if (*option == '+')
1056 break;
1057 i++;
1058 if (i == (ssize_t) argc)
1059 ThrowCompositeException(OptionError,"MissingArgument",option);
1060 interlace=ParseCommandOption(MagickInterlaceOptions,MagickFalse,
1061 argv[i]);
1062 if (interlace < 0)
1063 ThrowCompositeException(OptionError,
1064 "UnrecognizedInterlaceType",argv[i]);
1065 break;
1066 }
1067 if (LocaleCompare("interpolate",option+1) == 0)
1068 {
1069 ssize_t
1070 interpolate;
1071
1072 if (*option == '+')
1073 break;
1074 i++;
1075 if (i == (ssize_t) argc)
1076 ThrowCompositeException(OptionError,"MissingArgument",option);
1077 interpolate=ParseCommandOption(MagickInterpolateOptions,MagickFalse,
1078 argv[i]);
1079 if (interpolate < 0)
1080 ThrowCompositeException(OptionError,
1081 "UnrecognizedInterpolateMethod",argv[i]);
1082 break;
1083 }
1084 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1085 }
1086 case 'l':
1087 {
1088 if (LocaleCompare("label",option+1) == 0)
1089 {
1090 if (*option == '+')
1091 break;
1092 i++;
1093 if (i == (ssize_t) argc)
1094 ThrowCompositeException(OptionError,"MissingArgument",option);
1095 break;
1096 }
1097 if (LocaleCompare("limit",option+1) == 0)
1098 {
1099 char
1100 *p;
1101
1102 double
1103 value;
1104
1105 ssize_t
1106 resource;
1107
1108 if (*option == '+')
1109 break;
1110 i++;
1111 if (i == (ssize_t) argc)
1112 ThrowCompositeException(OptionError,"MissingArgument",option);
1113 resource=ParseCommandOption(MagickResourceOptions,MagickFalse,
1114 argv[i]);
1115 if (resource < 0)
1116 ThrowCompositeException(OptionError,"UnrecognizedResourceType",
1117 argv[i]);
1118 i++;
1119 if (i == (ssize_t) argc)
1120 ThrowCompositeException(OptionError,"MissingArgument",option);
1121 value=StringToDouble(argv[i],&p);
1122 (void) value;
1123 if ((p == argv[i]) && (LocaleCompare("unlimited",argv[i]) != 0))
1124 ThrowCompositeInvalidArgumentException(option,argv[i]);
1125 break;
1126 }
1127 if (LocaleCompare("list",option+1) == 0)
1128 {
1129 ssize_t
1130 list;
1131
1132 if (*option == '+')
1133 break;
1134 i++;
1135 if (i == (ssize_t) argc)
1136 ThrowCompositeException(OptionError,"MissingArgument",option);
1137 list=ParseCommandOption(MagickListOptions,MagickFalse,argv[i]);
1138 if (list < 0)
1139 ThrowCompositeException(OptionError,"UnrecognizedListType",
1140 argv[i]);
1141 status=MogrifyImageInfo(image_info,(int) (i-j+1),(const char **)
1142 argv+j,exception);
1143 DestroyComposite();
1144 return(status == 0 ? MagickFalse : MagickTrue);
1145 }
1146 if (LocaleCompare("log",option+1) == 0)
1147 {
1148 if (*option == '+')
1149 break;
1150 i++;
1151 if ((i == (ssize_t) argc) || (strchr(argv[i],'%') == (char *) NULL))
1152 ThrowCompositeException(OptionError,"MissingArgument",option);
1153 break;
1154 }
1155 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1156 }
1157 case 'm':
1158 {
1159 if (LocaleCompare("matte",option+1) == 0)
1160 break;
1161 if (LocaleCompare("monitor",option+1) == 0)
1162 break;
1163 if (LocaleCompare("monochrome",option+1) == 0)
1164 break;
1165 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1166 }
1167 case 'n':
1168 {
1169 if (LocaleCompare("negate",option+1) == 0)
1170 break;
1171 if (LocaleCompare("noop",option+1) == 0)
1172 break;
1173 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1174 }
1175 case 'p':
1176 {
1177 if (LocaleCompare("page",option+1) == 0)
1178 {
1179 if (*option == '+')
1180 break;
1181 i++;
1182 if (i == (ssize_t) argc)
1183 ThrowCompositeException(OptionError,"MissingArgument",option);
1184 break;
1185 }
1186 if (LocaleCompare("pointsize",option+1) == 0)
1187 {
1188 if (*option == '+')
1189 break;
1190 i++;
1191 if (i == (ssize_t) argc)
1192 ThrowCompositeException(OptionError,"MissingArgument",option);
1193 if (IsGeometry(argv[i]) == MagickFalse)
1194 ThrowCompositeInvalidArgumentException(option,argv[i]);
1195 break;
1196 }
1197 if (LocaleCompare("process",option+1) == 0)
1198 {
1199 if (*option == '+')
1200 break;
1201 i++;
1202 if (i == (ssize_t) argc)
1203 ThrowCompositeException(OptionError,"MissingArgument",option);
1204 break;
1205 }
1206 if (LocaleCompare("profile",option+1) == 0)
1207 {
1208 i++;
1209 if (i == (ssize_t) argc)
1210 ThrowCompositeException(OptionError,"MissingArgument",option);
1211 break;
1212 }
1213 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1214 }
1215 case 'q':
1216 {
1217 if (LocaleCompare("quality",option+1) == 0)
1218 {
1219 if (*option == '+')
1220 break;
1221 i++;
1222 if (i == (ssize_t) argc)
1223 ThrowCompositeException(OptionError,"MissingArgument",option);
1224 if (IsGeometry(argv[i]) == MagickFalse)
1225 ThrowCompositeInvalidArgumentException(option,argv[i]);
1226 break;
1227 }
1228 if (LocaleCompare("quantize",option+1) == 0)
1229 {
1230 ssize_t
1231 colorspace;
1232
1233 if (*option == '+')
1234 break;
1235 i++;
1236 if (i == (ssize_t) argc)
1237 ThrowCompositeException(OptionError,"MissingArgument",option);
1238 colorspace=ParseCommandOption(MagickColorspaceOptions,
1239 MagickFalse,argv[i]);
1240 if (colorspace < 0)
1241 ThrowCompositeException(OptionError,"UnrecognizedColorspace",
1242 argv[i]);
1243 break;
1244 }
1245 if (LocaleCompare("quiet",option+1) == 0)
1246 break;
1247 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1248 }
1249 case 'r':
1250 {
1251 if (LocaleCompare("red-primary",option+1) == 0)
1252 {
1253 if (*option == '+')
1254 break;
1255 i++;
1256 if (i == (ssize_t) argc)
1257 ThrowCompositeException(OptionError,"MissingArgument",option);
1258 if (IsGeometry(argv[i]) == MagickFalse)
1259 ThrowCompositeInvalidArgumentException(option,argv[i]);
1260 break;
1261 }
1262 if (LocaleCompare("regard-warnings",option+1) == 0)
1263 break;
1264 if (LocaleCompare("render",option+1) == 0)
1265 break;
1266 if (LocaleCompare("repage",option+1) == 0)
1267 {
1268 if (*option == '+')
1269 break;
1270 i++;
1271 if (i == (ssize_t) argc)
1272 ThrowCompositeException(OptionError,"MissingArgument",option);
1273 if (IsGeometry(argv[i]) == MagickFalse)
1274 ThrowCompositeInvalidArgumentException(option,argv[i]);
1275 break;
1276 }
1277 if (LocaleNCompare("respect-parentheses",option+1,17) == 0)
1278 {
1279 respect_parenthesis=(*option == '-') ? MagickTrue : MagickFalse;
1280 break;
1281 }
1282 if (LocaleCompare("resize",option+1) == 0)
1283 {
1284 if (*option == '+')
1285 break;
1286 i++;
1287 if (i == (ssize_t) argc)
1288 ThrowCompositeException(OptionError,"MissingArgument",option);
1289 if (IsGeometry(argv[i]) == MagickFalse)
1290 ThrowCompositeInvalidArgumentException(option,argv[i]);
1291 break;
1292 }
1293 if (LocaleCompare("rotate",option+1) == 0)
1294 {
1295 i++;
1296 if (i == (ssize_t) argc)
1297 ThrowCompositeException(OptionError,"MissingArgument",option);
1298 if (IsGeometry(argv[i]) == MagickFalse)
1299 ThrowCompositeInvalidArgumentException(option,argv[i]);
1300 break;
1301 }
1302 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1303 }
1304 case 's':
1305 {
1306 if (LocaleCompare("sampling-factor",option+1) == 0)
1307 {
1308 if (*option == '+')
1309 break;
1310 i++;
1311 if (i == (ssize_t) argc)
1312 ThrowCompositeException(OptionError,"MissingArgument",option);
1313 if (IsGeometry(argv[i]) == MagickFalse)
1314 ThrowCompositeInvalidArgumentException(option,argv[i]);
1315 break;
1316 }
1317 if (LocaleCompare("scene",option+1) == 0)
1318 {
1319 if (*option == '+')
1320 break;
1321 i++;
1322 if (i == (ssize_t) argc)
1323 ThrowCompositeException(OptionError,"MissingArgument",option);
1324 if (IsGeometry(argv[i]) == MagickFalse)
1325 ThrowCompositeInvalidArgumentException(option,argv[i]);
1326 break;
1327 }
1328 if (LocaleCompare("seed",option+1) == 0)
1329 {
1330 if (*option == '+')
1331 break;
1332 i++;
1333 if (i == (ssize_t) argc)
1334 ThrowCompositeException(OptionError,"MissingArgument",option);
1335 if (IsGeometry(argv[i]) == MagickFalse)
1336 ThrowCompositeInvalidArgumentException(option,argv[i]);
1337 break;
1338 }
1339 if (LocaleCompare("sharpen",option+1) == 0)
1340 {
1341 i++;
1342 if (i == (ssize_t) argc)
1343 ThrowCompositeException(OptionError,"MissingArgument",option);
1344 if (IsGeometry(argv[i]) == MagickFalse)
1345 ThrowCompositeInvalidArgumentException(option,argv[i]);
1346 break;
1347 }
1348 if (LocaleCompare("shave",option+1) == 0)
1349 {
1350 if (*option == '+')
1351 break;
1352 i++;
1353 if (i == (ssize_t) argc)
1354 ThrowCompositeException(OptionError,"MissingArgument",option);
1355 if (IsGeometry(argv[i]) == MagickFalse)
1356 ThrowCompositeInvalidArgumentException(option,argv[i]);
1357 break;
1358 }
1359 if (LocaleCompare("size",option+1) == 0)
1360 {
1361 if (*option == '+')
1362 break;
1363 i++;
1364 if (i == (ssize_t) argc)
1365 ThrowCompositeException(OptionError,"MissingArgument",option);
1366 if (IsGeometry(argv[i]) == MagickFalse)
1367 ThrowCompositeInvalidArgumentException(option,argv[i]);
1368 break;
1369 }
1370 if (LocaleCompare("stegano",option+1) == 0)
1371 {
1372 composite_options.stegano=0;
1373 if (*option == '+')
1374 break;
1375 i++;
1376 if (i == (ssize_t) argc)
1377 ThrowCompositeException(OptionError,"MissingArgument",option);
1378 if (IsGeometry(argv[i]) == MagickFalse)
1379 ThrowCompositeInvalidArgumentException(option,argv[i]);
1380 composite_options.stegano=(ssize_t) StringToLong(argv[i])+1;
1381 break;
1382 }
1383 if (LocaleCompare("stereo",option+1) == 0)
1384 {
1385 MagickStatusType
1386 flags;
1387
1388 composite_options.stereo=MagickFalse;
1389 if (*option == '+')
1390 break;
1391 i++;
1392 if (i == (ssize_t) argc)
1393 ThrowCompositeException(OptionError,"MissingArgument",option);
1394 if (IsGeometry(argv[i]) == MagickFalse)
1395 ThrowCompositeInvalidArgumentException(option,argv[i]);
1396 flags=ParseAbsoluteGeometry(argv[i],&composite_options.offset);
1397 if ((flags & YValue) == 0)
1398 composite_options.offset.y=composite_options.offset.x;
1399 composite_options.stereo=MagickTrue;
1400 break;
1401 }
1402 if (LocaleCompare("strip",option+1) == 0)
1403 break;
1404 if (LocaleCompare("support",option+1) == 0)
1405 {
1406 i++; /* deprecated */
1407 break;
1408 }
1409 if (LocaleCompare("swap",option+1) == 0)
1410 {
1411 if (*option == '+')
1412 break;
1413 i++;
1414 if (i == (ssize_t) argc)
1415 ThrowCompositeException(OptionError,"MissingArgument",option);
1416 if (IsGeometry(argv[i]) == MagickFalse)
1417 ThrowCompositeInvalidArgumentException(option,argv[i]);
1418 break;
1419 }
1420 if (LocaleCompare("synchronize",option+1) == 0)
1421 break;
1422 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1423 }
1424 case 't':
1425 {
1426 if (LocaleCompare("taint",option+1) == 0)
1427 break;
1428 if (LocaleCompare("thumbnail",option+1) == 0)
1429 {
1430 if (*option == '+')
1431 break;
1432 i++;
1433 if (i == (ssize_t) argc)
1434 ThrowCompositeException(OptionError,"MissingArgument",option);
1435 if (IsGeometry(argv[i]) == MagickFalse)
1436 ThrowCompositeInvalidArgumentException(option,argv[i]);
1437 break;
1438 }
1439 if (LocaleCompare("tile",option+1) == 0)
1440 {
1441 composite_options.tile=(*option == '-') ? MagickTrue : MagickFalse;
1442 (void) CopyMagickString(argv[i]+1,"sans",MaxTextExtent);
1443 break;
1444 }
1445 if (LocaleCompare("transform",option+1) == 0)
1446 break;
1447 if (LocaleCompare("transparent-color",option+1) == 0)
1448 {
1449 if (*option == '+')
1450 break;
1451 i++;
1452 if (i == (ssize_t) argc)
1453 ThrowCompositeException(OptionError,"MissingArgument",option);
1454 break;
1455 }
1456 if (LocaleCompare("treedepth",option+1) == 0)
1457 {
1458 if (*option == '+')
1459 break;
1460 i++;
1461 if (i == (ssize_t) argc)
1462 ThrowCompositeException(OptionError,"MissingArgument",option);
1463 if (IsGeometry(argv[i]) == MagickFalse)
1464 ThrowCompositeInvalidArgumentException(option,argv[i]);
1465 break;
1466 }
1467 if (LocaleCompare("type",option+1) == 0)
1468 {
1469 ssize_t
1470 type;
1471
1472 if (*option == '+')
1473 break;
1474 i++;
1475 if (i == (ssize_t) argc)
1476 ThrowCompositeException(OptionError,"MissingArgument",option);
1477 type=ParseCommandOption(MagickTypeOptions,MagickFalse,argv[i]);
1478 if (type < 0)
1479 ThrowCompositeException(OptionError,"UnrecognizedImageType",
1480 argv[i]);
1481 break;
1482 }
1483 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1484 }
1485 case 'u':
1486 {
1487 if (LocaleCompare("units",option+1) == 0)
1488 {
1489 ssize_t
1490 units;
1491
1492 if (*option == '+')
1493 break;
1494 i++;
1495 if (i == (ssize_t) argc)
1496 ThrowCompositeException(OptionError,"MissingArgument",option);
1497 units=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1498 argv[i]);
1499 if (units < 0)
1500 ThrowCompositeException(OptionError,"UnrecognizedUnitsType",
1501 argv[i]);
1502 break;
1503 }
1504 if (LocaleCompare("unsharp",option+1) == 0)
1505 {
1506 (void) CloneString(&composite_options.compose_args,(char *) NULL);
1507 if (*option == '+')
1508 break;
1509 i++;
1510 if (i == (ssize_t) argc)
1511 ThrowCompositeException(OptionError,"MissingArgument",option);
1512 if (IsGeometry(argv[i]) == MagickFalse)
1513 ThrowCompositeInvalidArgumentException(option,argv[i]);
1514 (void) CloneString(&composite_options.compose_args,argv[i]);
1515 composite_options.compose=ThresholdCompositeOp;
1516 break;
1517 }
1518 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1519 }
1520 case 'v':
1521 {
1522 if (LocaleCompare("verbose",option+1) == 0)
1523 break;
1524 if ((LocaleCompare("version",option+1) == 0) ||
1525 (LocaleCompare("-version",option+1) == 0))
1526 {
1527 ListMagickVersion(stdout);
1528 break;
1529 }
1530 if (LocaleCompare("virtual-pixel",option+1) == 0)
1531 {
1532 ssize_t
1533 method;
1534
1535 if (*option == '+')
1536 break;
1537 i++;
1538 if (i == (ssize_t) argc)
1539 ThrowCompositeException(OptionError,"MissingArgument",option);
1540 method=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1541 argv[i]);
1542 if (method < 0)
1543 ThrowCompositeException(OptionError,
1544 "UnrecognizedVirtualPixelMethod",argv[i]);
1545 break;
1546 }
1547 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1548 }
1549 case 'w':
1550 {
1551 if (LocaleCompare("watermark",option+1) == 0)
1552 {
1553 (void) CloneString(&composite_options.compose_args,(char *) NULL);
1554 if (*option == '+')
1555 break;
1556 i++;
1557 if (i == (ssize_t) argc)
1558 ThrowCompositeException(OptionError,"MissingArgument",option);
1559 if (IsGeometry(argv[i]) == MagickFalse)
1560 ThrowCompositeInvalidArgumentException(option,argv[i]);
1561 (void) CloneString(&composite_options.compose_args,argv[i]);
1562 composite_options.compose=ModulateCompositeOp;
1563 break;
1564 }
1565 if (LocaleCompare("white-point",option+1) == 0)
1566 {
1567 if (*option == '+')
1568 break;
1569 i++;
1570 if (i == (ssize_t) argc)
1571 ThrowCompositeException(OptionError,"MissingArgument",option);
1572 if (IsGeometry(argv[i]) == MagickFalse)
1573 ThrowCompositeInvalidArgumentException(option,argv[i]);
1574 break;
1575 }
1576 if (LocaleCompare("write",option+1) == 0)
1577 {
1578 i++;
1579 if (i == (ssize_t) argc)
1580 ThrowCompositeException(OptionError,"MissingArgument",option);
1581 break;
1582 }
1583 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1584 }
1585 case '?':
1586 break;
1587 default:
1588 ThrowCompositeException(OptionError,"UnrecognizedOption",option)
1589 }
1590 fire=(GetCommandOptionFlags(MagickCommandOptions,MagickFalse,option) &
1591 FireOptionFlag) == 0 ? MagickFalse : MagickTrue;
1592 if (fire != MagickFalse)
1593 FireImageStack(MagickFalse,MagickTrue,MagickTrue);
1594 }
1595 if (k != 0)
1596 ThrowCompositeException(OptionError,"UnbalancedParenthesis",argv[i]);
1597 if (i-- != (ssize_t) (argc-1))
1598 ThrowCompositeException(OptionError,"MissingAnImageFilename",argv[i]);
1599 if ((image == (Image *) NULL) || (GetImageListLength(image) < 2))
1600 ThrowCompositeException(OptionError,"MissingAnImageFilename",argv[argc-1]);
1601 FinalizeImageSettings(image_info,image,MagickTrue);
1602 if ((image == (Image *) NULL) || (GetImageListLength(image) < 2))
1603 ThrowCompositeException(OptionError,"MissingAnImageFilename",argv[argc-1]);
1604 /*
1605 Composite images.
1606 */
1607 RemoveImageStack(composite_image);
1608 RemoveImageStack(images);
1609 (void) TransformImage(&composite_image,(char *) NULL,
1610 composite_image->geometry);
1611 RemoveImageStack(mask_image);
1612 if (mask_image != (Image *) NULL)
1613 {
1614 if ((composite_options.compose == DisplaceCompositeOp) ||
1615 (composite_options.compose == DistortCompositeOp))
1616 {
1617 /*
1618 Merge Y displacement into X displacement image.
1619 */
1620 (void) CompositeImage(composite_image,CopyGreenCompositeOp,mask_image,
1621 0,0);
1622 mask_image=DestroyImage(mask_image);
1623 }
1624 else
1625 {
1626 /*
1627 Set a blending mask for the composition.
1628 */
1629 images->mask=mask_image;
1630 (void) NegateImage(images->mask,MagickFalse);
1631 }
1632 }
1633 status&=CompositeImageList(image_info,&images,composite_image,
1634 &composite_options,exception);
1635 composite_image=DestroyImage(composite_image);
1636 /*
1637 Write composite images.
1638 */
1639 status&=WriteImages(image_info,images,argv[argc-1],exception);
1640 if (metadata != (char **) NULL)
1641 {
1642 char
1643 *text;
1644
1645 text=InterpretImageProperties(image_info,images,format);
1646 InheritException(exception,&image->exception);
1647 if (text == (char *) NULL)
1648 ThrowCompositeException(ResourceLimitError,"MemoryAllocationFailed",
1649 GetExceptionMessage(errno));
1650 (void) ConcatenateString(&(*metadata),text);
1651 text=DestroyString(text);
1652 }
1653 images=DestroyImageList(images);
1654 RelinquishCompositeOptions(&composite_options);
1655 DestroyComposite();
1656 return(status != 0 ? MagickTrue : MagickFalse);
1657 }
1658