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