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