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