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