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