]> 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-2011 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=InterpretLocaleValue(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=InterpretLocaleValue(argv[i],
1286               (char **) NULL);
1287             break;
1288           }
1289         if (LocaleCompare("polaroid",option+1) == 0)
1290           {
1291             if (*option == '+')
1292               break;
1293             i++;
1294             if (i == (ssize_t) (argc-1))
1295               ThrowMontageException(OptionError,"MissingArgument",option);
1296             if (IsGeometry(argv[i]) == MagickFalse)
1297               ThrowMontageInvalidArgumentException(option,argv[i]);
1298             break;
1299           }
1300         if (LocaleCompare("profile",option+1) == 0)
1301           {
1302             i++;
1303             if (i == (ssize_t) (argc-1))
1304               ThrowMontageException(OptionError,"MissingArgument",option);
1305             break;
1306           }
1307         ThrowMontageException(OptionError,"UnrecognizedOption",option)
1308       }
1309       case 'q':
1310       {
1311         if (LocaleCompare("quality",option+1) == 0)
1312           {
1313             if (*option == '+')
1314               break;
1315             i++;
1316             if (i == (ssize_t) argc)
1317               ThrowMontageException(OptionError,"MissingArgument",option);
1318             if (IsGeometry(argv[i]) == MagickFalse)
1319               ThrowMontageInvalidArgumentException(option,argv[i]);
1320             break;
1321           }
1322         if (LocaleCompare("quantize",option+1) == 0)
1323           {
1324             ssize_t
1325               colorspace;
1326
1327             if (*option == '+')
1328               break;
1329             i++;
1330             if (i == (ssize_t) (argc-1))
1331               ThrowMontageException(OptionError,"MissingArgument",option);
1332             colorspace=ParseCommandOption(MagickColorspaceOptions,
1333               MagickFalse,argv[i]);
1334             if (colorspace < 0)
1335               ThrowMontageException(OptionError,"UnrecognizedColorspace",
1336                 argv[i]);
1337             break;
1338           }
1339         if (LocaleCompare("quiet",option+1) == 0)
1340           break;
1341         ThrowMontageException(OptionError,"UnrecognizedOption",option)
1342       }
1343       case 'r':
1344       {
1345         if (LocaleCompare("red-primary",option+1) == 0)
1346           {
1347             if (*option == '+')
1348               break;
1349             i++;
1350             if (i == (ssize_t) argc)
1351               ThrowMontageException(OptionError,"MissingArgument",option);
1352             if (IsGeometry(argv[i]) == MagickFalse)
1353               ThrowMontageInvalidArgumentException(option,argv[i]);
1354             break;
1355           }
1356         if (LocaleCompare("regard-warnings",option+1) == 0)
1357           break;
1358         if (LocaleCompare("render",option+1) == 0)
1359           break;
1360         if (LocaleCompare("repage",option+1) == 0)
1361           {
1362             if (*option == '+')
1363               break;
1364             i++;
1365             if (i == (ssize_t) argc)
1366               ThrowMontageException(OptionError,"MissingArgument",option);
1367             if (IsGeometry(argv[i]) == MagickFalse)
1368               ThrowMontageInvalidArgumentException(option,argv[i]);
1369             break;
1370           }
1371         if (LocaleCompare("resize",option+1) == 0)
1372           {
1373             if (*option == '+')
1374               break;
1375             i++;
1376             if (i == (ssize_t) argc)
1377               ThrowMontageException(OptionError,"MissingArgument",option);
1378             if (IsGeometry(argv[i]) == MagickFalse)
1379               ThrowMontageInvalidArgumentException(option,argv[i]);
1380             break;
1381           }
1382         if (LocaleNCompare("respect-parentheses",option+1,17) == 0)
1383           {
1384             respect_parenthesis=(*option == '-') ? MagickTrue : MagickFalse;
1385             break;
1386           }
1387         if (LocaleCompare("rotate",option+1) == 0)
1388           {
1389             i++;
1390             if (i == (ssize_t) argc)
1391               ThrowMontageException(OptionError,"MissingArgument",option);
1392             if (IsGeometry(argv[i]) == MagickFalse)
1393               ThrowMontageInvalidArgumentException(option,argv[i]);
1394             break;
1395           }
1396         ThrowMontageException(OptionError,"UnrecognizedOption",option)
1397       }
1398       case 's':
1399       {
1400         if (LocaleCompare("sampling-factor",option+1) == 0)
1401           {
1402             if (*option == '+')
1403               break;
1404             i++;
1405             if (i == (ssize_t) argc)
1406               ThrowMontageException(OptionError,"MissingArgument",option);
1407             if (IsGeometry(argv[i]) == MagickFalse)
1408               ThrowMontageInvalidArgumentException(option,argv[i]);
1409             break;
1410           }
1411         if (LocaleCompare("seed",option+1) == 0)
1412           {
1413             if (*option == '+')
1414               break;
1415             i++;
1416             if (i == (ssize_t) (argc-1))
1417               ThrowMontageException(OptionError,"MissingArgument",option);
1418             if (IsGeometry(argv[i]) == MagickFalse)
1419               ThrowMontageInvalidArgumentException(option,argv[i]);
1420             break;
1421           }
1422         if (LocaleCompare("scenes",option+1) == 0)
1423           {
1424             first_scene=0;
1425             last_scene=0;
1426             if (*option == '+')
1427               break;
1428             i++;
1429             if (i == (ssize_t) argc)
1430               ThrowMontageException(OptionError,"MissingArgument",option);
1431             if (IsSceneGeometry(argv[i],MagickFalse) == MagickFalse)
1432               ThrowMontageInvalidArgumentException(option,argv[i]);
1433             first_scene=(int) StringToLong(argv[i]);
1434             last_scene=first_scene;
1435             (void) sscanf(argv[i],"%ld-%ld",&first_scene,&last_scene);
1436             break;
1437           }
1438         if (LocaleCompare("set",option+1) == 0)
1439           {
1440             i++;
1441             if (i == (ssize_t) argc)
1442               ThrowMontageException(OptionError,"MissingArgument",option);
1443             if (*option == '+')
1444               break;
1445             i++;
1446             if (i == (ssize_t) argc)
1447               ThrowMontageException(OptionError,"MissingArgument",option);
1448             break;
1449           }
1450         if (LocaleCompare("shadow",option+1) == 0)
1451           {
1452             if (k == 0)
1453               {
1454                 (void) CopyMagickString(argv[i]+1,"sans",MaxTextExtent);
1455                 montage_info->shadow=(*option == '-') ? MagickTrue :
1456                   MagickFalse;
1457                 break;
1458               }
1459             if (*option == '+')
1460               break;
1461             i++;
1462             if (i == (ssize_t) (argc-1))
1463               ThrowMontageException(OptionError,"MissingArgument",option);
1464             if (IsGeometry(argv[i]) == MagickFalse)
1465               ThrowMontageInvalidArgumentException(option,argv[i]);
1466             break;
1467           }
1468         if (LocaleCompare("sharpen",option+1) == 0)
1469           {
1470             if (*option == '+')
1471               break;
1472             i++;
1473             if ((i == (ssize_t) argc) || (IsGeometry(argv[i]) == MagickFalse))
1474               ThrowMontageException(OptionError,"MissingArgument",option);
1475             break;
1476           }
1477         if (LocaleCompare("size",option+1) == 0)
1478           {
1479             if (*option == '+')
1480               break;
1481             i++;
1482             if (i == (ssize_t) argc)
1483               ThrowMontageException(OptionError,"MissingArgument",option);
1484             if (IsGeometry(argv[i]) == MagickFalse)
1485               ThrowMontageInvalidArgumentException(option,argv[i]);
1486             break;
1487           }
1488         if (LocaleCompare("stroke",option+1) == 0)
1489           {
1490             (void) QueryColorCompliance("none",AllCompliance,
1491               &montage_info->stroke,exception);
1492             if (*option == '+')
1493               break;
1494             i++;
1495             if (i == (ssize_t) argc)
1496               ThrowMontageException(OptionError,"MissingArgument",option);
1497             (void) QueryColorCompliance(argv[i],AllCompliance,
1498               &montage_info->stroke,exception);
1499             break;
1500           }
1501         if (LocaleCompare("strip",option+1) == 0)
1502           break;
1503         if (LocaleCompare("strokewidth",option+1) == 0)
1504           {
1505             if (*option == '+')
1506               break;
1507             i++;
1508             if (i == (ssize_t) argc)
1509               ThrowMontageException(OptionError,"MissingArgument",option);
1510             if (IsGeometry(argv[i]) == MagickFalse)
1511               ThrowMontageInvalidArgumentException(option,argv[i]);
1512             break;
1513           }
1514         if (LocaleCompare("support",option+1) == 0)
1515           {
1516             i++;  /* deprecated */
1517             break;
1518           }
1519         if (LocaleCompare("synchronize",option+1) == 0)
1520           break;
1521         ThrowMontageException(OptionError,"UnrecognizedOption",option)
1522       }
1523       case 't':
1524       {
1525         if (LocaleCompare("taint",option+1) == 0)
1526           break;
1527         if (LocaleCompare("texture",option+1) == 0)
1528           {
1529             (void) CloneString(&montage_info->texture,(char *) NULL);
1530             if (*option == '+')
1531               break;
1532             i++;
1533             if (i == (ssize_t) argc)
1534               ThrowMontageException(OptionError,"MissingArgument",option);
1535             (void) CloneString(&montage_info->texture,argv[i]);
1536             break;
1537           }
1538         if (LocaleCompare("thumbnail",option+1) == 0)
1539           {
1540             if (*option == '+')
1541               break;
1542             i++;
1543             if (i == (ssize_t) argc)
1544               ThrowMontageException(OptionError,"MissingArgument",option);
1545             if (IsGeometry(argv[i]) == MagickFalse)
1546               ThrowMontageInvalidArgumentException(option,argv[i]);
1547             break;
1548           }
1549         if (LocaleCompare("tile",option+1) == 0)
1550           {
1551             if (k == 0)
1552               {
1553                 (void) CopyMagickString(argv[i]+1,"sans",MaxTextExtent);
1554                 (void) CloneString(&montage_info->tile,(char *) NULL);
1555               }
1556             if (*option == '+')
1557               break;
1558             i++;
1559             if (i == (ssize_t) argc)
1560               ThrowMontageException(OptionError,"MissingArgument",option);
1561             if (IsGeometry(argv[i]) == MagickFalse)
1562               ThrowMontageInvalidArgumentException(option,argv[i]);
1563             if (k == 0)
1564               (void) CloneString(&montage_info->tile,argv[i]);
1565             break;
1566           }
1567         if (LocaleCompare("tile-offset",option+1) == 0)
1568           {
1569             if (*option == '+')
1570               break;
1571             i++;
1572             if (i == (ssize_t) (argc-1))
1573               ThrowMontageException(OptionError,"MissingArgument",option);
1574             if (IsGeometry(argv[i]) == MagickFalse)
1575               ThrowMontageInvalidArgumentException(option,argv[i]);
1576             break;
1577           }
1578         if (LocaleCompare("tint",option+1) == 0)
1579           {
1580             if (*option == '+')
1581               break;
1582             i++;
1583             if (i == (ssize_t) argc)
1584               ThrowMontageException(OptionError,"MissingArgument",option);
1585             if (IsGeometry(argv[i]) == MagickFalse)
1586               ThrowMontageInvalidArgumentException(option,argv[i]);
1587             break;
1588           }
1589         if (LocaleCompare("transform",option+1) == 0)
1590           break;
1591         if (LocaleCompare("transpose",option+1) == 0)
1592           break;
1593         if (LocaleCompare("title",option+1) == 0)
1594           {
1595             (void) CloneString(&montage_info->title,(char *) NULL);
1596             if (*option == '+')
1597               break;
1598             i++;
1599             if (i == (ssize_t) argc)
1600               ThrowMontageException(OptionError,"MissingArgument",option);
1601             (void) CloneString(&montage_info->title,argv[i]);
1602             break;
1603           }
1604         if (LocaleCompare("transform",option+1) == 0)
1605           break;
1606         if (LocaleCompare("transparent",option+1) == 0)
1607           {
1608             transparent_color=(char *) NULL;
1609             i++;
1610             if (i == (ssize_t) argc)
1611               ThrowMontageException(OptionError,"MissingArgument",option);
1612             (void) CloneString(&transparent_color,argv[i]);
1613             break;
1614           }
1615         if (LocaleCompare("transparent-color",option+1) == 0)
1616           {
1617             if (*option == '+')
1618               break;
1619             i++;
1620             if (i == (ssize_t) (argc-1))
1621               ThrowMontageException(OptionError,"MissingArgument",option);
1622             break;
1623           }
1624         if (LocaleCompare("treedepth",option+1) == 0)
1625           {
1626             if (*option == '+')
1627               break;
1628             i++;
1629             if (i == (ssize_t) argc)
1630               ThrowMontageException(OptionError,"MissingArgument",option);
1631             if (IsGeometry(argv[i]) == MagickFalse)
1632               ThrowMontageInvalidArgumentException(option,argv[i]);
1633             break;
1634           }
1635         if (LocaleCompare("trim",option+1) == 0)
1636           break;
1637         if (LocaleCompare("type",option+1) == 0)
1638           {
1639             ssize_t
1640               type;
1641
1642             if (*option == '+')
1643               break;
1644             i++;
1645             if (i == (ssize_t) argc)
1646               ThrowMontageException(OptionError,"MissingArgument",option);
1647             type=ParseCommandOption(MagickTypeOptions,MagickFalse,argv[i]);
1648             if (type < 0)
1649               ThrowMontageException(OptionError,"UnrecognizedImageType",
1650                 argv[i]);
1651             break;
1652           }
1653         ThrowMontageException(OptionError,"UnrecognizedOption",option)
1654       }
1655       case 'u':
1656       {
1657         if (LocaleCompare("units",option+1) == 0)
1658           {
1659             ssize_t
1660               units;
1661
1662             if (*option == '+')
1663               break;
1664             i++;
1665             if (i == (ssize_t) (argc-1))
1666               ThrowMontageException(OptionError,"MissingArgument",option);
1667             units=ParseCommandOption(MagickResolutionOptions,MagickFalse,
1668               argv[i]);
1669             if (units < 0)
1670               ThrowMontageException(OptionError,"UnrecognizedUnitsType",
1671                 argv[i]);
1672             break;
1673           }
1674         if (LocaleCompare("unsharp",option+1) == 0)
1675           {
1676             if (*option == '+')
1677               break;
1678             i++;
1679             if (i == (ssize_t) (argc-1))
1680               ThrowMontageException(OptionError,"MissingArgument",option);
1681             if (IsGeometry(argv[i]) == MagickFalse)
1682               ThrowMontageInvalidArgumentException(option,argv[i]);
1683             break;
1684           }
1685         ThrowMontageException(OptionError,"UnrecognizedOption",option)
1686       }
1687       case 'v':
1688       {
1689         if (LocaleCompare("verbose",option+1) == 0)
1690           {
1691             break;
1692           }
1693         if ((LocaleCompare("version",option+1) == 0) ||
1694             (LocaleCompare("-version",option+1) == 0))
1695           {
1696             (void) FormatLocaleFile(stdout,"Version: %s\n",
1697               GetMagickVersion((size_t *) NULL));
1698             (void) FormatLocaleFile(stdout,"Copyright: %s\n",
1699               GetMagickCopyright());
1700             (void) FormatLocaleFile(stdout,"Features: %s\n\n",
1701               GetMagickFeatures());
1702             break;
1703           }
1704         if (LocaleCompare("virtual-pixel",option+1) == 0)
1705           {
1706             ssize_t
1707               method;
1708
1709             if (*option == '+')
1710               break;
1711             i++;
1712             if (i == (ssize_t) argc)
1713               ThrowMontageException(OptionError,"MissingArgument",option);
1714             method=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
1715               argv[i]);
1716             if (method < 0)
1717               ThrowMontageException(OptionError,
1718                 "UnrecognizedVirtualPixelMethod",argv[i]);
1719             break;
1720           }
1721         ThrowMontageException(OptionError,"UnrecognizedOption",option)
1722       }
1723       case 'w':
1724       {
1725         if (LocaleCompare("white-point",option+1) == 0)
1726           {
1727             if (*option == '+')
1728               break;
1729             i++;
1730             if (i == (ssize_t) argc)
1731               ThrowMontageException(OptionError,"MissingArgument",option);
1732             if (IsGeometry(argv[i]) == MagickFalse)
1733               ThrowMontageInvalidArgumentException(option,argv[i]);
1734             break;
1735           }
1736         ThrowMontageException(OptionError,"UnrecognizedOption",option)
1737       }
1738       case '?':
1739         break;
1740       default:
1741         ThrowMontageException(OptionError,"UnrecognizedOption",option)
1742     }
1743     fire=(GetCommandOptionFlags(MagickCommandOptions,MagickFalse,option) &
1744       FireOptionFlag) == 0 ?  MagickFalse : MagickTrue;
1745     if (fire != MagickFalse)
1746       FireImageStack(MagickTrue,MagickTrue,MagickTrue);
1747   }
1748   if (k != 0)
1749     ThrowMontageException(OptionError,"UnbalancedParenthesis",argv[i]);
1750   if (i-- != (ssize_t) (argc-1))
1751     ThrowMontageException(OptionError,"MissingAnImageFilename",argv[i]);
1752   if (image == (Image *) NULL)
1753     ThrowMontageException(OptionError,"MissingAnImageFilename",argv[argc-1]);
1754   FinalizeImageSettings(image_info,image,MagickTrue);
1755   if (image == (Image *) NULL)
1756     ThrowMontageException(OptionError,"MissingAnImageFilename",argv[argc-1]);
1757   (void) CopyMagickString(montage_info->filename,argv[argc-1],MaxTextExtent);
1758   montage_image=MontageImageList(image_info,montage_info,image,exception);
1759   if (montage_image == (Image *) NULL)
1760     status=MagickFalse;
1761   else
1762     {
1763       /*
1764         Write image.
1765       */
1766       (void) CopyMagickString(image_info->filename,argv[argc-1],MaxTextExtent);
1767       (void) CopyMagickString(montage_image->magick_filename,argv[argc-1],
1768         MaxTextExtent);
1769       if (*montage_image->magick == '\0')
1770         (void) CopyMagickString(montage_image->magick,image->magick,
1771           MaxTextExtent);
1772       status&=WriteImages(image_info,montage_image,argv[argc-1],exception);
1773       if (metadata != (char **) NULL)
1774         {
1775           char
1776             *text;
1777
1778           text=InterpretImageProperties(image_info,montage_image,format,
1779             exception);
1780           if (text == (char *) NULL)
1781             ThrowMontageException(ResourceLimitError,"MemoryAllocationFailed",
1782               GetExceptionMessage(errno));
1783           (void) ConcatenateString(&(*metadata),text);
1784           (void) ConcatenateString(&(*metadata),"\n");
1785           text=DestroyString(text);
1786         }
1787     }
1788   montage_info=DestroyMontageInfo(montage_info);
1789   DestroyMontage();
1790   return(status != 0 ? MagickTrue : MagickFalse);
1791 }