montage.c revision 1b58f25a8c2616ecdf2898ab358e1ee63d1b522e
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%               M   M   OOO   N   N  TTTTT   AAA    GGGG  EEEEE               %
7%               MM MM  O   O  NN  N    T    A   A  G      E                   %
8%               M M M  O   O  N N N    T    AAAAA  G  GG  EEE                 %
9%               M   M  O   O  N  NN    T    A   A  G   G  E                   %
10%               M   M   OOO   N   N    T    A   A   GGG   EEEEE               %
11%                                                                             %
12%                                                                             %
13%                MagickWand Methods to Create Image Thumbnails                %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                 July 1992                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%  Use the montage program to create a composite image by combining several
37%  separate images. The images are tiled on the composite image optionally
38%  adorned with a border, frame, image name, and more.
39%
40*/
41
42/*
43  Include declarations.
44*/
45#include "MagickWand/studio.h"
46#include "MagickWand/MagickWand.h"
47#include "MagickWand/mogrify-private.h"
48#include "MagickCore/string-private.h"
49
50/*
51%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52%                                                                             %
53%                                                                             %
54%                                                                             %
55+    M o n t a g e I m a g e C o m m a n d                                    %
56%                                                                             %
57%                                                                             %
58%                                                                             %
59%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60%
61%  MontageImageCommand() reads one or more images, applies one or more image
62%  processing operations, and writes out the image in the same or
63%  differing format.
64%
65%  The format of the MontageImageCommand method is:
66%
67%      MagickBooleanType MontageImageCommand(ImageInfo *image_info,int argc,
68%        char **argv,char **metadata,ExceptionInfo *exception)
69%
70%  A description of each parameter follows:
71%
72%    o image_info: the image info.
73%
74%    o argc: the number of elements in the argument vector.
75%
76%    o argv: A text array containing the command line arguments.
77%
78%    o metadata: any metadata is returned here.
79%
80%    o exception: return any errors or warnings in this structure.
81%
82*/
83
84static MagickBooleanType MontageUsage(void)
85{
86  const char
87    **p;
88
89  static const char
90    *miscellaneous[]=
91    {
92      "-debug events        display copious debugging information",
93      "-help                print program options",
94      "-list type           print a list of supported option arguments",
95      "-log format          format of debugging information",
96      "-version             print version information",
97      (char *) NULL
98    },
99    *operators[]=
100    {
101      "-adaptive-sharpen geometry",
102      "                     adaptively sharpen pixels; increase effect near edges",
103      " annotate geometry text",
104      "                     annotate the image with text",
105      "-auto-orient         automagically orient image",
106      "-blur geometry      reduce image noise and reduce detail levels",
107      "-border geometry     surround image with a border of color",
108      "-crop geometry       preferred size and location of the cropped image",
109      "-extent geometry     set the image size",
110      "-flatten             flatten a sequence of images",
111      "-flip                flip image in the vertical direction",
112      "-flop                flop image in the horizontal direction",
113      "-frame geometry      surround image with an ornamental border",
114      "-monochrome          transform image to black and white",
115      "-polaroid angle      simulate a Polaroid picture",
116      "-repage geometry     size and location of an image canvas (operator)",
117      "-resize geometry     resize the image",
118      "-rotate degrees      apply Paeth rotation to the image",
119      "-strip               strip image of all profiles and comments",
120      "-transform           affine transform image",
121      "-transpose           flip image vertically and rotate 90 degrees",
122      "-transparent color   make this color transparent within the image",
123      "-type type           image type",
124      "-unsharp geometry    sharpen the image",
125      (char *) NULL
126    },
127    *settings[]=
128    {
129      "-adjoin              join images into a single multi-image file",
130      "-affine matrix       affine transform matrix",
131      "-alpha option        on, activate, off, deactivate, set, opaque, copy",
132      "                     transparent, extract, background, or shape",
133      "-authenticate password",
134      "                     decipher image with this password",
135      "-blue-primary point  chromaticity blue primary point",
136      "-bordercolor color   border color",
137      "-caption string      assign a caption to an image",
138      "-channel type        apply option to select image channels",
139      "-colors value        preferred number of colors in the image",
140      "-colorspace type     alternate image colorsapce",
141      "-comment string      annotate image with comment",
142      "-compose operator    composite operator",
143      "-compress type       type of pixel compression when writing the image",
144      "-define format:option",
145      "                     define one or more image format options",
146      "-density geometry    horizontal and vertical density of the image",
147      "-depth value         image depth",
148      "-display server      query font from this X server",
149      "-dispose method      layer disposal method",
150      "-dither method       apply error diffusion to image",
151      "-draw string         annotate the image with a graphic primitive",
152      "-encoding type       text encoding type",
153      "-endian type         endianness (MSB or LSB) of the image",
154      "-extract geometry    extract area from image",
155      "-fill color          color to use when filling a graphic primitive",
156      "-filter type         use this filter when resizing an image",
157      "-font name           render text with this font",
158      "-format \"string\"     output formatted image characteristics",
159      "-gamma value         level of gamma correction",
160      "-geometry geometry   preferred tile and border sizes",
161      "-gravity direction   which direction to gravitate towards",
162      "-green-primary point chromaticity green primary point",
163      "-identify            identify the format and characteristics of the image",
164      "-interlace type      type of image interlacing scheme",
165      "-interpolate method  pixel color interpolation method",
166      "-kerning value       set the space between two letters",
167      "-label string        assign a label to an image",
168      "-limit type value    pixel cache resource limit",
169      "-mattecolor color    frame color",
170      "-mode type           framing style",
171      "-monitor             monitor progress",
172      "-origin geometry     image origin",
173      "-page geometry       size and location of an image canvas (setting)",
174      "-pointsize value     font point size",
175      "-profile filename    add, delete, or apply an image profile",
176      "-quality value       JPEG/MIFF/PNG compression level",
177      "-quantize colorspace reduce colors in this colorspace",
178      "-quiet               suppress all warning messages",
179      "-red-primary point   chromaticity red primary point",
180      "-regard-warnings     pay attention to warning messages",
181      "-respect-parentheses settings remain in effect until parenthesis boundary",
182      "-sampling-factor geometry",
183      "                     horizontal and vertical sampling factor",
184      "-scenes range        image scene range",
185      "-seed value          seed a new sequence of pseudo-random numbers",
186      "-set attribute value set an image attribute",
187      "-shadow              add a shadow beneath a tile to simulate depth",
188      "-size geometry       width and height of image",
189      "-stroke color        color to use when stroking a graphic primitive",
190      "-synchronize         synchronize image to storage device",
191      "-taint               declare the image as modified",
192      "-texture filename    name of texture to tile onto the image background",
193      "-thumbnail geometry  create a thumbnail of the image",
194      "-tile geometry       number of tiles per row and column",
195      "-title string        decorate the montage image with a title",
196      "-transparent-color color",
197      "                     transparent color",
198      "-treedepth value     color tree depth",
199      "-trim                trim image edges",
200      "-units type          the units of image resolution",
201      "-verbose             print detailed information about the image",
202      "-virtual-pixel method",
203      "                     virtual pixel access method",
204      "-white-point point   chromaticity white point",
205      (char *) NULL
206    },
207    *sequence_operators[]=
208    {
209      "-coalesce            merge a sequence of images",
210      "-composite           composite image",
211      (char *) NULL
212    },
213    *stack_operators[]=
214    {
215      "-clone indexes       clone an image",
216      "-delete indexes      delete the image from the image sequence",
217      "-duplicate count,indexes",
218      "                     duplicate an image one or more times",
219      "-insert index        insert last image into the image sequence",
220      "-reverse             reverse image sequence",
221      "-swap indexes        swap two images in the image sequence",
222      (char *) NULL
223    };
224
225  (void) printf("Version: %s\n",GetMagickVersion((size_t *) NULL));
226  (void) printf("Copyright: %s\n",GetMagickCopyright());
227  (void) printf("Features: %s\n\n",GetMagickFeatures());
228  (void) printf("Usage: %s [options ...] file [ [options ...] file ...] file\n",
229    GetClientName());
230  (void) printf("\nImage Settings:\n");
231  for (p=settings; *p != (char *) NULL; p++)
232    (void) printf("  %s\n",*p);
233  (void) printf("\nImage Operators:\n");
234  for (p=operators; *p != (char *) NULL; p++)
235    (void) printf("  %s\n",*p);
236  (void) printf("\nImage Sequence Operators:\n");
237  for (p=sequence_operators; *p != (char *) NULL; p++)
238    (void) printf("  %s\n",*p);
239  (void) printf("\nImage Stack Operators:\n");
240  for (p=stack_operators; *p != (char *) NULL; p++)
241    (void) printf("  %s\n",*p);
242  (void) printf("\nMiscellaneous Options:\n");
243  for (p=miscellaneous; *p != (char *) NULL; p++)
244    (void) printf("  %s\n",*p);
245  (void) printf(
246    "\nIn addition to those listed above, you can specify these standard X\n");
247  (void) printf(
248    "resources as command line options:  -background, -bordercolor,\n");
249  (void) printf(
250    "-borderwidth, -font, -mattecolor, or -title\n");
251  (void) printf(
252    "\nBy default, the image format of `file' is determined by its magic\n");
253  (void) printf(
254    "number.  To specify a particular image format, precede the filename\n");
255  (void) printf(
256    "with an image format name and a colon (i.e. ps:image) or specify the\n");
257  (void) printf(
258    "image type as the filename suffix (i.e. image.ps).  Specify 'file' as\n");
259  (void) printf("'-' for standard input or output.\n");
260  return(MagickFalse);
261}
262
263WandExport MagickBooleanType MontageImageCommand(ImageInfo *image_info,
264  int argc,char **argv,char **metadata,ExceptionInfo *exception)
265{
266#define DestroyMontage() \
267{ \
268  if (montage_image != (Image *) NULL) \
269    montage_image=DestroyImageList(montage_image); \
270  DestroyImageStack(); \
271  for (i=0; i < (ssize_t) argc; i++) \
272    argv[i]=DestroyString(argv[i]); \
273  argv=(char **) RelinquishMagickMemory(argv); \
274}
275#define ThrowMontageException(asperity,tag,option) \
276{ \
277  (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
278    option); \
279  DestroyMontage(); \
280  return(MagickFalse); \
281}
282#define ThrowMontageInvalidArgumentException(option,argument) \
283{ \
284  (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \
285    "InvalidArgument","`%s': %s",option,argument); \
286  DestroyMontage(); \
287  return(MagickFalse); \
288}
289
290  char
291    *option,
292    *transparent_color;
293
294  const char
295    *format;
296
297  Image
298    *image,
299    *montage_image;
300
301  ImageStack
302    image_stack[MaxImageStackDepth+1];
303
304  long
305    first_scene,
306    last_scene;
307
308  MagickBooleanType
309    fire,
310    pend,
311    respect_parenthesis;
312
313  MagickStatusType
314    status;
315
316  MontageInfo
317    *montage_info;
318
319  register ssize_t
320    i;
321
322  ssize_t
323    j,
324    k,
325    scene;
326
327  /*
328    Set defaults.
329  */
330  assert(image_info != (ImageInfo *) NULL);
331  assert(image_info->signature == MagickSignature);
332  if (image_info->debug != MagickFalse)
333    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
334  assert(exception != (ExceptionInfo *) NULL);
335  if (argc == 2)
336    {
337      option=argv[1];
338      if ((LocaleCompare("version",option+1) == 0) ||
339          (LocaleCompare("-version",option+1) == 0))
340        {
341          (void) FormatLocaleFile(stdout,"Version: %s\n",
342            GetMagickVersion((size_t *) NULL));
343          (void) FormatLocaleFile(stdout,"Copyright: %s\n",
344            GetMagickCopyright());
345          (void) FormatLocaleFile(stdout,"Features: %s\n\n",
346            GetMagickFeatures());
347          return(MagickFalse);
348        }
349    }
350  if (argc < 3)
351    return(MontageUsage());
352  format="%w,%h,%m";
353  first_scene=0;
354  j=1;
355  k=0;
356  last_scene=0;
357  montage_image=NewImageList();
358  montage_info=CloneMontageInfo(image_info,(MontageInfo *) NULL);
359  NewImageStack();
360  option=(char *) NULL;
361  pend=MagickFalse;
362  respect_parenthesis=MagickFalse;
363  scene=0;
364  status=MagickFalse;
365  transparent_color=(char *) NULL;
366  /*
367    Parse command line.
368  */
369  ReadCommandlLine(argc,&argv);
370  status=ExpandFilenames(&argc,&argv);
371  if (status == MagickFalse)
372    ThrowMontageException(ResourceLimitError,"MemoryAllocationFailed",
373      GetExceptionMessage(errno));
374  for (i=1; i < (ssize_t) (argc-1); i++)
375  {
376    option=argv[i];
377    if (LocaleCompare(option,"(") == 0)
378      {
379        FireImageStack(MagickTrue,MagickTrue,pend);
380        if (k == MaxImageStackDepth)
381          ThrowMontageException(OptionError,"ParenthesisNestedTooDeeply",
382            option);
383        PushImageStack();
384        continue;
385      }
386    if (LocaleCompare(option,")") == 0)
387      {
388        FireImageStack(MagickTrue,MagickTrue,MagickTrue);
389        if (k == 0)
390          ThrowMontageException(OptionError,"UnableToParseExpression",option);
391        PopImageStack();
392        continue;
393      }
394    if (IsCommandOption(option) == MagickFalse)
395      {
396        Image
397          *images;
398
399        FireImageStack(MagickFalse,MagickFalse,pend);
400        for (scene=(ssize_t) first_scene; scene <= (ssize_t) last_scene ; scene++)
401        {
402          char
403            *filename;
404
405          /*
406            Option is a file name: begin by reading image from specified file.
407          */
408          filename=argv[i];
409          if ((LocaleCompare(filename,"--") == 0) && (i < (ssize_t) (argc-1)))
410            filename=argv[++i];
411          (void) CloneString(&image_info->font,montage_info->font);
412          if (first_scene == last_scene)
413            images=ReadImages(image_info,filename,exception);
414          else
415            {
416              char
417                filename[MaxTextExtent];
418
419              /*
420                Form filename for multi-part images.
421              */
422              (void) InterpretImageFilename(image_info,(Image *) NULL,
423                image_info->filename,(int) scene,filename,exception);
424              if (LocaleCompare(filename,image_info->filename) == 0)
425                (void) FormatLocaleString(filename,MaxTextExtent,"%s.%.20g",
426                  image_info->filename,(double) scene);
427              images=ReadImages(image_info,filename,exception);
428            }
429          status&=(images != (Image *) NULL) &&
430            (exception->severity < ErrorException);
431          if (images == (Image *) NULL)
432            continue;
433          AppendImageStack(images);
434        }
435        continue;
436      }
437    pend=image != (Image *) NULL ? MagickTrue : MagickFalse;
438    switch (*(option+1))
439    {
440      case 'a':
441      {
442        if (LocaleCompare("adaptive-sharpen",option+1) == 0)
443          {
444            i++;
445            if (i == (ssize_t) (argc-1))
446              ThrowMontageException(OptionError,"MissingArgument",option);
447            if (IsGeometry(argv[i]) == MagickFalse)
448              ThrowMontageInvalidArgumentException(option,argv[i]);
449            break;
450          }
451        if (LocaleCompare("adjoin",option+1) == 0)
452          break;
453        if (LocaleCompare("affine",option+1) == 0)
454          {
455            if (*option == '+')
456              break;
457            i++;
458            if (i == (ssize_t) (argc-1))
459              ThrowMontageException(OptionError,"MissingArgument",option);
460            if (IsGeometry(argv[i]) == MagickFalse)
461              ThrowMontageInvalidArgumentException(option,argv[i]);
462            break;
463          }
464        if (LocaleCompare("alpha",option+1) == 0)
465          {
466            ssize_t
467              type;
468
469            if (*option == '+')
470              break;
471            i++;
472            if (i == (ssize_t) argc)
473              ThrowMontageException(OptionError,"MissingArgument",option);
474            type=ParseCommandOption(MagickAlphaOptions,MagickFalse,argv[i]);
475            if (type < 0)
476              ThrowMontageException(OptionError,"UnrecognizedAlphaChannelType",
477                argv[i]);
478            break;
479          }
480        if (LocaleCompare("annotate",option+1) == 0)
481          {
482            if (*option == '+')
483              break;
484            i++;
485            if (i == (ssize_t) (argc-1))
486              ThrowMontageException(OptionError,"MissingArgument",option);
487            if (IsGeometry(argv[i]) == MagickFalse)
488              ThrowMontageInvalidArgumentException(option,argv[i]);
489            if (i == (ssize_t) (argc-1))
490              ThrowMontageException(OptionError,"MissingArgument",option);
491            i++;
492            break;
493          }
494        if (LocaleCompare("auto-orient",option+1) == 0)
495          break;
496        if (LocaleCompare("authenticate",option+1) == 0)
497          {
498            if (*option == '+')
499              break;
500            i++;
501            if (i == (ssize_t) argc)
502              ThrowMontageException(OptionError,"MissingArgument",option);
503            break;
504          }
505        ThrowMontageException(OptionError,"UnrecognizedOption",option)
506      }
507      case 'b':
508      {
509        if (LocaleCompare("background",option+1) == 0)
510          {
511            if (*option == '+')
512              break;
513            i++;
514            if (i == (ssize_t) argc)
515              ThrowMontageException(OptionError,"MissingArgument",option);
516            (void) QueryColorCompliance(argv[i],AllCompliance,
517              &montage_info->background_color,exception);
518            break;
519          }
520        if (LocaleCompare("blue-primary",option+1) == 0)
521          {
522            if (*option == '+')
523              break;
524            i++;
525            if (i == (ssize_t) argc)
526              ThrowMontageException(OptionError,"MissingArgument",option);
527            if (IsGeometry(argv[i]) == MagickFalse)
528              ThrowMontageInvalidArgumentException(option,argv[i]);
529            break;
530          }
531        if (LocaleCompare("blur",option+1) == 0)
532          {
533            if (*option == '+')
534              break;
535            i++;
536            if (i == (ssize_t) argc)
537              ThrowMontageException(OptionError,"MissingArgument",option);
538            if (IsGeometry(argv[i]) == MagickFalse)
539              ThrowMontageInvalidArgumentException(option,argv[i]);
540            break;
541          }
542        if (LocaleCompare("border",option+1) == 0)
543          {
544            if (k == 0)
545              {
546                (void) CopyMagickString(argv[i]+1,"sans",MaxTextExtent);
547                montage_info->border_width=0;
548              }
549            if (*option == '+')
550              break;
551            i++;
552            if (i == (ssize_t) argc)
553              ThrowMontageException(OptionError,"MissingArgument",option);
554            if (IsGeometry(argv[i]) == MagickFalse)
555              ThrowMontageInvalidArgumentException(option,argv[i]);
556            if (k == 0)
557              montage_info->border_width=StringToUnsignedLong(argv[i]);
558            break;
559          }
560        if (LocaleCompare("bordercolor",option+1) == 0)
561          {
562            if (*option == '+')
563              break;
564            i++;
565            if (i == (ssize_t) argc)
566              ThrowMontageException(OptionError,"MissingArgument",option);
567            (void) QueryColorCompliance(argv[i],AllCompliance,
568              &montage_info->border_color,exception);
569            break;
570          }
571        if (LocaleCompare("borderwidth",option+1) == 0)
572          {
573            montage_info->border_width=0;
574            if (*option == '+')
575              break;
576            i++;
577            if (i == (ssize_t) argc)
578              ThrowMontageException(OptionError,"MissingArgument",option);
579            if (IsGeometry(argv[i]) == MagickFalse)
580              ThrowMontageInvalidArgumentException(option,argv[i]);
581            montage_info->border_width=StringToUnsignedLong(argv[i]);
582            break;
583          }
584        ThrowMontageException(OptionError,"UnrecognizedOption",option)
585      }
586      case 'c':
587      {
588        if (LocaleCompare("cache",option+1) == 0)
589          {
590            if (*option == '+')
591              break;
592            i++;
593            if (i == (ssize_t) argc)
594              ThrowMontageException(OptionError,"MissingArgument",option);
595            if (IsGeometry(argv[i]) == MagickFalse)
596              ThrowMontageInvalidArgumentException(option,argv[i]);
597            break;
598          }
599        if (LocaleCompare("caption",option+1) == 0)
600          {
601            if (*option == '+')
602              break;
603            i++;
604            if (i == (ssize_t) argc)
605              ThrowMontageException(OptionError,"MissingArgument",option);
606            break;
607          }
608        if (LocaleCompare("channel",option+1) == 0)
609          {
610            ssize_t
611              channel;
612
613            if (*option == '+')
614              break;
615            i++;
616            if (i == (ssize_t) (argc-1))
617              ThrowMontageException(OptionError,"MissingArgument",option);
618            channel=ParseChannelOption(argv[i]);
619            if (channel < 0)
620              ThrowMontageException(OptionError,"UnrecognizedChannelType",
621                argv[i]);
622            break;
623          }
624        if (LocaleCompare("clone",option+1) == 0)
625          {
626            Image
627              *clone_images;
628
629            clone_images=image;
630            if (k != 0)
631              clone_images=image_stack[k-1].image;
632            if (clone_images == (Image *) NULL)
633              ThrowMontageException(ImageError,"ImageSequenceRequired",option);
634            FireImageStack(MagickTrue,MagickTrue,MagickTrue);
635            if (*option == '+')
636              clone_images=CloneImages(clone_images,"-1",exception);
637            else
638              {
639                i++;
640                if (i == (ssize_t) (argc-1))
641                  ThrowMontageException(OptionError,"MissingArgument",option);
642                if (IsSceneGeometry(argv[i],MagickFalse) == MagickFalse)
643                  ThrowMontageInvalidArgumentException(option,argv[i]);
644                clone_images=CloneImages(clone_images,argv[i],exception);
645              }
646            if (clone_images == (Image *) NULL)
647              ThrowMontageException(OptionError,"NoSuchImage",option);
648            AppendImageStack(clone_images);
649            break;
650          }
651        if (LocaleCompare("coalesce",option+1) == 0)
652          break;
653        if (LocaleCompare("colors",option+1) == 0)
654          {
655            if (*option == '+')
656              break;
657            i++;
658            if (i == (ssize_t) argc)
659              ThrowMontageException(OptionError,"MissingArgument",option);
660            if (IsGeometry(argv[i]) == MagickFalse)
661              ThrowMontageInvalidArgumentException(option,argv[i]);
662            break;
663          }
664        if (LocaleCompare("colorspace",option+1) == 0)
665          {
666            ssize_t
667              colorspace;
668
669            if (*option == '+')
670              break;
671            i++;
672            if (i == (ssize_t) argc)
673              ThrowMontageException(OptionError,"MissingArgument",option);
674            colorspace=ParseCommandOption(MagickColorspaceOptions,
675              MagickFalse,argv[i]);
676            if (colorspace < 0)
677              ThrowMontageException(OptionError,"UnrecognizedColorspace",
678                argv[i]);
679            break;
680          }
681        if (LocaleCompare("comment",option+1) == 0)
682          {
683            if (*option == '+')
684              break;
685            i++;
686            if (i == (ssize_t) argc)
687              ThrowMontageException(OptionError,"MissingArgument",option);
688            break;
689          }
690        if (LocaleCompare("compose",option+1) == 0)
691          {
692            ssize_t
693              compose;
694
695            if (*option == '+')
696              break;
697            i++;
698            if (i == (ssize_t) argc)
699              ThrowMontageException(OptionError,"MissingArgument",option);
700            compose=ParseCommandOption(MagickComposeOptions,MagickFalse,argv[i]);
701            if (compose < 0)
702              ThrowMontageException(OptionError,"UnrecognizedComposeOperator",
703                argv[i]);
704            break;
705          }
706        if (LocaleCompare("composite",option+1) == 0)
707          break;
708        if (LocaleCompare("compress",option+1) == 0)
709          {
710            ssize_t
711              compress;
712
713            if (*option == '+')
714              break;
715            i++;
716            if (i == (ssize_t) argc)
717              ThrowMontageException(OptionError,"MissingArgument",option);
718            compress=ParseCommandOption(MagickCompressOptions,MagickFalse,
719              argv[i]);
720            if (compress < 0)
721              ThrowMontageException(OptionError,"UnrecognizedCompressType",
722                argv[i]);
723            break;
724          }
725        if (LocaleCompare("concurrent",option+1) == 0)
726          break;
727        if (LocaleCompare("crop",option+1) == 0)
728          {
729            if (*option == '+')
730              break;
731            i++;
732            if (i == (ssize_t) argc)
733              ThrowMontageException(OptionError,"MissingArgument",option);
734            if (IsGeometry(argv[i]) == MagickFalse)
735              ThrowMontageInvalidArgumentException(option,argv[i]);
736            break;
737          }
738        ThrowMontageException(OptionError,"UnrecognizedOption",option)
739      }
740      case 'd':
741      {
742        if (LocaleCompare("debug",option+1) == 0)
743          {
744            ssize_t
745              event;
746
747            if (*option == '+')
748              break;
749            i++;
750            if (i == (ssize_t) argc)
751              ThrowMontageException(OptionError,"MissingArgument",option);
752            event=ParseCommandOption(MagickLogEventOptions,MagickFalse,argv[i]);
753            if (event < 0)
754              ThrowMontageException(OptionError,"UnrecognizedEventType",
755                argv[i]);
756            (void) SetLogEventMask(argv[i]);
757            break;
758          }
759        if (LocaleCompare("define",option+1) == 0)
760          {
761            i++;
762            if (i == (ssize_t) argc)
763              ThrowMontageException(OptionError,"MissingArgument",option);
764            if (*option == '+')
765              {
766                const char
767                  *define;
768
769                define=GetImageOption(image_info,argv[i]);
770                if (define == (const char *) NULL)
771                  ThrowMontageException(OptionError,"NoSuchOption",argv[i]);
772                break;
773              }
774            break;
775          }
776        if (LocaleCompare("delete",option+1) == 0)
777          {
778            if (*option == '+')
779              break;
780            i++;
781            if (i == (ssize_t) (argc-1))
782              ThrowMontageException(OptionError,"MissingArgument",option);
783            if (IsSceneGeometry(argv[i],MagickFalse) == MagickFalse)
784              ThrowMontageInvalidArgumentException(option,argv[i]);
785            break;
786          }
787        if (LocaleCompare("density",option+1) == 0)
788          {
789            if (*option == '+')
790              break;
791            i++;
792            if (i == (ssize_t) argc)
793              ThrowMontageException(OptionError,"MissingArgument",option);
794            if (IsGeometry(argv[i]) == MagickFalse)
795              ThrowMontageInvalidArgumentException(option,argv[i]);
796            break;
797          }
798        if (LocaleCompare("depth",option+1) == 0)
799          {
800            if (*option == '+')
801              break;
802            i++;
803            if (i == (ssize_t) argc)
804              ThrowMontageException(OptionError,"MissingArgument",option);
805            if (IsGeometry(argv[i]) == MagickFalse)
806              ThrowMontageInvalidArgumentException(option,argv[i]);
807            break;
808          }
809        if (LocaleCompare("display",option+1) == 0)
810          {
811            if (*option == '+')
812              break;
813            i++;
814            if (i == (ssize_t) argc)
815              ThrowMontageException(OptionError,"MissingArgument",option);
816            break;
817          }
818        if (LocaleCompare("dispose",option+1) == 0)
819          {
820            ssize_t
821              dispose;
822
823            if (*option == '+')
824              break;
825            i++;
826            if (i == (ssize_t) argc)
827              ThrowMontageException(OptionError,"MissingArgument",option);
828            dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse,argv[i]);
829            if (dispose < 0)
830              ThrowMontageException(OptionError,"UnrecognizedDisposeMethod",
831                argv[i]);
832            break;
833          }
834        if (LocaleCompare("dither",option+1) == 0)
835          {
836            ssize_t
837              method;
838
839            if (*option == '+')
840              break;
841            i++;
842            if (i == (ssize_t) argc)
843              ThrowMontageException(OptionError,"MissingArgument",option);
844            method=ParseCommandOption(MagickDitherOptions,MagickFalse,argv[i]);
845            if (method < 0)
846              ThrowMontageException(OptionError,"UnrecognizedDitherMethod",
847                argv[i]);
848            break;
849          }
850        if (LocaleCompare("draw",option+1) == 0)
851          {
852            if (*option == '+')
853              break;
854            i++;
855            if (i == (ssize_t) argc)
856              ThrowMontageException(OptionError,"MissingArgument",option);
857            break;
858          }
859        if (LocaleCompare("duplicate",option+1) == 0)
860          {
861            if (*option == '+')
862              break;
863            i++;
864            if (i == (ssize_t) (argc-1))
865              ThrowMontageException(OptionError,"MissingArgument",option);
866            if (IsGeometry(argv[i]) == MagickFalse)
867              ThrowMontageInvalidArgumentException(option,argv[i]);
868            break;
869          }
870        if (LocaleCompare("duration",option+1) == 0)
871          {
872            if (*option == '+')
873              break;
874            i++;
875            if (i == (ssize_t) (argc-1))
876              ThrowMontageException(OptionError,"MissingArgument",option);
877            if (IsGeometry(argv[i]) == MagickFalse)
878              ThrowMontageInvalidArgumentException(option,argv[i]);
879            break;
880          }
881        ThrowMontageException(OptionError,"UnrecognizedOption",option)
882      }
883      case 'e':
884      {
885        if (LocaleCompare("encoding",option+1) == 0)
886          {
887            if (*option == '+')
888              break;
889            i++;
890            if (i == (ssize_t) argc)
891              ThrowMontageException(OptionError,"MissingArgument",option);
892            break;
893          }
894        if (LocaleCompare("endian",option+1) == 0)
895          {
896            ssize_t
897              endian;
898
899            if (*option == '+')
900              break;
901            i++;
902            if (i == (ssize_t) argc)
903              ThrowMontageException(OptionError,"MissingArgument",option);
904            endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
905              argv[i]);
906            if (endian < 0)
907              ThrowMontageException(OptionError,"UnrecognizedEndianType",
908                argv[i]);
909            break;
910          }
911        if (LocaleCompare("extent",option+1) == 0)
912          {
913            if (*option == '+')
914              break;
915            i++;
916            if (i == (ssize_t) (argc-1))
917              ThrowMontageException(OptionError,"MissingArgument",option);
918            if (IsGeometry(argv[i]) == MagickFalse)
919              ThrowMontageInvalidArgumentException(option,argv[i]);
920            break;
921          }
922        ThrowMontageException(OptionError,"UnrecognizedOption",option)
923      }
924      case 'f':
925      {
926        if (LocaleCompare("fill",option+1) == 0)
927          {
928            (void) QueryColorCompliance("none",AllCompliance,
929              &montage_info->fill,exception);
930            if (*option == '+')
931              break;
932            i++;
933            if (i == (ssize_t) argc)
934              ThrowMontageException(OptionError,"MissingArgument",option);
935            (void) QueryColorCompliance(argv[i],AllCompliance,
936              &montage_info->fill,exception);
937            break;
938          }
939        if (LocaleCompare("filter",option+1) == 0)
940          {
941            ssize_t
942              filter;
943
944            if (*option == '+')
945              break;
946            i++;
947            if (i == (ssize_t) argc)
948              ThrowMontageException(OptionError,"MissingArgument",option);
949            filter=ParseCommandOption(MagickFilterOptions,MagickFalse,argv[i]);
950            if (filter < 0)
951              ThrowMontageException(OptionError,"UnrecognizedImageFilter",
952                argv[i]);
953            break;
954          }
955        if (LocaleCompare("flatten",option+1) == 0)
956          break;
957        if (LocaleCompare("flip",option+1) == 0)
958          break;
959        if (LocaleCompare("flop",option+1) == 0)
960          break;
961        if (LocaleCompare("font",option+1) == 0)
962          {
963            if (*option == '+')
964              break;
965            i++;
966            if (i == (ssize_t) argc)
967              ThrowMontageException(OptionError,"MissingArgument",option);
968            (void) CloneString(&montage_info->font,argv[i]);
969            break;
970          }
971        if (LocaleCompare("format",option+1) == 0)
972          {
973            if (*option == '+')
974              break;
975            i++;
976            if (i == (ssize_t) argc)
977              ThrowMontageException(OptionError,"MissingArgument",option);
978            format=argv[i];
979            break;
980          }
981        if (LocaleCompare("frame",option+1) == 0)
982          {
983            if (k == 0)
984              {
985                (void) CopyMagickString(argv[i]+1,"sans",MaxTextExtent);
986                (void) CloneString(&montage_info->frame,(char *) NULL);
987              }
988            if (*option == '+')
989              break;
990            i++;
991            if (i == (ssize_t) argc)
992              ThrowMontageException(OptionError,"MissingArgument",option);
993            if (IsGeometry(argv[i]) == MagickFalse)
994              ThrowMontageInvalidArgumentException(option,argv[i]);
995            if (k == 0)
996              (void) CloneString(&montage_info->frame,argv[i]);
997            break;
998          }
999        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1000      }
1001      case 'g':
1002      {
1003        if (LocaleCompare("gamma",option+1) == 0)
1004          {
1005            i++;
1006            if (i == (ssize_t) argc)
1007              ThrowMontageException(OptionError,"MissingArgument",option);
1008            if (IsGeometry(argv[i]) == MagickFalse)
1009              ThrowMontageInvalidArgumentException(option,argv[i]);
1010            break;
1011          }
1012        if (LocaleCompare("geometry",option+1) == 0)
1013          {
1014            (void) CloneString(&montage_info->geometry,(char *) NULL);
1015            if (*option == '+')
1016              break;
1017            i++;
1018            if (i == (ssize_t) argc)
1019              ThrowMontageException(OptionError,"MissingArgument",option);
1020            if (IsGeometry(argv[i]) == MagickFalse)
1021              ThrowMontageInvalidArgumentException(option,argv[i]);
1022            (void) CloneString(&montage_info->geometry,argv[i]);
1023            break;
1024          }
1025        if (LocaleCompare("gravity",option+1) == 0)
1026          {
1027            ssize_t
1028              gravity;
1029
1030            montage_info->gravity=UndefinedGravity;
1031            if (*option == '+')
1032              break;
1033            i++;
1034            if (i == (ssize_t) argc)
1035              ThrowMontageException(OptionError,"MissingArgument",option);
1036            gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,
1037              argv[i]);
1038            if (gravity < 0)
1039              ThrowMontageException(OptionError,"UnrecognizedGravityType",
1040                argv[i]);
1041            montage_info->gravity=(GravityType) gravity;
1042            break;
1043          }
1044        if (LocaleCompare("green-primary",option+1) == 0)
1045          {
1046            if (*option == '+')
1047              break;
1048            i++;
1049            if (i == (ssize_t) argc)
1050              ThrowMontageException(OptionError,"MissingArgument",option);
1051            if (IsGeometry(argv[i]) == MagickFalse)
1052              ThrowMontageInvalidArgumentException(option,argv[i]);
1053            break;
1054          }
1055        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1056      }
1057      case 'h':
1058      {
1059        if ((LocaleCompare("help",option+1) == 0) ||
1060            (LocaleCompare("-help",option+1) == 0))
1061          return(MontageUsage());
1062        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1063      }
1064      case 'i':
1065      {
1066        if (LocaleCompare("identify",option+1) == 0)
1067          break;
1068        if (LocaleCompare("insert",option+1) == 0)
1069          {
1070            if (*option == '+')
1071              break;
1072            i++;
1073            if (i == (ssize_t) (argc-1))
1074              ThrowMontageException(OptionError,"MissingArgument",option);
1075            if (IsGeometry(argv[i]) == MagickFalse)
1076              ThrowMontageInvalidArgumentException(option,argv[i]);
1077            break;
1078          }
1079        if (LocaleCompare("interlace",option+1) == 0)
1080          {
1081            ssize_t
1082              interlace;
1083
1084            if (*option == '+')
1085              break;
1086            i++;
1087            if (i == (ssize_t) argc)
1088              ThrowMontageException(OptionError,"MissingArgument",option);
1089            interlace=ParseCommandOption(MagickInterlaceOptions,MagickFalse,
1090              argv[i]);
1091            if (interlace < 0)
1092              ThrowMontageException(OptionError,"UnrecognizedInterlaceType",
1093                argv[i]);
1094            break;
1095          }
1096        if (LocaleCompare("interpolate",option+1) == 0)
1097          {
1098            ssize_t
1099              interpolate;
1100
1101            if (*option == '+')
1102              break;
1103            i++;
1104            if (i == (ssize_t) argc)
1105              ThrowMontageException(OptionError,"MissingArgument",option);
1106            interpolate=ParseCommandOption(MagickInterpolateOptions,MagickFalse,
1107              argv[i]);
1108            if (interpolate < 0)
1109              ThrowMontageException(OptionError,"UnrecognizedInterpolateMethod",
1110                argv[i]);
1111            break;
1112          }
1113        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1114      }
1115      case 'k':
1116      {
1117        if (LocaleCompare("kerning",option+1) == 0)
1118          {
1119            if (*option == '+')
1120              break;
1121            i++;
1122            if (i == (ssize_t) (argc-1))
1123              ThrowMontageException(OptionError,"MissingArgument",option);
1124            if (IsGeometry(argv[i]) == MagickFalse)
1125              ThrowMontageInvalidArgumentException(option,argv[i]);
1126            break;
1127          }
1128        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1129      }
1130      case 'l':
1131      {
1132        if (LocaleCompare("label",option+1) == 0)
1133          {
1134            if (*option == '+')
1135              break;
1136            i++;
1137            if (i == (ssize_t) argc)
1138              ThrowMontageException(OptionError,"MissingArgument",option);
1139            break;
1140          }
1141        if (LocaleCompare("limit",option+1) == 0)
1142          {
1143            char
1144              *p;
1145
1146            double
1147              value;
1148
1149            ssize_t
1150              resource;
1151
1152            if (*option == '+')
1153              break;
1154            i++;
1155            if (i == (ssize_t) argc)
1156              ThrowMontageException(OptionError,"MissingArgument",option);
1157            resource=ParseCommandOption(MagickResourceOptions,MagickFalse,
1158              argv[i]);
1159            if (resource < 0)
1160              ThrowMontageException(OptionError,"UnrecognizedResourceType",
1161                argv[i]);
1162            i++;
1163            if (i == (ssize_t) argc)
1164              ThrowMontageException(OptionError,"MissingArgument",option);
1165            value=StringToDouble(argv[i],&p);
1166            (void) value;
1167            if ((p == argv[i]) && (LocaleCompare("unlimited",argv[i]) != 0))
1168              ThrowMontageInvalidArgumentException(option,argv[i]);
1169            break;
1170          }
1171        if (LocaleCompare("list",option+1) == 0)
1172          {
1173            ssize_t
1174              list;
1175
1176            if (*option == '+')
1177              break;
1178            i++;
1179            if (i == (ssize_t) argc)
1180              ThrowMontageException(OptionError,"MissingArgument",option);
1181            list=ParseCommandOption(MagickListOptions,MagickFalse,argv[i]);
1182            if (list < 0)
1183              ThrowMontageException(OptionError,"UnrecognizedListType",argv[i]);
1184            status=MogrifyImageInfo(image_info,(int) (i-j+1),(const char **)
1185              argv+j,exception);
1186            DestroyMontage();
1187            return(status != 0 ? MagickFalse : MagickTrue);
1188          }
1189        if (LocaleCompare("log",option+1) == 0)
1190          {
1191            if (*option == '+')
1192              break;
1193            i++;
1194            if ((i == (ssize_t) argc) ||
1195                (strchr(argv[i],'%') == (char *) NULL))
1196              ThrowMontageException(OptionError,"MissingArgument",option);
1197            break;
1198          }
1199        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1200      }
1201      case 'm':
1202      {
1203        if (LocaleCompare("matte",option+1) == 0)
1204          break;
1205        if (LocaleCompare("mattecolor",option+1) == 0)
1206          {
1207            if (*option == '+')
1208              break;
1209            i++;
1210            if (i == (ssize_t) argc)
1211              ThrowMontageException(OptionError,"MissingArgument",option);
1212            (void) QueryColorCompliance(argv[i],AllCompliance,
1213              &montage_info->matte_color,exception);
1214            break;
1215          }
1216        if (LocaleCompare("mode",option+1) == 0)
1217          {
1218            MontageMode
1219              mode;
1220
1221            (void) CopyMagickString(argv[i]+1,"sans",MaxTextExtent);
1222            if (*option == '+')
1223              break;
1224            i++;
1225            if (i == (ssize_t) argc)
1226              ThrowMontageException(OptionError,"MissingArgument",option);
1227            mode=UndefinedMode;
1228            if (LocaleCompare("frame",argv[i]) == 0)
1229              {
1230                mode=FrameMode;
1231                (void) CloneString(&montage_info->frame,"15x15+3+3");
1232                montage_info->shadow=MagickTrue;
1233                break;
1234              }
1235            if (LocaleCompare("unframe",argv[i]) == 0)
1236              {
1237                mode=UnframeMode;
1238                montage_info->frame=(char *) NULL;
1239                montage_info->shadow=MagickFalse;
1240                montage_info->border_width=0;
1241                break;
1242              }
1243            if (LocaleCompare("concatenate",argv[i]) == 0)
1244              {
1245                mode=ConcatenateMode;
1246                montage_info->frame=(char *) NULL;
1247                montage_info->shadow=MagickFalse;
1248                montage_info->gravity=(GravityType) NorthWestGravity;
1249                (void) CloneString(&montage_info->geometry,"+0+0");
1250                montage_info->border_width=0;
1251                break;
1252              }
1253            if (mode == UndefinedMode)
1254              ThrowMontageException(OptionError,"UnrecognizedImageMode",
1255                argv[i]);
1256            break;
1257          }
1258        if (LocaleCompare("monitor",option+1) == 0)
1259          break;
1260        if (LocaleCompare("monochrome",option+1) == 0)
1261          {
1262            if (*option == '+')
1263              break;
1264            break;
1265          }
1266        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1267      }
1268      case 'n':
1269      {
1270        if (LocaleCompare("noop",option+1) == 0)
1271          break;
1272        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1273      }
1274      case 'o':
1275      {
1276        if (LocaleCompare("origin",option+1) == 0)
1277          {
1278            if (*option == '+')
1279              break;
1280            i++;
1281            if (i == (ssize_t) argc)
1282              ThrowMontageException(OptionError,"MissingArgument",option);
1283            if (IsGeometry(argv[i]) == MagickFalse)
1284              ThrowMontageInvalidArgumentException(option,argv[i]);
1285            break;
1286          }
1287        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1288      }
1289      case 'p':
1290      {
1291        if (LocaleCompare("page",option+1) == 0)
1292          {
1293            if (*option == '+')
1294              break;
1295            i++;
1296            if (i == (ssize_t) argc)
1297              ThrowMontageException(OptionError,"MissingArgument",option);
1298            break;
1299          }
1300        if (LocaleCompare("pointsize",option+1) == 0)
1301          {
1302            montage_info->pointsize=12;
1303            if (*option == '+')
1304              break;
1305            i++;
1306            if (i == (ssize_t) argc)
1307              ThrowMontageException(OptionError,"MissingArgument",option);
1308            if (IsGeometry(argv[i]) == MagickFalse)
1309              ThrowMontageInvalidArgumentException(option,argv[i]);
1310            montage_info->pointsize=StringToDouble(argv[i],(char **) NULL);
1311            break;
1312          }
1313        if (LocaleCompare("polaroid",option+1) == 0)
1314          {
1315            if (*option == '+')
1316              break;
1317            i++;
1318            if (i == (ssize_t) (argc-1))
1319              ThrowMontageException(OptionError,"MissingArgument",option);
1320            if (IsGeometry(argv[i]) == MagickFalse)
1321              ThrowMontageInvalidArgumentException(option,argv[i]);
1322            break;
1323          }
1324        if (LocaleCompare("profile",option+1) == 0)
1325          {
1326            i++;
1327            if (i == (ssize_t) (argc-1))
1328              ThrowMontageException(OptionError,"MissingArgument",option);
1329            break;
1330          }
1331        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1332      }
1333      case 'q':
1334      {
1335        if (LocaleCompare("quality",option+1) == 0)
1336          {
1337            if (*option == '+')
1338              break;
1339            i++;
1340            if (i == (ssize_t) argc)
1341              ThrowMontageException(OptionError,"MissingArgument",option);
1342            if (IsGeometry(argv[i]) == MagickFalse)
1343              ThrowMontageInvalidArgumentException(option,argv[i]);
1344            break;
1345          }
1346        if (LocaleCompare("quantize",option+1) == 0)
1347          {
1348            ssize_t
1349              colorspace;
1350
1351            if (*option == '+')
1352              break;
1353            i++;
1354            if (i == (ssize_t) (argc-1))
1355              ThrowMontageException(OptionError,"MissingArgument",option);
1356            colorspace=ParseCommandOption(MagickColorspaceOptions,
1357              MagickFalse,argv[i]);
1358            if (colorspace < 0)
1359              ThrowMontageException(OptionError,"UnrecognizedColorspace",
1360                argv[i]);
1361            break;
1362          }
1363        if (LocaleCompare("quiet",option+1) == 0)
1364          break;
1365        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1366      }
1367      case 'r':
1368      {
1369        if (LocaleCompare("red-primary",option+1) == 0)
1370          {
1371            if (*option == '+')
1372              break;
1373            i++;
1374            if (i == (ssize_t) argc)
1375              ThrowMontageException(OptionError,"MissingArgument",option);
1376            if (IsGeometry(argv[i]) == MagickFalse)
1377              ThrowMontageInvalidArgumentException(option,argv[i]);
1378            break;
1379          }
1380        if (LocaleCompare("regard-warnings",option+1) == 0)
1381          break;
1382        if (LocaleCompare("render",option+1) == 0)
1383          break;
1384        if (LocaleCompare("repage",option+1) == 0)
1385          {
1386            if (*option == '+')
1387              break;
1388            i++;
1389            if (i == (ssize_t) argc)
1390              ThrowMontageException(OptionError,"MissingArgument",option);
1391            if (IsGeometry(argv[i]) == MagickFalse)
1392              ThrowMontageInvalidArgumentException(option,argv[i]);
1393            break;
1394          }
1395        if (LocaleCompare("resize",option+1) == 0)
1396          {
1397            if (*option == '+')
1398              break;
1399            i++;
1400            if (i == (ssize_t) argc)
1401              ThrowMontageException(OptionError,"MissingArgument",option);
1402            if (IsGeometry(argv[i]) == MagickFalse)
1403              ThrowMontageInvalidArgumentException(option,argv[i]);
1404            break;
1405          }
1406        if (LocaleNCompare("respect-parentheses",option+1,17) == 0)
1407          {
1408            respect_parenthesis=(*option == '-') ? MagickTrue : MagickFalse;
1409            break;
1410          }
1411        if (LocaleCompare("reverse",option+1) == 0)
1412          break;
1413        if (LocaleCompare("rotate",option+1) == 0)
1414          {
1415            i++;
1416            if (i == (ssize_t) argc)
1417              ThrowMontageException(OptionError,"MissingArgument",option);
1418            if (IsGeometry(argv[i]) == MagickFalse)
1419              ThrowMontageInvalidArgumentException(option,argv[i]);
1420            break;
1421          }
1422        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1423      }
1424      case 's':
1425      {
1426        if (LocaleCompare("sampling-factor",option+1) == 0)
1427          {
1428            if (*option == '+')
1429              break;
1430            i++;
1431            if (i == (ssize_t) argc)
1432              ThrowMontageException(OptionError,"MissingArgument",option);
1433            if (IsGeometry(argv[i]) == MagickFalse)
1434              ThrowMontageInvalidArgumentException(option,argv[i]);
1435            break;
1436          }
1437        if (LocaleCompare("seed",option+1) == 0)
1438          {
1439            if (*option == '+')
1440              break;
1441            i++;
1442            if (i == (ssize_t) (argc-1))
1443              ThrowMontageException(OptionError,"MissingArgument",option);
1444            if (IsGeometry(argv[i]) == MagickFalse)
1445              ThrowMontageInvalidArgumentException(option,argv[i]);
1446            break;
1447          }
1448        if (LocaleCompare("scenes",option+1) == 0)
1449          {
1450            first_scene=0;
1451            last_scene=0;
1452            if (*option == '+')
1453              break;
1454            i++;
1455            if (i == (ssize_t) argc)
1456              ThrowMontageException(OptionError,"MissingArgument",option);
1457            if (IsSceneGeometry(argv[i],MagickFalse) == MagickFalse)
1458              ThrowMontageInvalidArgumentException(option,argv[i]);
1459            first_scene=(int) StringToLong(argv[i]);
1460            last_scene=first_scene;
1461            (void) sscanf(argv[i],"%ld-%ld",&first_scene,&last_scene);
1462            break;
1463          }
1464        if (LocaleCompare("set",option+1) == 0)
1465          {
1466            i++;
1467            if (i == (ssize_t) argc)
1468              ThrowMontageException(OptionError,"MissingArgument",option);
1469            if (*option == '+')
1470              break;
1471            i++;
1472            if (i == (ssize_t) argc)
1473              ThrowMontageException(OptionError,"MissingArgument",option);
1474            break;
1475          }
1476        if (LocaleCompare("shadow",option+1) == 0)
1477          {
1478            if (k == 0)
1479              {
1480                (void) CopyMagickString(argv[i]+1,"sans",MaxTextExtent);
1481                montage_info->shadow=(*option == '-') ? MagickTrue :
1482                  MagickFalse;
1483                break;
1484              }
1485            if (*option == '+')
1486              break;
1487            i++;
1488            if (i == (ssize_t) (argc-1))
1489              ThrowMontageException(OptionError,"MissingArgument",option);
1490            if (IsGeometry(argv[i]) == MagickFalse)
1491              ThrowMontageInvalidArgumentException(option,argv[i]);
1492            break;
1493          }
1494        if (LocaleCompare("sharpen",option+1) == 0)
1495          {
1496            if (*option == '+')
1497              break;
1498            i++;
1499            if ((i == (ssize_t) argc) || (IsGeometry(argv[i]) == MagickFalse))
1500              ThrowMontageException(OptionError,"MissingArgument",option);
1501            break;
1502          }
1503        if (LocaleCompare("size",option+1) == 0)
1504          {
1505            if (*option == '+')
1506              break;
1507            i++;
1508            if (i == (ssize_t) argc)
1509              ThrowMontageException(OptionError,"MissingArgument",option);
1510            if (IsGeometry(argv[i]) == MagickFalse)
1511              ThrowMontageInvalidArgumentException(option,argv[i]);
1512            break;
1513          }
1514        if (LocaleCompare("stroke",option+1) == 0)
1515          {
1516            (void) QueryColorCompliance("none",AllCompliance,
1517              &montage_info->stroke,exception);
1518            if (*option == '+')
1519              break;
1520            i++;
1521            if (i == (ssize_t) argc)
1522              ThrowMontageException(OptionError,"MissingArgument",option);
1523            (void) QueryColorCompliance(argv[i],AllCompliance,
1524              &montage_info->stroke,exception);
1525            break;
1526          }
1527        if (LocaleCompare("strip",option+1) == 0)
1528          break;
1529        if (LocaleCompare("strokewidth",option+1) == 0)
1530          {
1531            if (*option == '+')
1532              break;
1533            i++;
1534            if (i == (ssize_t) argc)
1535              ThrowMontageException(OptionError,"MissingArgument",option);
1536            if (IsGeometry(argv[i]) == MagickFalse)
1537              ThrowMontageInvalidArgumentException(option,argv[i]);
1538            break;
1539          }
1540        if (LocaleCompare("support",option+1) == 0)
1541          {
1542            i++;  /* deprecated */
1543            break;
1544          }
1545        if (LocaleCompare("swap",option+1) == 0)
1546          {
1547            if (*option == '+')
1548              break;
1549            i++;
1550            if (i == (ssize_t) (argc-1))
1551              ThrowMontageException(OptionError,"MissingArgument",option);
1552            if (IsGeometry(argv[i]) == MagickFalse)
1553              ThrowMontageInvalidArgumentException(option,argv[i]);
1554            break;
1555          }
1556        if (LocaleCompare("synchronize",option+1) == 0)
1557          break;
1558        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1559      }
1560      case 't':
1561      {
1562        if (LocaleCompare("taint",option+1) == 0)
1563          break;
1564        if (LocaleCompare("texture",option+1) == 0)
1565          {
1566            (void) CloneString(&montage_info->texture,(char *) NULL);
1567            if (*option == '+')
1568              break;
1569            i++;
1570            if (i == (ssize_t) argc)
1571              ThrowMontageException(OptionError,"MissingArgument",option);
1572            (void) CloneString(&montage_info->texture,argv[i]);
1573            break;
1574          }
1575        if (LocaleCompare("thumbnail",option+1) == 0)
1576          {
1577            if (*option == '+')
1578              break;
1579            i++;
1580            if (i == (ssize_t) argc)
1581              ThrowMontageException(OptionError,"MissingArgument",option);
1582            if (IsGeometry(argv[i]) == MagickFalse)
1583              ThrowMontageInvalidArgumentException(option,argv[i]);
1584            break;
1585          }
1586        if (LocaleCompare("tile",option+1) == 0)
1587          {
1588            if (k == 0)
1589              {
1590                (void) CopyMagickString(argv[i]+1,"sans",MaxTextExtent);
1591                (void) CloneString(&montage_info->tile,(char *) NULL);
1592              }
1593            if (*option == '+')
1594              break;
1595            i++;
1596            if (i == (ssize_t) argc)
1597              ThrowMontageException(OptionError,"MissingArgument",option);
1598            if (IsGeometry(argv[i]) == MagickFalse)
1599              ThrowMontageInvalidArgumentException(option,argv[i]);
1600            if (k == 0)
1601              (void) CloneString(&montage_info->tile,argv[i]);
1602            break;
1603          }
1604        if (LocaleCompare("tile-offset",option+1) == 0)
1605          {
1606            if (*option == '+')
1607              break;
1608            i++;
1609            if (i == (ssize_t) (argc-1))
1610              ThrowMontageException(OptionError,"MissingArgument",option);
1611            if (IsGeometry(argv[i]) == MagickFalse)
1612              ThrowMontageInvalidArgumentException(option,argv[i]);
1613            break;
1614          }
1615        if (LocaleCompare("tint",option+1) == 0)
1616          {
1617            if (*option == '+')
1618              break;
1619            i++;
1620            if (i == (ssize_t) argc)
1621              ThrowMontageException(OptionError,"MissingArgument",option);
1622            if (IsGeometry(argv[i]) == MagickFalse)
1623              ThrowMontageInvalidArgumentException(option,argv[i]);
1624            break;
1625          }
1626        if (LocaleCompare("transform",option+1) == 0)
1627          break;
1628        if (LocaleCompare("transpose",option+1) == 0)
1629          break;
1630        if (LocaleCompare("title",option+1) == 0)
1631          {
1632            (void) CloneString(&montage_info->title,(char *) NULL);
1633            if (*option == '+')
1634              break;
1635            i++;
1636            if (i == (ssize_t) argc)
1637              ThrowMontageException(OptionError,"MissingArgument",option);
1638            (void) CloneString(&montage_info->title,argv[i]);
1639            break;
1640          }
1641        if (LocaleCompare("transform",option+1) == 0)
1642          break;
1643        if (LocaleCompare("transparent",option+1) == 0)
1644          {
1645            transparent_color=(char *) NULL;
1646            i++;
1647            if (i == (ssize_t) argc)
1648              ThrowMontageException(OptionError,"MissingArgument",option);
1649            (void) CloneString(&transparent_color,argv[i]);
1650            break;
1651          }
1652        if (LocaleCompare("transparent-color",option+1) == 0)
1653          {
1654            if (*option == '+')
1655              break;
1656            i++;
1657            if (i == (ssize_t) (argc-1))
1658              ThrowMontageException(OptionError,"MissingArgument",option);
1659            break;
1660          }
1661        if (LocaleCompare("treedepth",option+1) == 0)
1662          {
1663            if (*option == '+')
1664              break;
1665            i++;
1666            if (i == (ssize_t) argc)
1667              ThrowMontageException(OptionError,"MissingArgument",option);
1668            if (IsGeometry(argv[i]) == MagickFalse)
1669              ThrowMontageInvalidArgumentException(option,argv[i]);
1670            break;
1671          }
1672        if (LocaleCompare("trim",option+1) == 0)
1673          break;
1674        if (LocaleCompare("type",option+1) == 0)
1675          {
1676            ssize_t
1677              type;
1678
1679            if (*option == '+')
1680              break;
1681            i++;
1682            if (i == (ssize_t) argc)
1683              ThrowMontageException(OptionError,"MissingArgument",option);
1684            type=ParseCommandOption(MagickTypeOptions,MagickFalse,argv[i]);
1685            if (type < 0)
1686              ThrowMontageException(OptionError,"UnrecognizedImageType",
1687                argv[i]);
1688            break;
1689          }
1690        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1691      }
1692      case 'u':
1693      {
1694        if (LocaleCompare("units",option+1) == 0)
1695          {
1696            ssize_t
1697              units;
1698
1699            if (*option == '+')
1700              break;
1701            i++;
1702            if (i == (ssize_t) (argc-1))
1703              ThrowMontageException(OptionError,"MissingArgument",option);
1704            units=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1705              argv[i]);
1706            if (units < 0)
1707              ThrowMontageException(OptionError,"UnrecognizedUnitsType",
1708                argv[i]);
1709            break;
1710          }
1711        if (LocaleCompare("unsharp",option+1) == 0)
1712          {
1713            if (*option == '+')
1714              break;
1715            i++;
1716            if (i == (ssize_t) (argc-1))
1717              ThrowMontageException(OptionError,"MissingArgument",option);
1718            if (IsGeometry(argv[i]) == MagickFalse)
1719              ThrowMontageInvalidArgumentException(option,argv[i]);
1720            break;
1721          }
1722        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1723      }
1724      case 'v':
1725      {
1726        if (LocaleCompare("verbose",option+1) == 0)
1727          {
1728            break;
1729          }
1730        if ((LocaleCompare("version",option+1) == 0) ||
1731            (LocaleCompare("-version",option+1) == 0))
1732          {
1733            (void) FormatLocaleFile(stdout,"Version: %s\n",
1734              GetMagickVersion((size_t *) NULL));
1735            (void) FormatLocaleFile(stdout,"Copyright: %s\n",
1736              GetMagickCopyright());
1737            (void) FormatLocaleFile(stdout,"Features: %s\n\n",
1738              GetMagickFeatures());
1739            break;
1740          }
1741        if (LocaleCompare("virtual-pixel",option+1) == 0)
1742          {
1743            ssize_t
1744              method;
1745
1746            if (*option == '+')
1747              break;
1748            i++;
1749            if (i == (ssize_t) argc)
1750              ThrowMontageException(OptionError,"MissingArgument",option);
1751            method=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1752              argv[i]);
1753            if (method < 0)
1754              ThrowMontageException(OptionError,
1755                "UnrecognizedVirtualPixelMethod",argv[i]);
1756            break;
1757          }
1758        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1759      }
1760      case 'w':
1761      {
1762        if (LocaleCompare("white-point",option+1) == 0)
1763          {
1764            if (*option == '+')
1765              break;
1766            i++;
1767            if (i == (ssize_t) argc)
1768              ThrowMontageException(OptionError,"MissingArgument",option);
1769            if (IsGeometry(argv[i]) == MagickFalse)
1770              ThrowMontageInvalidArgumentException(option,argv[i]);
1771            break;
1772          }
1773        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1774      }
1775      case '?':
1776        break;
1777      default:
1778        ThrowMontageException(OptionError,"UnrecognizedOption",option)
1779    }
1780    fire=(GetCommandOptionFlags(MagickCommandOptions,MagickFalse,option) &
1781      FireOptionFlag) == 0 ?  MagickFalse : MagickTrue;
1782    if (fire != MagickFalse)
1783      FireImageStack(MagickTrue,MagickTrue,MagickTrue);
1784  }
1785  if (k != 0)
1786    ThrowMontageException(OptionError,"UnbalancedParenthesis",argv[i]);
1787  if (i-- != (ssize_t) (argc-1))
1788    ThrowMontageException(OptionError,"MissingAnImageFilename",argv[i]);
1789  if (image == (Image *) NULL)
1790    ThrowMontageException(OptionError,"MissingAnImageFilename",argv[argc-1]);
1791  FinalizeImageSettings(image_info,image,MagickTrue);
1792  if (image == (Image *) NULL)
1793    ThrowMontageException(OptionError,"MissingAnImageFilename",argv[argc-1]);
1794  (void) CopyMagickString(montage_info->filename,argv[argc-1],MaxTextExtent);
1795  montage_image=MontageImageList(image_info,montage_info,image,exception);
1796  if (montage_image == (Image *) NULL)
1797    status=MagickFalse;
1798  else
1799    {
1800      /*
1801        Write image.
1802      */
1803      (void) CopyMagickString(image_info->filename,argv[argc-1],MaxTextExtent);
1804      (void) CopyMagickString(montage_image->magick_filename,argv[argc-1],
1805        MaxTextExtent);
1806      if (*montage_image->magick == '\0')
1807        (void) CopyMagickString(montage_image->magick,image->magick,
1808          MaxTextExtent);
1809      status&=WriteImages(image_info,montage_image,argv[argc-1],exception);
1810      if (metadata != (char **) NULL)
1811        {
1812          char
1813            *text;
1814
1815          text=InterpretImageProperties(image_info,montage_image,format,
1816            exception);
1817          if (text == (char *) NULL)
1818            ThrowMontageException(ResourceLimitError,"MemoryAllocationFailed",
1819              GetExceptionMessage(errno));
1820          (void) ConcatenateString(&(*metadata),text);
1821          (void) ConcatenateString(&(*metadata),"\n");
1822          text=DestroyString(text);
1823        }
1824    }
1825  montage_info=DestroyMontageInfo(montage_info);
1826  DestroyMontage();
1827  return(status != 0 ? MagickTrue : MagickFalse);
1828}
1829