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