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