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