1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                 IIIII  M   M  PPPP    OOO   RRRR   TTTTT                    %
7%                   I    MM MM  P   P  O   O  R   R    T                      %
8%                   I    M M M  PPPP   O   O  RRRR     T                      %
9%                   I    M   M  P      O   O  R R      T                      %
10%                 IIIII  M   M  P       OOO   R  R     T                      %
11%                                                                             %
12%                                                                             %
13%                       Import Image from X11 Screen                          %
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 import program to capture some or all of an X server screen and
37%  save the image to a file.
38%
39*/
40
41/*
42  Include declarations.
43*/
44#include "MagickWand/studio.h"
45#include "MagickWand/MagickWand.h"
46#include "MagickWand/mogrify-private.h"
47#include "MagickCore/string-private.h"
48#include "MagickCore/image-private.h"
49#include "MagickCore/xwindow-private.h"
50
51/*
52%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53%                                                                             %
54%                                                                             %
55%                                                                             %
56+   I m p o r t I m a g e C o m m a n d                                       %
57%                                                                             %
58%                                                                             %
59%                                                                             %
60%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61%
62%  ImportImageCommand() reads an image from any visible window on an X server
63%  and outputs it as an image file. You can capture a single window, the
64%  entire screen, or any rectangular portion of the screen.  You can use the
65%  display utility for redisplay, printing, editing, formatting, archiving,
66%  image processing, etc. of the captured image.
67%
68%  The target window can be specified by id, name, or may be selected by
69%  clicking the mouse in the desired window. If you press a button and then
70%  drag, a rectangle will form which expands and contracts as the mouse moves.
71%  To save the portion of the screen defined by the rectangle, just release
72%  the button. The keyboard bell is rung once at the beginning of the screen
73%  capture and twice when it completes.
74%
75%  The format of the ImportImageCommand method is:
76%
77%      MagickBooleanType ImportImageCommand(ImageInfo *image_info,int argc,
78%        char **argv,char **metadata,ExceptionInfo *exception)
79%
80%  A description of each parameter follows:
81%
82%    o image_info: the image info.
83%
84%    o argc: the number of elements in the argument vector.
85%
86%    o argv: A text array containing the command line arguments.
87%
88%    o metadata: any metadata is returned here.
89%
90%    o exception: return any errors or warnings in this structure.
91%
92*/
93
94static MagickBooleanType ImportUsage(void)
95{
96  const char
97    **p;
98
99  static const char
100    *miscellaneous[]=
101    {
102      "-debug events        display copious debugging information",
103      "-help                print program options",
104      "-list type           print a list of supported option arguments",
105      "-log format          format of debugging information",
106      "-version             print version information",
107      (char *) NULL
108    },
109    *operators[]=
110    {
111      "-annotate geometry text",
112      "                     annotate the image with text",
113      "-colors value        preferred number of colors in the image",
114      "-crop geometry       preferred size and location of the cropped image",
115      "-encipher filename   convert plain pixels to cipher pixels",
116      "-geometry geometry   preferred size or location of the image",
117      "-help                print program options",
118      "-monochrome          transform image to black and white",
119      "-negate              replace every pixel with its complementary color ",
120      "-repage geometry     size and location of an image canvas",
121      "-quantize colorspace reduce colors in this colorspace",
122      "-resize geometry     resize the image",
123      "-rotate degrees      apply Paeth rotation to the image",
124      "-strip               strip image of all profiles and comments",
125      "-thumbnail geometry  create a thumbnail of the image",
126      "-transparent color   make this color transparent within the image",
127      "-trim                trim image edges",
128      "-type type           image type",
129      (char *) NULL
130    },
131    *settings[]=
132    {
133      "-adjoin              join images into a single multi-image file",
134      "-border              include window border in the output image",
135      "-channel type        apply option to select image channels",
136      "-colorspace type     alternate image colorspace",
137      "-comment string      annotate image with comment",
138      "-compress type       type of pixel compression when writing the image",
139      "-define format:option",
140      "                     define one or more image format options",
141      "-density geometry    horizontal and vertical density of the image",
142      "-depth value         image depth",
143      "-descend             obtain image by descending window hierarchy",
144      "-display server      X server to contact",
145      "-dispose method      layer disposal method",
146      "-dither method       apply error diffusion to image",
147      "-delay value         display the next image after pausing",
148      "-encipher filename   convert plain pixels to cipher pixels",
149      "-endian type         endianness (MSB or LSB) of the image",
150      "-encoding type       text encoding type",
151      "-filter type         use this filter when resizing an image",
152      "-format \"string\"     output formatted image characteristics",
153      "-frame               include window manager frame",
154      "-gravity direction   which direction to gravitate towards",
155      "-identify            identify the format and characteristics of the image",
156      "-interlace type      None, Line, Plane, or Partition",
157      "-interpolate method  pixel color interpolation method",
158      "-label string        assign a label to an image",
159      "-limit type value    Area, Disk, Map, or Memory resource limit",
160      "-monitor             monitor progress",
161      "-page geometry       size and location of an image canvas",
162      "-pause seconds       seconds delay between snapshots",
163      "-pointsize value     font point size",
164      "-quality value       JPEG/MIFF/PNG compression level",
165      "-quiet               suppress all warning messages",
166      "-regard-warnings     pay attention to warning messages",
167      "-respect-parentheses settings remain in effect until parenthesis boundary",
168      "-sampling-factor geometry",
169      "                     horizontal and vertical sampling factor",
170      "-scene value         image scene number",
171      "-screen              select image from root window",
172      "-seed value          seed a new sequence of pseudo-random numbers",
173      "-set property value  set an image property",
174      "-silent              operate silently, i.e. don't ring any bells ",
175      "-snaps value         number of screen snapshots",
176      "-support factor      resize support: > 1.0 is blurry, < 1.0 is sharp",
177      "-synchronize         synchronize image to storage device",
178      "-taint               declare the image as modified",
179      "-transparent-color color",
180      "                     transparent color",
181      "-treedepth value     color tree depth",
182      "-verbose             print detailed information about the image",
183      "-virtual-pixel method",
184      "                     Constant, Edge, Mirror, or Tile",
185      "-window id           select window with this id or name",
186      (char *) NULL
187    };
188
189  ListMagickVersion(stdout);
190  (void) printf("Usage: %s [options ...] [ file ]\n",
191    GetClientName());
192  (void) printf("\nImage Settings:\n");
193  for (p=settings; *p != (char *) NULL; p++)
194    (void) printf("  %s\n",*p);
195  (void) printf("\nImage Operators:\n");
196  for (p=operators; *p != (char *) NULL; p++)
197    (void) printf("  %s\n",*p);
198  (void) printf("\nMiscellaneous Options:\n");
199  for (p=miscellaneous; *p != (char *) NULL; p++)
200    (void) printf("  %s\n",*p);
201  (void) printf(
202  "\nBy default, 'file' is written in the MIFF image format.  To\n");
203  (void) printf(
204    "specify a particular image format, precede the filename with an image\n");
205  (void) printf(
206    "format name and a colon (i.e. ps:image) or specify the image type as\n");
207  (void) printf(
208    "the filename suffix (i.e. image.ps).  Specify 'file' as '-' for\n");
209  (void) printf("standard input or output.\n");
210  return(MagickFalse);
211}
212
213WandExport MagickBooleanType ImportImageCommand(ImageInfo *image_info,
214  int argc,char **argv,char **wand_unused(metadata),ExceptionInfo *exception)
215{
216#if defined(MAGICKCORE_X11_DELEGATE)
217#define DestroyImport() \
218{ \
219  XDestroyResourceInfo(&resource_info); \
220  if (display != (Display *) NULL) \
221    { \
222      XCloseDisplay(display); \
223      display=(Display *) NULL; \
224    } \
225  DestroyImageStack(); \
226  if (target_window != (char *) NULL) \
227    target_window=DestroyString(target_window); \
228  for (i=0; i < (ssize_t) argc; i++) \
229    argv[i]=DestroyString(argv[i]); \
230  argv=(char **) RelinquishMagickMemory(argv); \
231}
232#define ThrowImportException(asperity,tag,option) \
233{ \
234  (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
235     option); \
236  DestroyImport(); \
237  return(MagickFalse); \
238}
239#define ThrowImportInvalidArgumentException(option,argument) \
240{ \
241  (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \
242    "InvalidArgument","'%s': %s",option,argument); \
243  DestroyImport(); \
244  return(MagickFalse); \
245}
246
247  char
248    *filename,
249    *option,
250    *resource_value,
251    *server_name,
252    *target_window;
253
254  Display
255    *display;
256
257  Image
258    *image;
259
260  ImageStack
261    image_stack[MaxImageStackDepth+1];
262
263  MagickBooleanType
264    fire,
265    pend,
266    respect_parenthesis;
267
268  MagickStatusType
269    status;
270
271  QuantizeInfo
272    *quantize_info;
273
274  register ssize_t
275    i;
276
277  ssize_t
278    j,
279    k,
280    snapshots;
281
282  XImportInfo
283    ximage_info;
284
285  XResourceInfo
286    resource_info;
287
288  XrmDatabase
289    resource_database;
290
291  /*
292    Set defaults.
293  */
294  assert(image_info != (ImageInfo *) NULL);
295  assert(image_info->signature == MagickCoreSignature);
296  if (image_info->debug != MagickFalse)
297    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
298  assert(exception != (ExceptionInfo *) NULL);
299  if (argc == 2)
300    {
301      option=argv[1];
302      if ((LocaleCompare("version",option+1) == 0) ||
303          (LocaleCompare("-version",option+1) == 0))
304        {
305          ListMagickVersion(stdout);
306          return(MagickTrue);
307        }
308    }
309  display=(Display *) NULL;
310  j=1;
311  k=0;
312  NewImageStack();
313  option=(char *) NULL;
314  pend=MagickFalse;
315  resource_database=(XrmDatabase) NULL;
316  respect_parenthesis=MagickFalse;
317  (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
318  server_name=(char *) NULL;
319  status=MagickTrue;
320  SetNotifyHandlers;
321  target_window=(char *) NULL;
322  /*
323    Check for server name specified on the command line.
324  */
325  ReadCommandlLine(argc,&argv);
326  status=ExpandFilenames(&argc,&argv);
327  if (status == MagickFalse)
328    ThrowImportException(ResourceLimitError,"MemoryAllocationFailed",
329      GetExceptionMessage(errno));
330  for (i=1; i < (ssize_t) argc; i++)
331  {
332    /*
333      Check command line for server name.
334    */
335    option=argv[i];
336    if (LocaleCompare("display",option+1) == 0)
337      {
338        /*
339          User specified server name.
340        */
341        i++;
342        if (i == (ssize_t) argc)
343          ThrowImportException(OptionError,"MissingArgument",option);
344        server_name=argv[i];
345      }
346    if ((LocaleCompare("help",option+1) == 0) ||
347        (LocaleCompare("-help",option+1) == 0))
348      return(ImportUsage());
349  }
350  /*
351    Get user defaults from X resource database.
352  */
353  display=XOpenDisplay(server_name);
354  if (display == (Display *) NULL)
355    ThrowImportException(XServerError,"UnableToOpenXServer",
356      XDisplayName(server_name));
357  (void) XSetErrorHandler(XError);
358  resource_database=XGetResourceDatabase(display,GetClientName());
359  XGetImportInfo(&ximage_info);
360  XGetResourceInfo(image_info,resource_database,GetClientName(),
361    &resource_info);
362  quantize_info=resource_info.quantize_info;
363  resource_value=XGetResourceInstance(resource_database,GetClientName(),
364    "border","False");
365  ximage_info.borders=IsStringTrue(resource_value);
366  resource_value=XGetResourceInstance(resource_database,GetClientName(),
367    "delay","0");
368  resource_info.delay=(unsigned int) StringToUnsignedLong(resource_value);
369  image_info->density=XGetResourceInstance(resource_database,GetClientName(),
370    "density",(char *) NULL);
371  resource_value=XGetResourceInstance(resource_database,GetClientName(),
372    "descend","False");
373  ximage_info.descend=IsStringTrue(resource_value);
374  resource_value=XGetResourceInstance(resource_database,GetClientName(),
375    "frame","False");
376  ximage_info.frame=IsStringTrue(resource_value);
377  resource_value=XGetResourceInstance(resource_database,GetClientName(),
378    "interlace","none");
379  image_info->interlace=UndefinedInterlace;
380  if (LocaleCompare("None",resource_value) == 0)
381    image_info->interlace=NoInterlace;
382  if (LocaleCompare("Line",resource_value) == 0)
383    image_info->interlace=LineInterlace;
384  if (LocaleCompare("Plane",resource_value) == 0)
385    image_info->interlace=PlaneInterlace;
386  if (LocaleCompare("Partition",resource_value) == 0)
387    image_info->interlace=PartitionInterlace;
388  if (image_info->interlace == UndefinedInterlace)
389    ThrowImportException(OptionError,"Unrecognized interlace type",
390      resource_value);
391  image_info->page=XGetResourceInstance(resource_database,GetClientName(),
392    "pageGeometry",(char *) NULL);
393  resource_value=XGetResourceInstance(resource_database,GetClientName(),
394    "pause","0");
395  resource_info.pause=(unsigned int) StringToUnsignedLong(resource_value);
396  resource_value=XGetResourceInstance(resource_database,GetClientName(),
397    "quality","85");
398  image_info->quality=StringToUnsignedLong(resource_value);
399  resource_value=XGetResourceInstance(resource_database,GetClientName(),
400    "screen","False");
401  ximage_info.screen=IsStringTrue(resource_value);
402  resource_value=XGetResourceInstance(resource_database,GetClientName(),
403    "silent","False");
404  ximage_info.silent=IsStringTrue(resource_value);
405  resource_value=XGetResourceInstance(resource_database,GetClientName(),
406    "verbose","False");
407  image_info->verbose=IsStringTrue(resource_value);
408  resource_value=XGetResourceInstance(resource_database,GetClientName(),
409    "dither","True");
410  quantize_info->dither_method=IsStringTrue(resource_value) != MagickFalse ?
411    RiemersmaDitherMethod : NoDitherMethod;
412  snapshots=1;
413  status=MagickTrue;
414  filename=(char *) NULL;
415  /*
416    Check command syntax.
417  */
418  for (i=1; i < (ssize_t) argc; i++)
419  {
420    option=argv[i];
421    if (LocaleCompare(option,"(") == 0)
422      {
423        FireImageStack(MagickFalse,MagickTrue,pend);
424        if (k == MaxImageStackDepth)
425          ThrowImportException(OptionError,"ParenthesisNestedTooDeeply",
426            option);
427        PushImageStack();
428        continue;
429      }
430    if (LocaleCompare(option,")") == 0)
431      {
432        FireImageStack(MagickFalse,MagickTrue,MagickTrue);
433        if (k == 0)
434          ThrowImportException(OptionError,"UnableToParseExpression",option);
435        PopImageStack();
436        continue;
437      }
438    if (IsCommandOption(option) == MagickFalse)
439      {
440        Image
441          *images;
442
443        size_t
444          scene;
445
446        /*
447          Read image from X server.
448        */
449        FireImageStack(MagickFalse,MagickFalse,pend);
450        filename=argv[i];
451        if (target_window != (char *) NULL)
452          (void) CopyMagickString(image_info->filename,target_window,
453            MagickPathExtent);
454        for (scene=0; scene < (size_t) MagickMax(snapshots,1); scene++)
455        {
456          MagickDelay(1000*resource_info.pause);
457          images=XImportImage(image_info,&ximage_info,exception);
458          status&=(images != (Image *) NULL) &&
459            (exception->severity < ErrorException);
460          if (images == (Image *) NULL)
461            continue;
462          (void) CopyMagickString(images->filename,filename,MagickPathExtent);
463          (void) CopyMagickString(images->magick,"PS",MagickPathExtent);
464          images->scene=scene;
465          AppendImageStack(images);
466        }
467        continue;
468      }
469    pend=image != (Image *) NULL ? MagickTrue : MagickFalse;
470    switch(*(option+1))
471    {
472      case 'a':
473      {
474        if (LocaleCompare("adjoin",option+1) == 0)
475          break;
476        if (LocaleCompare("annotate",option+1) == 0)
477          {
478            if (*option == '+')
479              break;
480            i++;
481            if (i == (ssize_t) argc)
482              ThrowImportException(OptionError,"MissingArgument",option);
483            if (IsGeometry(argv[i]) == MagickFalse)
484              ThrowImportInvalidArgumentException(option,argv[i]);
485            if (i == (ssize_t) argc)
486              ThrowImportException(OptionError,"MissingArgument",option);
487            i++;
488            break;
489          }
490        ThrowImportException(OptionError,"UnrecognizedOption",option);
491      }
492      case 'b':
493      {
494        if (LocaleCompare("border",option+1) == 0)
495          {
496            (void) CopyMagickString(argv[i]+1,"sans",MagickPathExtent);
497            ximage_info.borders=(*option == '-') ? MagickTrue : MagickFalse;
498            break;
499          }
500        if (LocaleCompare("bordercolor",option+1) == 0)
501          {
502            if (*option == '+')
503              break;
504            i++;
505            if (i == (ssize_t) argc)
506              ThrowImportException(OptionError,"MissingArgument",option);
507            break;
508          }
509        ThrowImportException(OptionError,"UnrecognizedOption",option);
510      }
511      case 'c':
512      {
513        if (LocaleCompare("cache",option+1) == 0)
514          {
515            if (*option == '+')
516              break;
517            i++;
518            if (i == (ssize_t) argc)
519              ThrowImportException(OptionError,"MissingArgument",option);
520            if (IsGeometry(argv[i]) == MagickFalse)
521              ThrowImportInvalidArgumentException(option,argv[i]);
522            break;
523          }
524        if (LocaleCompare("channel",option+1) == 0)
525          {
526            ssize_t
527              channel;
528
529            if (*option == '+')
530              break;
531            i++;
532            if (i == (ssize_t) argc)
533              ThrowImportException(OptionError,"MissingArgument",option);
534            channel=ParseChannelOption(argv[i]);
535            if (channel < 0)
536              ThrowImportException(OptionError,"UnrecognizedChannelType",
537                argv[i]);
538            break;
539          }
540        if (LocaleCompare("colors",option+1) == 0)
541          {
542            quantize_info->number_colors=0;
543            if (*option == '+')
544              break;
545            i++;
546            if (i == (ssize_t) argc)
547              ThrowImportException(OptionError,"MissingArgument",option);
548            if (IsGeometry(argv[i]) == MagickFalse)
549              ThrowImportInvalidArgumentException(option,argv[i]);
550            quantize_info->number_colors=StringToUnsignedLong(argv[i]);
551            break;
552          }
553        if (LocaleCompare("colorspace",option+1) == 0)
554          {
555            ssize_t
556              colorspace;
557
558            if (*option == '+')
559              break;
560            i++;
561            if (i == (ssize_t) argc)
562              ThrowImportException(OptionError,"MissingArgument",option);
563            colorspace=ParseCommandOption(MagickColorspaceOptions,MagickFalse,
564              argv[i]);
565            if (colorspace < 0)
566              ThrowImportException(OptionError,"UnrecognizedColorspace",
567                argv[i]);
568            break;
569          }
570        if (LocaleCompare("comment",option+1) == 0)
571          {
572            if (*option == '+')
573              break;
574            i++;
575            if (i == (ssize_t) argc)
576              ThrowImportException(OptionError,"MissingArgument",option);
577            status=SetImageOption(image_info,"comment",argv[i]);
578            if (status == MagickFalse)
579              ThrowImportException(OptionError,"UnrecognizedOption",argv[i]);
580            break;
581          }
582        if (LocaleCompare("compress",option+1) == 0)
583          {
584            ssize_t
585              compress;
586
587            if (*option == '+')
588              break;
589            i++;
590            if (i == (ssize_t) argc)
591              ThrowImportException(OptionError,"MissingArgument",option);
592            compress=ParseCommandOption(MagickCompressOptions,MagickFalse,
593              argv[i]);
594            if (compress < 0)
595              ThrowImportException(OptionError,"UnrecognizedImageCompression",
596                argv[i]);
597            break;
598          }
599        if (LocaleCompare("concurrent",option+1) == 0)
600          break;
601        if (LocaleCompare("crop",option+1) == 0)
602          {
603            if (*option == '+')
604              break;
605            i++;
606            if (i == (ssize_t) argc)
607              ThrowImportException(OptionError,"MissingArgument",option);
608            if (IsGeometry(argv[i]) == MagickFalse)
609              ThrowImportInvalidArgumentException(option,argv[i]);
610            break;
611          }
612        ThrowImportException(OptionError,"UnrecognizedOption",option);
613      }
614      case 'd':
615      {
616        if (LocaleCompare("debug",option+1) == 0)
617          {
618            ssize_t
619              event;
620
621            if (*option == '+')
622              break;
623            i++;
624            if (i == (ssize_t) argc)
625              ThrowImportException(OptionError,"MissingArgument",option);
626            event=ParseCommandOption(MagickLogEventOptions,MagickFalse,argv[i]);
627            if (event < 0)
628              ThrowImportException(OptionError,"UnrecognizedEventType",argv[i]);
629            (void) SetLogEventMask(argv[i]);
630            break;
631          }
632        if (LocaleCompare("define",option+1) == 0)
633          {
634            i++;
635            if (i == (ssize_t) argc)
636              ThrowImportException(OptionError,"MissingArgument",option);
637            if (*option == '+')
638              {
639                const char
640                  *define;
641
642                define=GetImageOption(image_info,argv[i]);
643                if (define == (char *) NULL)
644                  ThrowImportException(OptionError,"NoSuchOption",argv[i]);
645                break;
646              }
647            break;
648          }
649        if (LocaleCompare("delay",option+1) == 0)
650          {
651            if (*option == '+')
652              break;
653            i++;
654            if (i == (ssize_t) argc)
655              ThrowImportException(OptionError,"MissingArgument",option);
656            if (IsGeometry(argv[i]) == MagickFalse)
657              ThrowImportInvalidArgumentException(option,argv[i]);
658            status=SetImageOption(image_info,"delay",argv[i]);
659            if (status == MagickFalse)
660              ThrowImportException(OptionError,"UnrecognizedOption",argv[i]);
661            break;
662          }
663        if (LocaleCompare("density",option+1) == 0)
664          {
665            if (*option == '+')
666              break;
667            i++;
668            if (i == (ssize_t) argc)
669              ThrowImportException(OptionError,"MissingArgument",option);
670            if (IsGeometry(argv[i]) == MagickFalse)
671              ThrowImportInvalidArgumentException(option,argv[i]);
672            break;
673          }
674        if (LocaleCompare("depth",option+1) == 0)
675          {
676            if (*option == '+')
677              break;
678            i++;
679            if (i == (ssize_t) argc)
680              ThrowImportException(OptionError,"MissingArgument",option);
681            if (IsGeometry(argv[i]) == MagickFalse)
682              ThrowImportInvalidArgumentException(option,argv[i]);
683            break;
684          }
685        if (LocaleCompare("descend",option+1) == 0)
686          {
687            ximage_info.descend=(*option == '-') ? MagickTrue : MagickFalse;
688            break;
689          }
690        if (LocaleCompare("display",option+1) == 0)
691          {
692            if (*option == '+')
693              break;
694            i++;
695            if (i == (ssize_t) argc)
696              ThrowImportException(OptionError,"MissingArgument",option);
697            break;
698          }
699        if (LocaleCompare("dispose",option+1) == 0)
700          {
701            ssize_t
702              dispose;
703
704            if (*option == '+')
705              break;
706            i++;
707            if (i == (ssize_t) argc)
708              ThrowImportException(OptionError,"MissingArgument",option);
709            dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse,argv[i]);
710            if (dispose < 0)
711              ThrowImportException(OptionError,"UnrecognizedDisposeMethod",
712                argv[i]);
713            break;
714          }
715        if (LocaleCompare("dither",option+1) == 0)
716          {
717            ssize_t
718              method;
719
720            quantize_info->dither_method=NoDitherMethod;
721            if (*option == '+')
722              break;
723            i++;
724            if (i == (ssize_t) argc)
725              ThrowImportException(OptionError,"MissingArgument",option);
726            method=ParseCommandOption(MagickDitherOptions,MagickFalse,argv[i]);
727            if (method < 0)
728              ThrowImportException(OptionError,"UnrecognizedDitherMethod",
729                argv[i]);
730            quantize_info->dither_method=(DitherMethod) method;
731            break;
732          }
733        if (LocaleCompare("duration",option+1) == 0)
734          {
735            if (*option == '+')
736              break;
737            i++;
738            if (i == (ssize_t) argc)
739              ThrowImportException(OptionError,"MissingArgument",option);
740            if (IsGeometry(argv[i]) == MagickFalse)
741              ThrowImportInvalidArgumentException(option,argv[i]);
742            break;
743          }
744        ThrowImportException(OptionError,"UnrecognizedOption",option);
745      }
746      case 'e':
747      {
748        if (LocaleCompare("encipher",option+1) == 0)
749          {
750            if (*option == '+')
751              break;
752            i++;
753            if (i == (ssize_t) argc)
754              ThrowImportException(OptionError,"MissingArgument",option);
755            break;
756          }
757        if (LocaleCompare("encoding",option+1) == 0)
758          {
759            if (*option == '+')
760              break;
761            i++;
762            if (i == (ssize_t) argc)
763              ThrowImportException(OptionError,"MissingArgument",option);
764            break;
765          }
766        if (LocaleCompare("endian",option+1) == 0)
767          {
768            ssize_t
769              endian;
770
771            if (*option == '+')
772              break;
773            i++;
774            if (i == (ssize_t) argc)
775              ThrowImportException(OptionError,"MissingArgument",option);
776            endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
777              argv[i]);
778            if (endian < 0)
779              ThrowImportException(OptionError,"UnrecognizedEndianType",
780                argv[i]);
781            break;
782          }
783        ThrowImportException(OptionError,"UnrecognizedOption",option);
784      }
785      case 'f':
786      {
787        if (LocaleCompare("filter",option+1) == 0)
788          {
789            ssize_t
790              filter;
791
792            if (*option == '+')
793              break;
794            i++;
795            if (i == (ssize_t) argc)
796              ThrowImportException(OptionError,"MissingArgument",option);
797            filter=ParseCommandOption(MagickFilterOptions,MagickFalse,argv[i]);
798            if (filter < 0)
799              ThrowImportException(OptionError,"UnrecognizedImageFilter",
800                argv[i]);
801            break;
802          }
803        if (LocaleCompare("frame",option+1) == 0)
804          {
805            (void) CopyMagickString(argv[i]+1,"sans0",MagickPathExtent);
806            ximage_info.frame=(*option == '-') ? MagickTrue : MagickFalse;
807            break;
808          }
809        if (LocaleCompare("format",option+1) == 0)
810          {
811            if (*option == '+')
812              break;
813            i++;
814            if (i == (ssize_t) argc)
815              ThrowImportException(OptionError,"MissingArgument",option);
816            break;
817          }
818        ThrowImportException(OptionError,"UnrecognizedOption",option);
819      }
820      case 'g':
821      {
822        if (LocaleCompare("geometry",option+1) == 0)
823          {
824            if (*option == '+')
825              break;
826            i++;
827            if (i == (ssize_t) argc)
828              ThrowImportException(OptionError,"MissingArgument",option);
829            if (IsGeometry(argv[i]) == MagickFalse)
830              ThrowImportInvalidArgumentException(option,argv[i]);
831            break;
832          }
833        if (LocaleCompare("gravity",option+1) == 0)
834          {
835            ssize_t
836              gravity;
837
838            if (*option == '+')
839              break;
840            i++;
841            if (i == (ssize_t) argc)
842              ThrowImportException(OptionError,"MissingArgument",option);
843            gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,argv[i]);
844            if (gravity < 0)
845              ThrowImportException(OptionError,"UnrecognizedGravityType",
846                argv[i]);
847            break;
848          }
849        ThrowImportException(OptionError,"UnrecognizedOption",option);
850      }
851      case 'h':
852      {
853        if (LocaleCompare("help",option+1) == 0)
854          break;
855        ThrowImportException(OptionError,"UnrecognizedOption",option);
856      }
857      case 'i':
858      {
859        if (LocaleCompare("identify",option+1) == 0)
860          break;
861        if (LocaleCompare("interlace",option+1) == 0)
862          {
863            ssize_t
864              interlace;
865
866            if (*option == '+')
867              break;
868            i++;
869            if (i == (ssize_t) argc)
870              ThrowImportException(OptionError,"MissingArgument",option);
871            interlace=ParseCommandOption(MagickInterlaceOptions,MagickFalse,
872              argv[i]);
873            if (interlace < 0)
874              ThrowImportException(OptionError,"UnrecognizedInterlaceType",
875                argv[i]);
876            break;
877          }
878        if (LocaleCompare("interpolate",option+1) == 0)
879          {
880            ssize_t
881              interpolate;
882
883            if (*option == '+')
884              break;
885            i++;
886            if (i == (ssize_t) argc)
887              ThrowImportException(OptionError,"MissingArgument",option);
888            interpolate=ParseCommandOption(MagickInterpolateOptions,MagickFalse,
889              argv[i]);
890            if (interpolate < 0)
891              ThrowImportException(OptionError,"UnrecognizedInterpolateMethod",
892                argv[i]);
893            break;
894          }
895        ThrowImportException(OptionError,"UnrecognizedOption",option);
896      }
897      case 'l':
898      {
899        if (LocaleCompare("label",option+1) == 0)
900          {
901            if (*option == '+')
902              break;
903            i++;
904            if (i == (ssize_t) argc)
905              ThrowImportException(OptionError,"MissingArgument",option);
906            status=SetImageOption(image_info,"label",argv[i]);
907            if (status == MagickFalse)
908              ThrowImportException(OptionError,"UnrecognizedOption",argv[i]);
909            break;
910          }
911        if (LocaleCompare("limit",option+1) == 0)
912          {
913            char
914              *p;
915
916            double
917              value;
918
919            ssize_t
920              resource;
921
922            if (*option == '+')
923              break;
924            i++;
925            if (i == (ssize_t) argc)
926              ThrowImportException(OptionError,"MissingArgument",option);
927            resource=ParseCommandOption(MagickResourceOptions,MagickFalse,
928              argv[i]);
929            if (resource < 0)
930              ThrowImportException(OptionError,"UnrecognizedResourceType",
931                argv[i]);
932            i++;
933            if (i == (ssize_t) argc)
934              ThrowImportException(OptionError,"MissingArgument",option);
935            value=StringToDouble(argv[i],&p);
936            (void) value;
937            if ((p == argv[i]) && (LocaleCompare("unlimited",argv[i]) != 0))
938              ThrowImportInvalidArgumentException(option,argv[i]);
939            break;
940          }
941        if (LocaleCompare("list",option+1) == 0)
942          {
943            ssize_t
944              list;
945
946            if (*option == '+')
947              break;
948            i++;
949            if (i == (ssize_t) argc)
950              ThrowImportException(OptionError,"MissingArgument",option);
951            list=ParseCommandOption(MagickListOptions,MagickFalse,argv[i]);
952            if (list < 0)
953              ThrowImportException(OptionError,"UnrecognizedListType",argv[i]);
954            status=MogrifyImageInfo(image_info,(int) (i-j+1),(const char **)
955              argv+j,exception);
956            DestroyImport();
957            return(status == 0 ? MagickTrue : MagickFalse);
958          }
959        if (LocaleCompare("log",option+1) == 0)
960          {
961            if (*option == '+')
962              break;
963            i++;
964            if ((i == (ssize_t) argc) || (strchr(argv[i],'%') == (char *) NULL))
965              ThrowImportException(OptionError,"MissingArgument",option);
966            break;
967          }
968        ThrowImportException(OptionError,"UnrecognizedOption",option);
969      }
970      case 'm':
971      {
972        if (LocaleCompare("monitor",option+1) == 0)
973          break;
974        if (LocaleCompare("monochrome",option+1) == 0)
975          {
976            if (*option == '+')
977              break;
978            quantize_info->number_colors=2;
979            quantize_info->colorspace=GRAYColorspace;
980            break;
981          }
982        ThrowImportException(OptionError,"UnrecognizedOption",option);
983      }
984      case 'n':
985      {
986        if (LocaleCompare("negate",option+1) == 0)
987          break;
988        ThrowImportException(OptionError,"UnrecognizedOption",option);
989      }
990      case 'p':
991      {
992        if (LocaleCompare("page",option+1) == 0)
993          {
994            if (*option == '+')
995              break;
996            i++;
997            if (i == (ssize_t) argc)
998              ThrowImportException(OptionError,"MissingArgument",option);
999            status=SetImageOption(image_info,"page",argv[i]);
1000            if (status == MagickFalse)
1001              ThrowImportException(OptionError,"UnrecognizedOption",argv[i]);
1002            break;
1003          }
1004        if (LocaleCompare("pause",option+1) == 0)
1005          {
1006            resource_info.pause=0;
1007            if (*option == '+')
1008              break;
1009            i++;
1010            if (i == (ssize_t) argc)
1011              ThrowImportException(OptionError,"MissingArgument",option);
1012            if (IsGeometry(argv[i]) == MagickFalse)
1013              ThrowImportInvalidArgumentException(option,argv[i]);
1014            resource_info.pause=(unsigned int) StringToUnsignedLong(argv[i]);
1015            break;
1016          }
1017        if (LocaleCompare("ping",option+1) == 0)
1018          break;  /* deprecated option */
1019        if (LocaleCompare("pointsize",option+1) == 0)
1020          {
1021            if (*option == '+')
1022              break;
1023            i++;
1024            if (i == (ssize_t) argc)
1025              ThrowImportException(OptionError,"MissingArgument",option);
1026            if (IsGeometry(argv[i]) == MagickFalse)
1027              ThrowImportInvalidArgumentException(option,argv[i]);
1028            break;
1029          }
1030        ThrowImportException(OptionError,"UnrecognizedOption",option);
1031      }
1032      case 'q':
1033      {
1034        if (LocaleCompare("quality",option+1) == 0)
1035          {
1036            if (*option == '+')
1037              break;
1038            i++;
1039            if (i == (ssize_t) argc)
1040              ThrowImportException(OptionError,"MissingArgument",option);
1041            if (IsGeometry(argv[i]) == MagickFalse)
1042              ThrowImportInvalidArgumentException(option,argv[i]);
1043            break;
1044          }
1045        if (LocaleCompare("quantize",option+1) == 0)
1046          {
1047            ssize_t
1048              colorspace;
1049
1050            if (*option == '+')
1051              break;
1052            i++;
1053            if (i == (ssize_t) argc)
1054              ThrowImportException(OptionError,"MissingArgument",option);
1055            colorspace=ParseCommandOption(MagickColorspaceOptions,
1056              MagickFalse,argv[i]);
1057            if (colorspace < 0)
1058              ThrowImportException(OptionError,"UnrecognizedColorspace",
1059                argv[i]);
1060            break;
1061          }
1062        if (LocaleCompare("quiet",option+1) == 0)
1063          break;
1064        ThrowImportException(OptionError,"UnrecognizedOption",option);
1065      }
1066      case 'r':
1067      {
1068        if (LocaleCompare("regard-warnings",option+1) == 0)
1069          break;
1070        if (LocaleCompare("repage",option+1) == 0)
1071          {
1072            if (*option == '+')
1073              break;
1074            i++;
1075            if (i == (ssize_t) argc)
1076              ThrowImportException(OptionError,"MissingArgument",option);
1077            if (IsGeometry(argv[i]) == MagickFalse)
1078              ThrowImportInvalidArgumentException(option,argv[i]);
1079            break;
1080          }
1081        if (LocaleCompare("resize",option+1) == 0)
1082          {
1083            if (*option == '+')
1084              break;
1085            i++;
1086            if (i == (ssize_t) argc)
1087              ThrowImportException(OptionError,"MissingArgument",option);
1088            if (IsGeometry(argv[i]) == MagickFalse)
1089              ThrowImportInvalidArgumentException(option,argv[i]);
1090            break;
1091          }
1092        if (LocaleNCompare("respect-parentheses",option+1,17) == 0)
1093          {
1094            respect_parenthesis=(*option == '-') ? MagickTrue : MagickFalse;
1095            break;
1096          }
1097        if (LocaleCompare("rotate",option+1) == 0)
1098          {
1099            i++;
1100            if (i == (ssize_t) argc)
1101              ThrowImportException(OptionError,"MissingArgument",option);
1102            if (IsGeometry(argv[i]) == MagickFalse)
1103              ThrowImportInvalidArgumentException(option,argv[i]);
1104            break;
1105          }
1106        ThrowImportException(OptionError,"UnrecognizedOption",option);
1107      }
1108      case 's':
1109      {
1110        if (LocaleCompare("sampling-factor",option+1) == 0)
1111          {
1112            if (*option == '+')
1113              break;
1114            i++;
1115            if (i == (ssize_t) argc)
1116              ThrowImportException(OptionError,"MissingArgument",option);
1117            if (IsGeometry(argv[i]) == MagickFalse)
1118              ThrowImportInvalidArgumentException(option,argv[i]);
1119            break;
1120          }
1121        if (LocaleCompare("scene",option+1) == 0)
1122          {
1123            if (*option == '+')
1124              break;
1125            i++;
1126            if (i == (ssize_t) argc)
1127              ThrowImportException(OptionError,"MissingArgument",option);
1128            if (IsGeometry(argv[i]) == MagickFalse)
1129              ThrowImportInvalidArgumentException(option,argv[i]);
1130            break;
1131          }
1132        if (LocaleCompare("set",option+1) == 0)
1133          {
1134            i++;
1135            if (i == (ssize_t) argc)
1136              ThrowImportException(OptionError,"MissingArgument",option);
1137            if (*option == '+')
1138              break;
1139            i++;
1140            if (i == (ssize_t) argc)
1141              ThrowImportException(OptionError,"MissingArgument",option);
1142            break;
1143          }
1144        if (LocaleCompare("screen",option+1) == 0)
1145          {
1146            ximage_info.screen=(*option == '-') ? MagickTrue : MagickFalse;
1147            break;
1148          }
1149        if (LocaleCompare("seed",option+1) == 0)
1150          {
1151            if (*option == '+')
1152              break;
1153            i++;
1154            if (i == (ssize_t) argc)
1155              ThrowImportException(OptionError,"MissingArgument",option);
1156            if (IsGeometry(argv[i]) == MagickFalse)
1157              ThrowImportInvalidArgumentException(option,argv[i]);
1158            break;
1159          }
1160        if (LocaleCompare("silent",option+1) == 0)
1161          {
1162            ximage_info.silent=(*option == '-') ? MagickTrue : MagickFalse;
1163            break;
1164          }
1165        if (LocaleCompare("snaps",option+1) == 0)
1166          {
1167            (void) CopyMagickString(argv[i]+1,"sans",MagickPathExtent);
1168            i++;
1169            if (i == (ssize_t) argc)
1170              ThrowImportException(OptionError,"MissingArgument",option);
1171            if (IsGeometry(argv[i]) == MagickFalse)
1172              ThrowImportInvalidArgumentException(option,argv[i]);
1173            snapshots=(ssize_t) StringToLong(argv[i]);
1174            break;
1175          }
1176        if (LocaleCompare("strip",option+1) == 0)
1177          break;
1178        if (LocaleCompare("support",option+1) == 0)
1179          {
1180            i++;  /* deprecated */
1181            break;
1182          }
1183        if (LocaleCompare("synchronize",option+1) == 0)
1184          break;
1185        ThrowImportException(OptionError,"UnrecognizedOption",option);
1186      }
1187      case 't':
1188      {
1189        if (LocaleCompare("taint",option+1) == 0)
1190          break;
1191        if (LocaleCompare("thumbnail",option+1) == 0)
1192          {
1193            if (*option == '+')
1194              break;
1195            i++;
1196            if (i == (ssize_t) argc)
1197              ThrowImportException(OptionError,"MissingArgument",option);
1198            if (IsGeometry(argv[i]) == MagickFalse)
1199              ThrowImportInvalidArgumentException(option,argv[i]);
1200            break;
1201          }
1202        if (LocaleCompare("transparent",option+1) == 0)
1203          {
1204            i++;
1205            if (i == (ssize_t) argc)
1206              ThrowImportException(OptionError,"MissingArgument",option);
1207            break;
1208          }
1209        if (LocaleCompare("transparent-color",option+1) == 0)
1210          {
1211            if (*option == '+')
1212              break;
1213            i++;
1214            if (i == (ssize_t) argc)
1215              ThrowImportException(OptionError,"MissingArgument",option);
1216            break;
1217          }
1218        if (LocaleCompare("treedepth",option+1) == 0)
1219          {
1220            quantize_info->tree_depth=0;
1221            if (*option == '+')
1222              break;
1223            i++;
1224            if (i == (ssize_t) argc)
1225              ThrowImportException(OptionError,"MissingArgument",option);
1226            if (IsGeometry(argv[i]) == MagickFalse)
1227              ThrowImportInvalidArgumentException(option,argv[i]);
1228            quantize_info->tree_depth=StringToUnsignedLong(argv[i]);
1229            break;
1230          }
1231        if (LocaleCompare("trim",option+1) == 0)
1232          break;
1233        if (LocaleCompare("type",option+1) == 0)
1234          {
1235            ssize_t
1236              type;
1237
1238            if (*option == '+')
1239              break;
1240            i++;
1241            if (i == (ssize_t) argc)
1242              ThrowImportException(OptionError,"MissingArgument",option);
1243            type=ParseCommandOption(MagickTypeOptions,MagickFalse,argv[i]);
1244            if (type < 0)
1245              ThrowImportException(OptionError,"UnrecognizedImageType",argv[i]);
1246            break;
1247          }
1248        ThrowImportException(OptionError,"UnrecognizedOption",option);
1249      }
1250      case 'w':
1251      {
1252        i++;
1253        if (i == (ssize_t) argc)
1254          ThrowImportException(OptionError,"MissingArgument",option);
1255        (void) CloneString(&target_window,argv[i]);
1256        break;
1257      }
1258      case 'v':
1259      {
1260        if (LocaleCompare("verbose",option+1) == 0)
1261          break;
1262        if ((LocaleCompare("version",option+1) == 0) ||
1263            (LocaleCompare("-version",option+1) == 0))
1264          {
1265            ListMagickVersion(stdout);
1266            break;
1267          }
1268        ThrowImportException(OptionError,"UnrecognizedOption",option);
1269      }
1270      case '?':
1271        break;
1272      default:
1273        ThrowImportException(OptionError,"UnrecognizedOption",option);
1274    }
1275    fire=(GetCommandOptionFlags(MagickCommandOptions,MagickFalse,option) &
1276      FireOptionFlag) == 0 ?  MagickFalse : MagickTrue;
1277    if (fire != MagickFalse)
1278      FireImageStack(MagickFalse,MagickTrue,MagickTrue);
1279  }
1280  if (k != 0)
1281    ThrowImportException(OptionError,"UnbalancedParenthesis",argv[i]);
1282  if (i-- != (ssize_t) argc)
1283    ThrowImportException(OptionError,"MissingAnImageFilename",argv[i]);
1284  if (image == (Image *) NULL)
1285    ThrowImportException(OptionError,"MissingAnImageFilename",argv[argc-1]);
1286  FinalizeImageSettings(image_info,image,MagickTrue);
1287  status&=WriteImages(image_info,image,filename,exception);
1288  DestroyImport();
1289  return(status != 0 ? MagickTrue : MagickFalse);
1290#else
1291  (void) argc;
1292  (void) argv;
1293  (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
1294    "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image_info->filename);
1295  return(ImportUsage());
1296#endif
1297}
1298