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