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