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