1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %           IIIII  DDDD   EEEEE  N   N  TTTTT  IIIII  FFFFF  Y   Y            %
7 %             I    D   D  E      NN  N    T      I    F       Y Y             %
8 %             I    D   D  EEE    N N N    T      I    FFF      Y              %
9 %             I    D   D  E      N  NN    T      I    F        Y              %
10 %           IIIII  DDDD   EEEEE  N   N    T    IIIII  F        Y              %
11 %                                                                             %
12 %                                                                             %
13 %               Identify an Image Format and Characteristics.                 %
14 %                                                                             %
15 %                           Software Design                                   %
16 %                                Cristy                                       %
17 %                            September 1994                                   %
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 %  The identify program describes the format and characteristics of one or more
37 %  image files. It also reports if an image is incomplete or corrupt. The
38 %  information returned includes the image number, the file name, the width and
39 %  height of the image, whether the image is colormapped or not, the number of
40 %  colors in the image, the number of bytes in the image, the format of the
41 %  image (JPEG, PNM, etc.), and finally the number of seconds it took to read
42 %  and process the image. Many more attributes are available with the verbose
43 %  option.
44 %
45 */
46 
47 /*
48   Include declarations.
49 */
50 #include "MagickWand/studio.h"
51 #include "MagickWand/MagickWand.h"
52 #include "MagickWand/mogrify-private.h"
53 #include "MagickCore/string-private.h"
54 
55 /*
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 %                                                                             %
58 %                                                                             %
59 %                                                                             %
60 +   I d e n t i f y I m a g e C o m m a n d                                   %
61 %                                                                             %
62 %                                                                             %
63 %                                                                             %
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65 %
66 %  IdentifyImageCommand() describes the format and characteristics of one or
67 %  more image files. It will also report if an image is incomplete or corrupt.
68 %  The information displayed includes the scene number, the file name, the
69 %  width and height of the image, whether the image is colormapped or not,
70 %  the number of colors in the image, the number of bytes in the image, the
71 %  format of the image (JPEG, PNM, etc.), and finally the number of seconds
72 %  it took to read and process the image.
73 %
74 %  The format of the IdentifyImageCommand method is:
75 %
76 %      MagickBooleanType IdentifyImageCommand(ImageInfo *image_info,int argc,
77 %        char **argv,char **metadata,ExceptionInfo *exception)
78 %
79 %  A description of each parameter follows:
80 %
81 %    o image_info: the image info.
82 %
83 %    o argc: the number of elements in the argument vector.
84 %
85 %    o argv: A text array containing the command line arguments.
86 %
87 %    o metadata: any metadata is returned here.
88 %
89 %    o exception: return any errors or warnings in this structure.
90 %
91 */
92 
IdentifyUsage(void)93 static MagickBooleanType IdentifyUsage(void)
94 {
95   static const char
96     miscellaneous[] =
97       "  -debug events        display copious debugging information\n"
98       "  -help                print program options\n"
99       "  -list type           print a list of supported option arguments\n"
100       "  -log format          format of debugging information\n"
101       "  -version             print version information",
102     operators[] =
103       "  -channel mask        set the image channel mask\n"
104       "  -grayscale method    convert image to grayscale\n"
105       "  -negate              replace every pixel with its complementary color",
106     settings[] =
107       "  -alpha option        on, activate, off, deactivate, set, opaque, copy\n"
108       "                       transparent, extract, background, or shape\n"
109       "  -antialias           remove pixel-aliasing\n"
110       "  -authenticate password\n"
111       "                       decipher image with this password\n"
112       "  -clip                clip along the first path from the 8BIM profile\n"
113       "  -clip-mask filename  associate a clip mask with the image\n"
114       "  -clip-path id        clip along a named path from the 8BIM profile\n"
115       "  -colorspace type     alternate image colorspace\n"
116       "  -crop geometry       cut out a rectangular region of the image\n"
117       "  -define format:option\n"
118       "                       define one or more image format options\n"
119       "  -density geometry    horizontal and vertical density of the image\n"
120       "  -depth value         image depth\n"
121       "  -endian type         endianness (MSB or LSB) of the image\n"
122       "  -extract geometry    extract area from image\n"
123       "  -features distance   analyze image features (e.g. contrast, correlation)\n"
124       "  -format \"string\"     output formatted image characteristics\n"
125       "  -fuzz distance       colors within this distance are considered equal\n"
126       "  -gamma value         of gamma correction\n"
127       "  -interlace type      type of image interlacing scheme\n"
128       "  -interpolate method  pixel color interpolation method\n"
129       "  -limit type value    pixel cache resource limit\n"
130       "  -matte               store matte channel if the image has one\n"
131       "  -moments             report image moments\n"
132       "  -monitor             monitor progress\n"
133       "  -ping                efficiently determine image attributes\n"
134       "  -precision value     maximum number of significant digits to print\n"
135       "  -quiet               suppress all warning messages\n"
136       "  -read-mask filename  associate a read mask with the image\n"
137       "  -regard-warnings     pay attention to warning messages\n"
138       "  -respect-parentheses settings remain in effect until parenthesis boundary\n"
139       "  -sampling-factor geometry\n"
140       "                       horizontal and vertical sampling factor\n"
141       "  -seed value          seed a new sequence of pseudo-random numbers\n"
142       "  -set attribute value set an image attribute\n"
143       "  -size geometry       width and height of image\n"
144       "  -strip               strip image of all profiles and comments\n"
145       "  -unique              display the number of unique colors in the image\n"
146       "  -units type          the units of image resolution\n"
147       "  -verbose             print detailed information about the image\n"
148       "  -virtual-pixel method\n"
149       "                       virtual pixel access method";
150 
151   ListMagickVersion(stdout);
152   (void) printf("Usage: %s [options ...] file [ [options ...] "
153     "file ... ]\n",GetClientName());
154   (void) printf("\nImage Settings:\n");
155   (void) puts(settings);
156   (void) printf("\nImage Operators:\n");
157   (void) puts(operators);
158   (void) printf("\nMiscellaneous Options:\n");
159   (void) puts(miscellaneous);
160   (void) printf(
161     "\nBy default, the image format of 'file' is determined by its magic\n");
162   (void) printf(
163     "number.  To specify a particular image format, precede the filename\n");
164   (void) printf(
165     "with an image format name and a colon (i.e. ps:image) or specify the\n");
166   (void) printf(
167     "image type as the filename suffix (i.e. image.ps).  Specify 'file' as\n");
168   (void) printf("'-' for standard input or output.\n");
169   return(MagickTrue);
170 }
171 
IdentifyImageCommand(ImageInfo * image_info,int argc,char ** argv,char ** metadata,ExceptionInfo * exception)172 WandExport MagickBooleanType IdentifyImageCommand(ImageInfo *image_info,
173   int argc,char **argv,char **metadata,ExceptionInfo *exception)
174 {
175 #define DestroyIdentify() \
176 { \
177   DestroyImageStack(); \
178   for (i=0; i < (ssize_t) argc; i++) \
179     argv[i]=DestroyString(argv[i]); \
180   argv=(char **) RelinquishMagickMemory(argv); \
181 }
182 #define ThrowIdentifyException(asperity,tag,option) \
183 { \
184   (void) ThrowMagickException(exception,GetMagickModule(),asperity,tag,"`%s'", \
185     option); \
186   DestroyIdentify(); \
187   return(MagickFalse); \
188 }
189 #define ThrowIdentifyInvalidArgumentException(option,argument) \
190 { \
191   (void) ThrowMagickException(exception,GetMagickModule(),OptionError, \
192     "InvalidArgument","'%s': %s",option,argument); \
193   DestroyIdentify(); \
194   return(MagickFalse); \
195 }
196 
197   const char
198     *format,
199     *option;
200 
201   Image
202     *image;
203 
204   ImageStack
205     image_stack[MaxImageStackDepth+1];
206 
207   MagickBooleanType
208     fire,
209     pend,
210     respect_parenthesis;
211 
212   MagickStatusType
213     status;
214 
215   ssize_t
216     i;
217 
218   size_t
219     count;
220 
221   ssize_t
222     j,
223     k;
224 
225   /*
226     Set defaults.
227   */
228   assert(image_info != (ImageInfo *) NULL);
229   assert(image_info->signature == MagickCoreSignature);
230   if (image_info->debug != MagickFalse)
231     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
232   assert(exception != (ExceptionInfo *) NULL);
233   if (argc == 2)
234     {
235       option=argv[1];
236       if ((LocaleCompare("version",option+1) == 0) ||
237           (LocaleCompare("-version",option+1) == 0))
238         {
239           ListMagickVersion(stdout);
240           return(MagickTrue);
241         }
242     }
243   if (argc < 2)
244     return(IdentifyUsage());
245   count=0;
246   format=NULL;
247   j=1;
248   k=0;
249   NewImageStack();
250   option=(char *) NULL;
251   pend=MagickFalse;
252   respect_parenthesis=MagickFalse;
253   status=MagickTrue;
254   /*
255     Identify an image.
256   */
257   ReadCommandlLine(argc,&argv);
258   status=ExpandFilenames(&argc,&argv);
259   if (status == MagickFalse)
260     ThrowIdentifyException(ResourceLimitError,"MemoryAllocationFailed",
261       GetExceptionMessage(errno));
262   image_info->ping=MagickTrue;
263   for (i=1; i < (ssize_t) argc; i++)
264   {
265     option=argv[i];
266     if (LocaleCompare(option,"(") == 0)
267       {
268         FireImageStack(MagickFalse,MagickTrue,pend);
269         if (k == MaxImageStackDepth)
270           ThrowIdentifyException(OptionError,"ParenthesisNestedTooDeeply",
271             option);
272         PushImageStack();
273         continue;
274       }
275     if (LocaleCompare(option,")") == 0)
276       {
277         FireImageStack(MagickFalse,MagickTrue,MagickTrue);
278         if (k == 0)
279           ThrowIdentifyException(OptionError,"UnableToParseExpression",option);
280         PopImageStack();
281         continue;
282       }
283     if (IsCommandOption(option) == MagickFalse)
284       {
285         char
286           *filename;
287 
288         Image
289           *images;
290 
291         ImageInfo
292           *identify_info;
293 
294         /*
295           Read input image.
296         */
297         FireImageStack(MagickFalse,MagickFalse,pend);
298         identify_info=CloneImageInfo(image_info);
299         identify_info->verbose=MagickFalse;
300         filename=argv[i];
301         if ((LocaleCompare(filename,"--") == 0) && (i < (ssize_t) (argc-1)))
302           filename=argv[++i];
303         if (identify_info->ping != MagickFalse)
304           images=PingImages(identify_info,filename,exception);
305         else
306           images=ReadImages(identify_info,filename,exception);
307         identify_info=DestroyImageInfo(identify_info);
308         status&=(images != (Image *) NULL) &&
309           (exception->severity < ErrorException);
310         if (images == (Image *) NULL)
311           continue;
312         AppendImageStack(images);
313         FinalizeImageSettings(image_info,image,MagickFalse);
314         count=0;
315         for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
316         {
317           if (image->scene == 0)
318             image->scene=count++;
319           if (format == (char *) NULL)
320             {
321               (void) IdentifyImage(image,stdout,image_info->verbose,exception);
322               continue;
323             }
324           if (metadata != (char **) NULL)
325             {
326               char
327                 *text;
328 
329               text=InterpretImageProperties(image_info,image,format,exception);
330               if (text == (char *) NULL)
331                 ThrowIdentifyException(ResourceLimitError,
332                   "MemoryAllocationFailed",GetExceptionMessage(errno));
333               (void) ConcatenateString(&(*metadata),text);
334               text=DestroyString(text);
335             }
336         }
337         RemoveAllImageStack();
338         continue;
339       }
340     pend=image != (Image *) NULL ? MagickTrue : MagickFalse;
341     image_info->ping=MagickFalse;
342     switch (*(option+1))
343     {
344       case 'a':
345       {
346         if (LocaleCompare("alpha",option+1) == 0)
347           {
348             ssize_t
349               type;
350 
351             if (*option == '+')
352               break;
353             i++;
354             if (i == (ssize_t) argc)
355               ThrowIdentifyException(OptionError,"MissingArgument",option);
356             type=ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,
357               argv[i]);
358             if (type < 0)
359               ThrowIdentifyException(OptionError,
360                 "UnrecognizedAlphaChannelOption",argv[i]);
361             break;
362           }
363         if (LocaleCompare("antialias",option+1) == 0)
364           break;
365         if (LocaleCompare("authenticate",option+1) == 0)
366           {
367             if (*option == '+')
368               break;
369             i++;
370             if (i == (ssize_t) argc)
371               ThrowIdentifyException(OptionError,"MissingArgument",option);
372             break;
373           }
374         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
375       }
376       case 'c':
377       {
378         if (LocaleCompare("cache",option+1) == 0)
379           {
380             if (*option == '+')
381               break;
382             i++;
383             if (i == (ssize_t) argc)
384               ThrowIdentifyException(OptionError,"MissingArgument",option);
385             if (IsGeometry(argv[i]) == MagickFalse)
386               ThrowIdentifyInvalidArgumentException(option,argv[i]);
387             break;
388           }
389         if (LocaleCompare("channel",option+1) == 0)
390           {
391             ssize_t
392               channel;
393 
394             if (*option == '+')
395               break;
396             i++;
397             if (i == (ssize_t) argc)
398               ThrowIdentifyException(OptionError,"MissingArgument",option);
399             channel=ParseChannelOption(argv[i]);
400             if (channel < 0)
401               ThrowIdentifyException(OptionError,"UnrecognizedChannelType",
402                 argv[i]);
403             break;
404           }
405         if (LocaleCompare("clip",option+1) == 0)
406           break;
407         if (LocaleCompare("clip-mask",option+1) == 0)
408           {
409             if (*option == '+')
410               break;
411             i++;
412             if (i == (ssize_t) argc)
413               ThrowIdentifyException(OptionError,"MissingArgument",option);
414             break;
415           }
416         if (LocaleCompare("clip-path",option+1) == 0)
417           {
418             i++;
419             if (i == (ssize_t) argc)
420               ThrowIdentifyException(OptionError,"MissingArgument",option);
421             break;
422           }
423         if (LocaleCompare("colorspace",option+1) == 0)
424           {
425             ssize_t
426               colorspace;
427 
428             if (*option == '+')
429               break;
430             i++;
431             if (i == (ssize_t) argc)
432               ThrowIdentifyException(OptionError,"MissingArgument",option);
433             colorspace=ParseCommandOption(MagickColorspaceOptions,
434               MagickFalse,argv[i]);
435             if (colorspace < 0)
436               ThrowIdentifyException(OptionError,"UnrecognizedColorspace",
437                 argv[i]);
438             break;
439           }
440         if (LocaleCompare("crop",option+1) == 0)
441           {
442             if (*option == '+')
443               break;
444             i++;
445             if (i == (ssize_t) argc)
446               ThrowIdentifyException(OptionError,"MissingArgument",option);
447             if (IsGeometry(argv[i]) == MagickFalse)
448               ThrowIdentifyInvalidArgumentException(option,argv[i]);
449             break;
450           }
451         if (LocaleCompare("concurrent",option+1) == 0)
452           break;
453         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
454       }
455       case 'd':
456       {
457         if (LocaleCompare("debug",option+1) == 0)
458           {
459             ssize_t
460               event;
461 
462             if (*option == '+')
463               break;
464             i++;
465             if (i == (ssize_t) argc)
466               ThrowIdentifyException(OptionError,"MissingArgument",option);
467             event=ParseCommandOption(MagickLogEventOptions,MagickFalse,argv[i]);
468             if (event < 0)
469               ThrowIdentifyException(OptionError,"UnrecognizedEventType",
470                 argv[i]);
471             (void) SetLogEventMask(argv[i]);
472             break;
473           }
474         if (LocaleCompare("define",option+1) == 0)
475           {
476             i++;
477             if (i == (ssize_t) argc)
478               ThrowIdentifyException(OptionError,"MissingArgument",option);
479             if (*option == '+')
480               {
481                 const char
482                   *define;
483 
484                 define=GetImageOption(image_info,argv[i]);
485                 if (define == (const char *) NULL)
486                   ThrowIdentifyException(OptionError,"NoSuchOption",argv[i]);
487                 break;
488               }
489             break;
490           }
491         if (LocaleCompare("density",option+1) == 0)
492           {
493             if (*option == '+')
494               break;
495             i++;
496             if (i == (ssize_t) argc)
497               ThrowIdentifyException(OptionError,"MissingArgument",option);
498             if (IsGeometry(argv[i]) == MagickFalse)
499               ThrowIdentifyInvalidArgumentException(option,argv[i]);
500             break;
501           }
502         if (LocaleCompare("depth",option+1) == 0)
503           {
504             if (*option == '+')
505               break;
506             i++;
507             if (i == (ssize_t) argc)
508               ThrowIdentifyException(OptionError,"MissingArgument",option);
509             if (IsGeometry(argv[i]) == MagickFalse)
510               ThrowIdentifyInvalidArgumentException(option,argv[i]);
511             break;
512           }
513         if (LocaleCompare("duration",option+1) == 0)
514           {
515             if (*option == '+')
516               break;
517             i++;
518             if (i == (ssize_t) argc)
519               ThrowIdentifyException(OptionError,"MissingArgument",option);
520             if (IsGeometry(argv[i]) == MagickFalse)
521               ThrowIdentifyInvalidArgumentException(option,argv[i]);
522             break;
523           }
524         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
525       }
526       case 'e':
527       {
528         if (LocaleCompare("endian",option+1) == 0)
529           {
530             ssize_t
531               endian;
532 
533             if (*option == '+')
534               break;
535             i++;
536             if (i == (ssize_t) argc)
537               ThrowIdentifyException(OptionError,"MissingArgument",option);
538             endian=ParseCommandOption(MagickEndianOptions,MagickFalse,
539               argv[i]);
540             if (endian < 0)
541               ThrowIdentifyException(OptionError,"UnrecognizedEndianType",
542                 argv[i]);
543             break;
544           }
545         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
546       }
547       case 'f':
548       {
549         if (LocaleCompare("features",option+1) == 0)
550           {
551             if (*option == '+')
552               break;
553             i++;
554             if (i == (ssize_t) argc)
555               ThrowIdentifyException(OptionError,"MissingArgument",option);
556             if (IsGeometry(argv[i]) == MagickFalse)
557               ThrowIdentifyInvalidArgumentException(option,argv[i]);
558             break;
559           }
560         if (LocaleCompare("format",option+1) == 0)
561           {
562             format=(char *) NULL;
563             if (*option == '+')
564               break;
565             i++;
566             if (i == (ssize_t) argc)
567               ThrowIdentifyException(OptionError,"MissingArgument",option);
568             format=argv[i];
569             break;
570           }
571         if (LocaleCompare("fuzz",option+1) == 0)
572           {
573             if (*option == '+')
574               break;
575             i++;
576             if (i == (ssize_t) argc)
577               ThrowIdentifyException(OptionError,"MissingArgument",option);
578             if (IsGeometry(argv[i]) == MagickFalse)
579               ThrowIdentifyInvalidArgumentException(option,argv[i]);
580             break;
581           }
582         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
583       }
584       case 'g':
585       {
586         if (LocaleCompare("gamma",option+1) == 0)
587           {
588             i++;
589             if (i == (ssize_t) argc)
590               ThrowIdentifyException(OptionError,"MissingArgument",option);
591             if (IsGeometry(argv[i]) == MagickFalse)
592               ThrowIdentifyInvalidArgumentException(option,argv[i]);
593             break;
594           }
595         if (LocaleCompare("grayscale",option+1) == 0)
596           {
597             ssize_t
598               method;
599 
600             if (*option == '+')
601               break;
602             i++;
603             if (i == (ssize_t) argc)
604               ThrowIdentifyException(OptionError,"MissingArgument",option);
605             method=ParseCommandOption(MagickPixelIntensityOptions,MagickFalse,
606               argv[i]);
607             if (method < 0)
608               ThrowIdentifyException(OptionError,"UnrecognizedIntensityMethod",
609                 argv[i]);
610             break;
611           }
612         if (LocaleCompare("green-primary",option+1) == 0)
613           {
614             if (*option == '+')
615               break;
616             i++;
617             if (i == (ssize_t) argc)
618               ThrowIdentifyException(OptionError,"MissingArgument",option);
619             if (IsGeometry(argv[i]) == MagickFalse)
620               ThrowIdentifyInvalidArgumentException(option,argv[i]);
621             break;
622           }
623         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
624       }
625       case 'h':
626       {
627         if ((LocaleCompare("help",option+1) == 0) ||
628             (LocaleCompare("-help",option+1) == 0))
629           {
630             DestroyIdentify();
631             return(IdentifyUsage());
632           }
633         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
634       }
635       case 'i':
636       {
637         if (LocaleCompare("interlace",option+1) == 0)
638           {
639             ssize_t
640               interlace;
641 
642             if (*option == '+')
643               break;
644             i++;
645             if (i == (ssize_t) argc)
646               ThrowIdentifyException(OptionError,"MissingArgument",option);
647             interlace=ParseCommandOption(MagickInterlaceOptions,MagickFalse,
648               argv[i]);
649             if (interlace < 0)
650               ThrowIdentifyException(OptionError,"UnrecognizedInterlaceType",
651                 argv[i]);
652             break;
653           }
654         if (LocaleCompare("interpolate",option+1) == 0)
655           {
656             ssize_t
657               interpolate;
658 
659             if (*option == '+')
660               break;
661             i++;
662             if (i == (ssize_t) argc)
663               ThrowIdentifyException(OptionError,"MissingArgument",option);
664             interpolate=ParseCommandOption(MagickInterpolateOptions,MagickFalse,
665               argv[i]);
666             if (interpolate < 0)
667               ThrowIdentifyException(OptionError,
668                 "UnrecognizedInterpolateMethod",argv[i]);
669             break;
670           }
671         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
672       }
673       case 'l':
674       {
675         if (LocaleCompare("limit",option+1) == 0)
676           {
677             char
678               *p;
679 
680             double
681               value;
682 
683             ssize_t
684               resource;
685 
686             if (*option == '+')
687               break;
688             i++;
689             if (i == (ssize_t) argc)
690               ThrowIdentifyException(OptionError,"MissingArgument",option);
691             resource=ParseCommandOption(MagickResourceOptions,MagickFalse,
692               argv[i]);
693             if (resource < 0)
694               ThrowIdentifyException(OptionError,"UnrecognizedResourceType",
695                 argv[i]);
696             i++;
697             if (i == (ssize_t) argc)
698               ThrowIdentifyException(OptionError,"MissingArgument",option);
699             value=StringToDouble(argv[i],&p);
700             (void) value;
701             if ((p == argv[i]) && (LocaleCompare("unlimited",argv[i]) != 0))
702               ThrowIdentifyInvalidArgumentException(option,argv[i]);
703             break;
704           }
705         if (LocaleCompare("list",option+1) == 0)
706           {
707             ssize_t
708               list;
709 
710             if (*option == '+')
711               break;
712             i++;
713             if (i == (ssize_t) argc)
714               ThrowIdentifyException(OptionError,"MissingArgument",option);
715             list=ParseCommandOption(MagickListOptions,MagickFalse,argv[i]);
716             if (list < 0)
717               ThrowIdentifyException(OptionError,"UnrecognizedListType",
718                 argv[i]);
719             status=MogrifyImageInfo(image_info,(int) (i-j+1),(const char **)
720               argv+j,exception);
721             DestroyIdentify();
722             return(status == 0 ? MagickFalse : MagickTrue);
723           }
724         if (LocaleCompare("log",option+1) == 0)
725           {
726             if (*option == '+')
727               break;
728             i++;
729             if ((i == (ssize_t) argc) ||
730                 (strchr(argv[i],'%') == (char *) NULL))
731               ThrowIdentifyException(OptionError,"MissingArgument",option);
732             break;
733           }
734         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
735       }
736       case 'm':
737       {
738         if (LocaleCompare("mask",option+1) == 0)
739           {
740             if (*option == '+')
741               break;
742             i++;
743             if (i == (ssize_t) argc)
744               ThrowIdentifyException(OptionError,"MissingArgument",option);
745             break;
746           }
747         if (LocaleCompare("matte",option+1) == 0)
748           break;
749         if (LocaleCompare("moments",option+1) == 0)
750           break;
751         if (LocaleCompare("monitor",option+1) == 0)
752           break;
753         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
754       }
755       case 'n':
756       {
757         if (LocaleCompare("negate",option+1) == 0)
758           break;
759         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
760       }
761       case 'p':
762       {
763         if (LocaleCompare("ping",option+1) == 0)
764           {
765             image_info->ping=MagickTrue;
766             break;
767           }
768         if (LocaleCompare("precision",option+1) == 0)
769           {
770             if (*option == '+')
771               break;
772             i++;
773             if (i == (ssize_t) argc)
774               ThrowIdentifyException(OptionError,"MissingArgument",option);
775             if (IsGeometry(argv[i]) == MagickFalse)
776               ThrowIdentifyInvalidArgumentException(option,argv[i]);
777             break;
778           }
779         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
780       }
781       case 'q':
782       {
783         if (LocaleCompare("quiet",option+1) == 0)
784           break;
785         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
786       }
787       case 'r':
788       {
789         if (LocaleCompare("regard-warnings",option+1) == 0)
790           break;
791         if (LocaleNCompare("respect-parentheses",option+1,17) == 0)
792           {
793             respect_parenthesis=(*option == '-') ? MagickTrue : MagickFalse;
794             break;
795           }
796         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
797       }
798       case 's':
799       {
800         if (LocaleCompare("sampling-factor",option+1) == 0)
801           {
802             if (*option == '+')
803               break;
804             i++;
805             if (i == (ssize_t) argc)
806               ThrowIdentifyException(OptionError,"MissingArgument",option);
807             if (IsGeometry(argv[i]) == MagickFalse)
808               ThrowIdentifyInvalidArgumentException(option,argv[i]);
809             break;
810           }
811         if (LocaleCompare("seed",option+1) == 0)
812           {
813             if (*option == '+')
814               break;
815             i++;
816             if (i == (ssize_t) argc)
817               ThrowIdentifyException(OptionError,"MissingArgument",option);
818             if (IsGeometry(argv[i]) == MagickFalse)
819               ThrowIdentifyInvalidArgumentException(option,argv[i]);
820             break;
821           }
822         if (LocaleCompare("set",option+1) == 0)
823           {
824             i++;
825             if (i == (ssize_t) argc)
826               ThrowIdentifyException(OptionError,"MissingArgument",option);
827             if (*option == '+')
828               break;
829             i++;
830             if (i == (ssize_t) argc)
831               ThrowIdentifyException(OptionError,"MissingArgument",option);
832             break;
833           }
834         if (LocaleCompare("size",option+1) == 0)
835           {
836             if (*option == '+')
837               break;
838             i++;
839             if (i == (ssize_t) argc)
840               ThrowIdentifyException(OptionError,"MissingArgument",option);
841             if (IsGeometry(argv[i]) == MagickFalse)
842               ThrowIdentifyInvalidArgumentException(option,argv[i]);
843             break;
844           }
845         if (LocaleCompare("strip",option+1) == 0)
846           break;
847         if (LocaleCompare("support",option+1) == 0)
848           {
849             if (*option == '+')
850               break;
851             i++;
852             if (i == (ssize_t) argc)
853               ThrowIdentifyException(OptionError,"MissingArgument",option);
854             if (IsGeometry(argv[i]) == MagickFalse)
855               ThrowIdentifyInvalidArgumentException(option,argv[i]);
856             break;
857           }
858         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
859       }
860       case 'u':
861       {
862         if (LocaleCompare("unique",option+1) == 0)
863           break;
864         if (LocaleCompare("units",option+1) == 0)
865           {
866             ssize_t
867               units;
868 
869             if (*option == '+')
870               break;
871             i++;
872             if (i == (ssize_t) argc)
873               ThrowIdentifyException(OptionError,"MissingArgument",option);
874             units=ParseCommandOption(MagickResolutionOptions,MagickFalse,
875               argv[i]);
876             if (units < 0)
877               ThrowIdentifyException(OptionError,"UnrecognizedUnitsType",
878                 argv[i]);
879             break;
880           }
881         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
882       }
883       case 'v':
884       {
885         if (LocaleCompare("verbose",option+1) == 0)
886           break;
887         if (LocaleCompare("virtual-pixel",option+1) == 0)
888           {
889             ssize_t
890               method;
891 
892             if (*option == '+')
893               break;
894             i++;
895             if (i == (ssize_t) argc)
896               ThrowIdentifyException(OptionError,"MissingArgument",option);
897             method=ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,
898               argv[i]);
899             if (method < 0)
900               ThrowIdentifyException(OptionError,
901                 "UnrecognizedVirtualPixelMethod",argv[i]);
902             break;
903           }
904         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
905       }
906       case '?':
907         break;
908       default:
909         ThrowIdentifyException(OptionError,"UnrecognizedOption",option)
910     }
911     fire=(GetCommandOptionFlags(MagickCommandOptions,MagickFalse,option) &
912       FireOptionFlag) == 0 ?  MagickFalse : MagickTrue;
913     if (fire != MagickFalse)
914       FireImageStack(MagickFalse,MagickTrue,MagickTrue);
915   }
916   if (k != 0)
917     ThrowIdentifyException(OptionError,"UnbalancedParenthesis",argv[i]);
918   if (i != (ssize_t) argc)
919     ThrowIdentifyException(OptionError,"MissingAnImageFilename",argv[i]);
920   DestroyIdentify();
921   return(status != 0 ? MagickTrue : MagickFalse);
922 }
923