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