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