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