identify.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %           IIIII  DDDD   EEEEE  N   N  TTTTT  IIIII  FFFFF  Y   Y            %
00007 %             I    D   D  E      NN  N    T      I    F       Y Y             %
00008 %             I    D   D  EEE    N N N    T      I    FFF      Y              %
00009 %             I    D   D  E      N  NN    T      I    F        Y              %
00010 %           IIIII  DDDD   EEEEE  N   N    T    IIIII  F        Y              %
00011 %                                                                             %
00012 %                                                                             %
00013 %               Identify an Image Format and Characteristics.                 %
00014 %                                                                             %
00015 %                           Software Design                                   %
00016 %                             John Cristy                                     %
00017 %                            September 1994                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %  Identify describes the format and characteristics of one or more image
00037 %  files.  It will also report if an image is incomplete or corrupt.
00038 %
00039 %
00040 */
00041 
00042 /*
00043   Include declarations.
00044 */
00045 #include "magick/studio.h"
00046 #include "magick/annotate.h"
00047 #include "magick/artifact.h"
00048 #include "magick/blob.h"
00049 #include "magick/cache.h"
00050 #include "magick/client.h"
00051 #include "magick/coder.h"
00052 #include "magick/color.h"
00053 #include "magick/configure.h"
00054 #include "magick/constitute.h"
00055 #include "magick/decorate.h"
00056 #include "magick/delegate.h"
00057 #include "magick/draw.h"
00058 #include "magick/effect.h"
00059 #include "magick/exception.h"
00060 #include "magick/exception-private.h"
00061 #include "magick/gem.h"
00062 #include "magick/geometry.h"
00063 #include "magick/identify.h"
00064 #include "magick/image.h"
00065 #include "magick/image-private.h"
00066 #include "magick/list.h"
00067 #include "magick/locale_.h"
00068 #include "magick/log.h"
00069 #include "magick/magic.h"
00070 #include "magick/magick.h"
00071 #include "magick/memory_.h"
00072 #include "magick/module.h"
00073 #include "magick/monitor.h"
00074 #include "magick/montage.h"
00075 #include "magick/option.h"
00076 #include "magick/pixel-private.h"
00077 #include "magick/prepress.h"
00078 #include "magick/profile.h"
00079 #include "magick/property.h"
00080 #include "magick/quantize.h"
00081 #include "magick/quantum.h"
00082 #include "magick/random_.h"
00083 #include "magick/registry.h"
00084 #include "magick/resize.h"
00085 #include "magick/resource_.h"
00086 #include "magick/signature.h"
00087 #include "magick/statistic.h"
00088 #include "magick/string_.h"
00089 #include "magick/timer.h"
00090 #include "magick/utility.h"
00091 #include "magick/version.h"
00092 #if defined(MAGICKCORE_LCMS_DELEGATE)
00093 #if defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
00094 #include <lcms/lcms.h>
00095 #else
00096 #include "lcms.h"
00097 #endif
00098 #endif
00099 
00100 /*
00101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00102 %                                                                             %
00103 %                                                                             %
00104 %                                                                             %
00105 %   I d e n t i f y I m a g e                                                 %
00106 %                                                                             %
00107 %                                                                             %
00108 %                                                                             %
00109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00110 %
00111 %  IdentifyImage() identifies an image by printing its attributes to the file.
00112 %  Attributes include the image width, height, size, and others.
00113 %
00114 %  The format of the IdentifyImage method is:
00115 %
00116 %      MagickBooleanType IdentifyImage(Image *image,FILE *file,
00117 %        const MagickBooleanType verbose)
00118 %
00119 %  A description of each parameter follows:
00120 %
00121 %    o image: the image.
00122 %
00123 %    o file: the file, typically stdout.
00124 %
00125 %    o verbose: A value other than zero prints more detailed information
00126 %      about the image.
00127 %
00128 */
00129 
00130 MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
00131   const MagickBooleanType verbose)
00132 {
00133 #define IdentifyFormat "    %s:\n      min: " QuantumFormat  \
00134   " (%g)\n      max: " QuantumFormat " (%g)\n"  \
00135   "      mean: %g (%g)\n      standard deviation: %g (%g)\n"
00136 
00137   char
00138     color[MaxTextExtent],
00139     format[MaxTextExtent],
00140     key[MaxTextExtent];
00141 
00142   ColorspaceType
00143     colorspace;
00144 
00145   const char
00146     *artifact,
00147     *name,
00148     *property,
00149     *registry,
00150     *value;
00151 
00152   const MagickInfo
00153     *magick_info;
00154 
00155   const PixelPacket
00156     *pixels;
00157 
00158   double
00159     elapsed_time,
00160     user_time;
00161 
00162   ExceptionInfo
00163     *exception;
00164 
00165   ImageType
00166     type;
00167 
00168   long
00169     y;
00170 
00171   MagickBooleanType
00172     ping;
00173 
00174   register long
00175     i,
00176     x;
00177 
00178   unsigned long
00179     scale;
00180 
00181   assert(image != (Image *) NULL);
00182   assert(image->signature == MagickSignature);
00183   if (image->debug != MagickFalse)
00184     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00185   if (file == (FILE *) NULL)
00186     file=stdout;
00187   *format='\0';
00188   elapsed_time=GetElapsedTime(&image->timer);
00189   user_time=GetUserTime(&image->timer);
00190   GetTimerInfo(&image->timer);
00191   if (verbose == MagickFalse)
00192     {
00193       /*
00194         Display summary info about the image.
00195       */
00196       if (*image->magick_filename != '\0')
00197         if (LocaleCompare(image->magick_filename,image->filename) != 0)
00198           (void) fprintf(file,"%s=>",image->magick_filename);
00199        if ((GetPreviousImageInList(image) == (Image *) NULL) &&
00200            (GetNextImageInList(image) == (Image *) NULL) && (image->scene == 0))
00201         (void) fprintf(file,"%s ",image->filename);
00202       else
00203         (void) fprintf(file,"%s[%lu] ",image->filename,image->scene);
00204       (void) fprintf(file,"%s ",image->magick);
00205       if ((image->magick_columns != 0) || (image->magick_rows != 0))
00206         if ((image->magick_columns != image->columns) ||
00207             (image->magick_rows != image->rows))
00208           (void) fprintf(file,"%lux%lu=>",image->magick_columns,
00209             image->magick_rows);
00210       (void) fprintf(file,"%lux%lu ",image->columns,image->rows);
00211       if ((image->page.width != 0) || (image->page.height != 0) ||
00212           (image->page.x != 0) || (image->page.y != 0))
00213         (void) fprintf(file,"%lux%lu%+ld%+ld ",image->page.width,
00214           image->page.height,image->page.x,image->page.y);
00215       (void) fprintf(file,"%lu-bit ",image->depth);
00216       if (image->type != UndefinedType)
00217         (void) fprintf(file,"%s ",MagickOptionToMnemonic(MagickTypeOptions,
00218           (long) image->type));
00219       if (image->storage_class == DirectClass)
00220         {
00221           (void) fprintf(file,"DirectClass ");
00222           if (image->total_colors != 0)
00223             {
00224               (void) FormatMagickSize(image->total_colors,format);
00225               (void) fprintf(file,"%s ",format);
00226             }
00227         }
00228       else
00229         if (image->total_colors <= image->colors)
00230           (void) fprintf(file,"PseudoClass %luc ",image->colors);
00231         else
00232           (void) fprintf(file,"PseudoClass %lu=>%luc ",image->total_colors,
00233             image->colors);
00234       if (image->error.mean_error_per_pixel != 0.0)
00235         (void) fprintf(file,"%ld/%f/%fdb ",(long)
00236           (image->error.mean_error_per_pixel+0.5),
00237           image->error.normalized_mean_error,
00238           image->error.normalized_maximum_error);
00239       if (GetBlobSize(image) != 0)
00240         {
00241           (void) FormatMagickSize(GetBlobSize(image),format);
00242           (void) fprintf(file,"%s ",format);
00243         }
00244       if (elapsed_time > 0.06)
00245         (void) fprintf(file,"%0.3fu %ld:%02ld",user_time,(long)
00246           (elapsed_time/60.0+0.5),(long) ceil(fmod(elapsed_time,60.0)));
00247       (void) fprintf(file,"\n");
00248       (void) fflush(file);
00249       return(ferror(file) != 0 ? MagickFalse : MagickTrue);
00250     }
00251   /*
00252     Display verbose info about the image.
00253   */
00254   exception=AcquireExceptionInfo();
00255   pixels=GetVirtualPixels(image,0,0,1,1,exception);
00256   exception=DestroyExceptionInfo(exception);
00257   ping=pixels == (const PixelPacket *) NULL ? MagickTrue : MagickFalse;
00258   type=GetImageType(image,&image->exception);
00259   (void) SignatureImage(image);
00260   (void) fprintf(file,"Image: %s\n",image->filename);
00261   if (*image->magick_filename != '\0')
00262     if (LocaleCompare(image->magick_filename,image->filename) != 0)
00263       {
00264         char
00265           filename[MaxTextExtent];
00266 
00267         GetPathComponent(image->magick_filename,TailPath,filename);
00268         (void) fprintf(file,"  Base filename: %s\n",filename);
00269       }
00270   magick_info=GetMagickInfo(image->magick,&image->exception);
00271   if ((magick_info == (const MagickInfo *) NULL) ||
00272       (*GetMagickDescription(magick_info) == '\0'))
00273     (void) fprintf(file,"  Format: %s\n",image->magick);
00274   else
00275     (void) fprintf(file,"  Format: %s (%s)\n",image->magick,
00276       GetMagickDescription(magick_info));
00277   (void) fprintf(file,"  Class: %s\n",MagickOptionToMnemonic(MagickClassOptions,
00278     (long) image->storage_class));
00279   (void) fprintf(file,"  Geometry: %lux%lu%+ld%+ld\n",image->columns,
00280     image->rows,image->tile_offset.x,image->tile_offset.y);
00281   if ((image->magick_columns != 0) || (image->magick_rows != 0))
00282     if ((image->magick_columns != image->columns) ||
00283         (image->magick_rows != image->rows))
00284       (void) fprintf(file,"  Base geometry: %lux%lu\n",image->magick_columns,
00285         image->magick_rows);
00286   if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
00287     {
00288       (void) fprintf(file,"  Resolution: %gx%g\n",image->x_resolution,
00289         image->y_resolution);
00290       (void) fprintf(file,"  Print size: %gx%g\n",(double) image->columns/
00291         image->x_resolution,(double) image->rows/image->y_resolution);
00292     }
00293   (void) fprintf(file,"  Units: %s\n",MagickOptionToMnemonic(
00294     MagickResolutionOptions,(long) image->units));
00295   (void) fprintf(file,"  Type: %s\n",MagickOptionToMnemonic(MagickTypeOptions,
00296     (long) type));
00297   if (image->type != UndefinedType)
00298     (void) fprintf(file,"  Base type: %s\n",MagickOptionToMnemonic(
00299       MagickTypeOptions,(long) image->type));
00300   (void) fprintf(file,"  Endianess: %s\n",MagickOptionToMnemonic(
00301     MagickEndianOptions,(long) image->endian));
00302   /*
00303     Detail channel depth and extrema.
00304   */
00305   (void) fprintf(file,"  Colorspace: %s\n",MagickOptionToMnemonic(
00306     MagickColorspaceOptions,(long) image->colorspace));
00307   if (ping == MagickFalse)
00308     {
00309       ChannelStatistics
00310         *channel_statistics;
00311 
00312       unsigned long
00313         depth;
00314 
00315       depth=GetImageDepth(image,&image->exception);
00316       if (image->depth == depth)
00317         (void) fprintf(file,"  Depth: %lu-bit\n",image->depth);
00318       else
00319         (void) fprintf(file,"  Depth: %lu/%lu-bit\n",image->depth,depth);
00320       channel_statistics=GetImageChannelStatistics(image,&image->exception);
00321       (void) fprintf(file,"  Channel depth:\n");
00322       colorspace=image->colorspace;
00323       if (IsGrayImage(image,&image->exception) != MagickFalse)
00324         colorspace=GRAYColorspace;
00325       switch (colorspace)
00326       {
00327         case RGBColorspace:
00328         default:
00329         {
00330           (void) fprintf(file,"    red: %lu-bit\n",
00331             channel_statistics[RedChannel].depth);
00332           (void) fprintf(file,"    green: %lu-bit\n",
00333             channel_statistics[GreenChannel].depth);
00334           (void) fprintf(file,"    blue: %lu-bit\n",
00335             channel_statistics[BlueChannel].depth);
00336           if (image->matte != MagickFalse)
00337             (void) fprintf(file,"    alpha: %lu-bit\n",
00338               channel_statistics[OpacityChannel].depth);
00339           break;
00340         }
00341         case CMYKColorspace:
00342         {
00343           (void) fprintf(file,"    cyan: %lu-bit\n",
00344             channel_statistics[CyanChannel].depth);
00345           (void) fprintf(file,"    magenta: %lu-bit\n",
00346             channel_statistics[MagentaChannel].depth);
00347           (void) fprintf(file,"    yellow: %lu-bit\n",
00348             channel_statistics[YellowChannel].depth);
00349           (void) fprintf(file,"    black: %lu-bit\n",
00350             channel_statistics[BlackChannel].depth);
00351           if (image->matte != MagickFalse)
00352             (void) fprintf(file,"    alpha: %lu-bit\n",
00353               channel_statistics[OpacityChannel].depth);
00354           break;
00355         }
00356         case GRAYColorspace:
00357         {
00358           (void) fprintf(file,"    gray: %lu-bit\n",
00359             channel_statistics[GrayChannel].depth);
00360           if (image->matte != MagickFalse)
00361             (void) fprintf(file,"    alpha: %lu-bit\n",
00362               channel_statistics[OpacityChannel].depth);
00363           break;
00364         }
00365       }
00366       scale=1;
00367       if (image->depth <= MAGICKCORE_QUANTUM_DEPTH)
00368         scale=QuantumRange/((unsigned long) QuantumRange >> ((unsigned long)
00369           MAGICKCORE_QUANTUM_DEPTH-image->depth));
00370       (void) fprintf(file,"  Channel statistics:\n");
00371       switch (colorspace)
00372       {
00373         case RGBColorspace:
00374         default:
00375         {
00376           (void) fprintf(file,IdentifyFormat,"red",(Quantum)
00377             (channel_statistics[RedChannel].minima/scale),(double)
00378             channel_statistics[RedChannel].minima/(double) QuantumRange,
00379             (Quantum) (channel_statistics[RedChannel].maxima/scale),(double)
00380             channel_statistics[RedChannel].maxima/(double) QuantumRange,
00381             channel_statistics[RedChannel].mean/(double) scale,
00382             channel_statistics[RedChannel].mean/(double) QuantumRange,
00383             channel_statistics[RedChannel].standard_deviation/(double) scale,
00384             channel_statistics[RedChannel].standard_deviation/(double)
00385             QuantumRange);
00386           (void) fprintf(file,IdentifyFormat,"green",(Quantum)
00387             (channel_statistics[GreenChannel].minima/scale),(double)
00388             channel_statistics[GreenChannel].minima/(double) QuantumRange,
00389             (Quantum) (channel_statistics[GreenChannel].maxima/scale),(double)
00390             channel_statistics[GreenChannel].maxima/(double) QuantumRange,
00391             channel_statistics[GreenChannel].mean/(double) scale,
00392             channel_statistics[GreenChannel].mean/(double) QuantumRange,
00393             channel_statistics[GreenChannel].standard_deviation/(double) scale,
00394             channel_statistics[GreenChannel].standard_deviation/(double)
00395             QuantumRange);
00396           (void) fprintf(file,IdentifyFormat,"blue",(Quantum)
00397             (channel_statistics[BlueChannel].minima/scale),(double)
00398             channel_statistics[BlueChannel].minima/(double) QuantumRange,
00399             (Quantum) (channel_statistics[BlueChannel].maxima/scale),(double)
00400             channel_statistics[BlueChannel].maxima/(double) QuantumRange,
00401             channel_statistics[BlueChannel].mean/(double) scale,
00402             channel_statistics[BlueChannel].mean/(double) QuantumRange,
00403             channel_statistics[BlueChannel].standard_deviation/(double) scale,
00404             channel_statistics[BlueChannel].standard_deviation/(double)
00405             QuantumRange);
00406           break;
00407         }
00408         case CMYKColorspace:
00409         {
00410           (void) fprintf(file,IdentifyFormat,"cyan",(Quantum)
00411             (channel_statistics[CyanChannel].minima/scale),(double)
00412             channel_statistics[CyanChannel].minima/(double) QuantumRange,
00413             (Quantum) (channel_statistics[CyanChannel].maxima/scale),(double)
00414             channel_statistics[CyanChannel].maxima/(double) QuantumRange,
00415             channel_statistics[CyanChannel].mean/(double) scale,
00416             channel_statistics[CyanChannel].mean/(double) QuantumRange,
00417             channel_statistics[CyanChannel].standard_deviation/(double) scale,
00418             channel_statistics[CyanChannel].standard_deviation/(double)
00419             QuantumRange);
00420           (void) fprintf(file,IdentifyFormat,"magenta",(Quantum)
00421             (channel_statistics[MagentaChannel].minima/scale),(double)
00422             channel_statistics[MagentaChannel].minima/(double) QuantumRange,
00423             (Quantum) (channel_statistics[MagentaChannel].maxima/scale),(double)
00424             channel_statistics[MagentaChannel].maxima/(double) QuantumRange,
00425             channel_statistics[MagentaChannel].mean/(double) scale,
00426             channel_statistics[MagentaChannel].mean/(double) QuantumRange,
00427             channel_statistics[MagentaChannel].standard_deviation/(double)
00428             scale,channel_statistics[MagentaChannel].standard_deviation/(double)
00429             QuantumRange);
00430           (void) fprintf(file,IdentifyFormat,"yellow",(Quantum)
00431             (channel_statistics[YellowChannel].minima/scale),(double)
00432             channel_statistics[YellowChannel].minima/(double) QuantumRange,
00433             (Quantum) (channel_statistics[YellowChannel].maxima/scale),(double)
00434             channel_statistics[YellowChannel].maxima/(double) QuantumRange,
00435             channel_statistics[YellowChannel].mean/(double) scale,
00436             channel_statistics[YellowChannel].mean/(double) QuantumRange,
00437             channel_statistics[YellowChannel].standard_deviation/(double) scale,
00438             channel_statistics[YellowChannel].standard_deviation/(double)
00439             QuantumRange);
00440           (void) fprintf(file,IdentifyFormat,"black",(Quantum)
00441             (channel_statistics[BlackChannel].minima/scale),(double)
00442             channel_statistics[BlackChannel].minima/(double) QuantumRange,
00443             (Quantum) (channel_statistics[BlackChannel].maxima/scale),(double)
00444             channel_statistics[BlackChannel].maxima/(double) QuantumRange,
00445             channel_statistics[BlackChannel].mean/(double) scale,
00446             channel_statistics[BlackChannel].mean/(double) QuantumRange,
00447             channel_statistics[BlackChannel].standard_deviation/(double) scale,
00448             channel_statistics[BlackChannel].standard_deviation/(double)
00449             QuantumRange);
00450           break;
00451         }
00452         case GRAYColorspace:
00453         {
00454           (void) fprintf(file,IdentifyFormat,"gray",(Quantum)
00455             (channel_statistics[GrayChannel].minima/scale),(double)
00456             channel_statistics[GrayChannel].minima/(double) QuantumRange,
00457             (Quantum) (channel_statistics[GrayChannel].maxima/scale),(double)
00458             channel_statistics[GrayChannel].maxima/(double) QuantumRange,
00459             channel_statistics[GrayChannel].mean/(double) scale,
00460             channel_statistics[GrayChannel].mean/(double) QuantumRange,
00461             channel_statistics[GrayChannel].standard_deviation/(double) scale,
00462             channel_statistics[GrayChannel].standard_deviation/(double)
00463             QuantumRange);
00464           break;
00465         }
00466       }
00467       if (image->matte != MagickFalse)
00468         (void) fprintf(file,IdentifyFormat,"alpha",(Quantum)
00469           ((QuantumRange-channel_statistics[AlphaChannel].maxima)/scale),
00470           (double) (QuantumRange-channel_statistics[AlphaChannel].maxima)/
00471           (double) QuantumRange, (Quantum) ((QuantumRange-
00472           channel_statistics[AlphaChannel].minima)/scale),(double)
00473           (QuantumRange-channel_statistics[AlphaChannel].minima)/(double)
00474           QuantumRange,(QuantumRange-channel_statistics[AlphaChannel].mean)/
00475           (double) scale,(QuantumRange-channel_statistics[AlphaChannel].mean)/
00476           (double) QuantumRange,
00477           channel_statistics[AlphaChannel].standard_deviation/(double) scale,
00478           channel_statistics[AlphaChannel].standard_deviation/(double)
00479           QuantumRange);
00480       channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
00481         channel_statistics);
00482       if (image->colorspace == CMYKColorspace)
00483         (void) fprintf(file,"  Total ink density: %.0f%%\n",100.0*
00484           GetImageTotalInkDensity(image)/(double) QuantumRange);
00485       x=0;
00486       if (image->matte != MagickFalse)
00487         {
00488           register const IndexPacket
00489             *indexes;
00490 
00491           register const PixelPacket
00492             *p;
00493 
00494           p=(PixelPacket *) NULL;
00495           indexes=(IndexPacket *) NULL;
00496           for (y=0; y < (long) image->rows; y++)
00497           {
00498             p=GetVirtualPixels(image,0,y,image->columns,1,exception);
00499             if (p == (const PixelPacket *) NULL)
00500               break;
00501             indexes=GetVirtualIndexQueue(image);
00502             for (x=0; x < (long) image->columns; x++)
00503             {
00504               if (p->opacity == (Quantum) TransparentOpacity)
00505                 break;
00506               p++;
00507             }
00508             if (x < (long) image->columns)
00509               break;
00510           }
00511           if ((x < (long) image->columns) || (y < (long) image->rows))
00512             {
00513               char
00514                 tuple[MaxTextExtent];
00515 
00516               MagickPixelPacket
00517                 pixel;
00518 
00519               GetMagickPixelPacket(image,&pixel);
00520               SetMagickPixelPacket(image,p,indexes+x,&pixel);
00521               (void) QueryMagickColorname(image,&pixel,SVGCompliance,tuple,
00522                 &image->exception);
00523               (void) fprintf(file,"  Alpha: %s ",tuple);
00524               GetColorTuple(&pixel,MagickTrue,tuple);
00525               (void) fprintf(file,"  %s\n",tuple);
00526             }
00527         }
00528       if (ping == MagickFalse)
00529         {
00530           artifact=GetImageArtifact(image,"identify:unique");
00531           if ((artifact != (const char *) NULL) &&
00532               (IsMagickTrue(artifact) != MagickFalse))
00533             (void) fprintf(file,"  Colors: %lu\n",GetNumberColors(image,
00534               (FILE *) NULL,&image->exception));
00535           if (IsHistogramImage(image,&image->exception) != MagickFalse)
00536             {
00537               (void) fprintf(file,"  Histogram:\n");
00538               (void) GetNumberColors(image,file,&image->exception);
00539             }
00540         }
00541     }
00542   if (image->storage_class == PseudoClass)
00543     {
00544       (void) fprintf(file,"  Colormap: %lu\n",image->colors);
00545       if (image->colors <= 1024)
00546         {
00547           char
00548             color[MaxTextExtent],
00549             hex[MaxTextExtent],
00550             tuple[MaxTextExtent];
00551 
00552           MagickPixelPacket
00553             pixel;
00554 
00555           register PixelPacket
00556             *p;
00557 
00558           GetMagickPixelPacket(image,&pixel);
00559           p=image->colormap;
00560           for (i=0; i < (long) image->colors; i++)
00561           {
00562             SetMagickPixelPacket(image,p,(IndexPacket *) NULL,&pixel);
00563             (void) CopyMagickString(tuple,"(",MaxTextExtent);
00564             ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
00565             (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
00566             ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
00567             (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
00568             ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
00569             if (pixel.colorspace == CMYKColorspace)
00570               {
00571                 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
00572                 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,
00573                   tuple);
00574               }
00575             if (pixel.matte != MagickFalse)
00576               {
00577                 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
00578                 ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,
00579                   tuple);
00580               }
00581             (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
00582             (void) QueryMagickColorname(image,&pixel,SVGCompliance,color,
00583               &image->exception);
00584             GetColorTuple(&pixel,MagickTrue,hex);
00585             (void) fprintf(file,"  %8ld: %s %s %s\n",i,tuple,hex,color);
00586             p++;
00587           }
00588         }
00589     }
00590   if (image->error.mean_error_per_pixel != 0.0)
00591     (void) fprintf(file,"  Mean error per pixel: %g\n",
00592       image->error.mean_error_per_pixel);
00593   if (image->error.normalized_mean_error != 0.0)
00594     (void) fprintf(file,"  Normalized mean error: %g\n",
00595       image->error.normalized_mean_error);
00596   if (image->error.normalized_maximum_error != 0.0)
00597     (void) fprintf(file,"  Normalized maximum error: %g\n",
00598       image->error.normalized_maximum_error);
00599   (void) fprintf(file,"  Rendering intent: %s\n",MagickOptionToMnemonic(
00600     MagickIntentOptions,(long) image->rendering_intent));
00601   if (image->gamma != 0.0)
00602     (void) fprintf(file,"  Gamma: %g\n",image->gamma);
00603   if ((image->chromaticity.red_primary.x != 0.0) ||
00604       (image->chromaticity.green_primary.x != 0.0) ||
00605       (image->chromaticity.blue_primary.x != 0.0) ||
00606       (image->chromaticity.white_point.x != 0.0))
00607     {
00608       /*
00609         Display image chromaticity.
00610       */
00611       (void) fprintf(file,"  Chromaticity:\n");
00612       (void) fprintf(file,"    red primary: (%g,%g)\n",
00613         image->chromaticity.red_primary.x,image->chromaticity.red_primary.y);
00614       (void) fprintf(file,"    green primary: (%g,%g)\n",
00615         image->chromaticity.green_primary.x,
00616         image->chromaticity.green_primary.y);
00617       (void) fprintf(file,"    blue primary: (%g,%g)\n",
00618         image->chromaticity.blue_primary.x,image->chromaticity.blue_primary.y);
00619       (void) fprintf(file,"    white point: (%g,%g)\n",
00620         image->chromaticity.white_point.x,image->chromaticity.white_point.y);
00621     }
00622   if ((image->extract_info.width*image->extract_info.height) != 0)
00623     (void) fprintf(file,"  Tile geometry: %lux%lu%+ld%+ld\n",
00624       image->extract_info.width,image->extract_info.height,
00625       image->extract_info.x,image->extract_info.y);
00626   (void) fprintf(file,"  Interlace: %s\n",MagickOptionToMnemonic(
00627     MagickInterlaceOptions,(long) image->interlace));
00628   (void) QueryColorname(image,&image->background_color,SVGCompliance,color,
00629     &image->exception);
00630   (void) fprintf(file,"  Background color: %s\n",color);
00631   (void) QueryColorname(image,&image->border_color,SVGCompliance,color,
00632     &image->exception);
00633   (void) fprintf(file,"  Border color: %s\n",color);
00634   (void) QueryColorname(image,&image->matte_color,SVGCompliance,color,
00635     &image->exception);
00636   (void) fprintf(file,"  Matte color: %s\n",color);
00637   (void) QueryColorname(image,&image->transparent_color,SVGCompliance,color,
00638     &image->exception);
00639   (void) fprintf(file,"  Transparent color: %s\n",color);
00640   if ((image->page.width != 0) || (image->page.height != 0) ||
00641       (image->page.x != 0) || (image->page.y != 0))
00642     (void) fprintf(file,"  Page geometry: %lux%lu%+ld%+ld\n",image->page.width,
00643       image->page.height,image->page.x,image->page.y);
00644   if ((image->page.x != 0) || (image->page.y != 0))
00645     (void) fprintf(file,"  Origin geometry: %+ld%+ld\n",image->page.x,
00646       image->page.y);
00647   (void) fprintf(file,"  Dispose: %s\n",MagickOptionToMnemonic(
00648     MagickDisposeOptions,(long) image->dispose));
00649   if (image->delay != 0)
00650     (void) fprintf(file,"  Delay: %lux%ld\n",image->delay,
00651       image->ticks_per_second);
00652   if (image->iterations != 1)
00653     (void) fprintf(file,"  Iterations: %lu\n",image->iterations);
00654   if ((image->next != (Image *) NULL) || (image->previous != (Image *) NULL))
00655     (void) fprintf(file,"  Scene: %lu of %lu\n",image->scene,
00656       GetImageListLength(image));
00657   else
00658     if (image->scene != 0)
00659       (void) fprintf(file,"  Scene: %lu\n",image->scene);
00660   (void) fprintf(file,"  Compression: %s\n",MagickOptionToMnemonic(
00661     MagickCompressOptions,(long) image->compression));
00662   if (image->quality != UndefinedCompressionQuality)
00663     (void) fprintf(file,"  Quality: %lu\n",image->quality);
00664   (void) fprintf(file,"  Orientation: %s\n",MagickOptionToMnemonic(
00665     MagickOrientationOptions,(long) image->orientation));
00666   if (image->montage != (char *) NULL)
00667     (void) fprintf(file,"  Montage: %s\n",image->montage);
00668   if (image->directory != (char *) NULL)
00669     {
00670       Image
00671         *tile;
00672 
00673       ImageInfo
00674         *image_info;
00675 
00676       register char
00677         *p,
00678         *q;
00679 
00680       WarningHandler
00681         handler;
00682 
00683       /*
00684         Display visual image directory.
00685       */
00686       image_info=AcquireImageInfo();
00687       (void) CloneString(&image_info->size,"64x64");
00688       (void) fprintf(file,"  Directory:\n");
00689       for (p=image->directory; *p != '\0'; p++)
00690       {
00691         q=p;
00692         while ((*q != '\n') && (*q != '\0'))
00693           q++;
00694         (void) CopyMagickString(image_info->filename,p,(size_t) (q-p+1));
00695         p=q;
00696         (void) fprintf(file,"    %s",image_info->filename);
00697         handler=SetWarningHandler((WarningHandler) NULL);
00698         tile=ReadImage(image_info,&image->exception);
00699         (void) SetWarningHandler(handler);
00700         if (tile == (Image *) NULL)
00701           {
00702             (void) fprintf(file,"\n");
00703             continue;
00704           }
00705         (void) fprintf(file," %lux%lu %s\n",tile->magick_columns,
00706           tile->magick_rows,tile->magick);
00707         (void) SignatureImage(tile);
00708         ResetImagePropertyIterator(tile);
00709         property=GetNextImageProperty(tile);
00710         while (property != (const char *) NULL)
00711         {
00712           (void) fprintf(file,"  %s:\n",property);
00713           value=GetImageProperty(tile,property);
00714           if (value != (const char *) NULL)
00715             (void) fprintf(file,"%s\n",value);
00716           property=GetNextImageProperty(tile);
00717         }
00718         tile=DestroyImage(tile);
00719       }
00720       image_info=DestroyImageInfo(image_info);
00721     }
00722   (void) GetImageProperty(image,"exif:*");
00723   ResetImagePropertyIterator(image);
00724   property=GetNextImageProperty(image);
00725   if (property != (const char *) NULL)
00726     {
00727       /*
00728         Display image properties.
00729       */
00730       (void) fprintf(file,"  Properties:\n");
00731       while (property != (const char *) NULL)
00732       {
00733         (void) fprintf(file,"    %c",*property);
00734         if (strlen(property) > 1)
00735           (void) fprintf(file,"%s: ",property+1);
00736         if (strlen(property) > 80)
00737           (void) fputc('\n',file);
00738         value=GetImageProperty(image,property);
00739         if (value != (const char *) NULL)
00740           (void) fprintf(file,"%s\n",value);
00741         property=GetNextImageProperty(image);
00742       }
00743     }
00744   (void) FormatMagickString(key,MaxTextExtent,"8BIM:1999,2998:#1");
00745   value=GetImageProperty(image,key);
00746   if (value != (const char *) NULL)
00747     {
00748       /*
00749         Display clipping path.
00750       */
00751       (void) fprintf(file,"  Clipping path: ");
00752       if (strlen(value) > 80)
00753         (void) fputc('\n',file);
00754       (void) fprintf(file,"%s\n",value);
00755     }
00756   ResetImageProfileIterator(image);
00757   name=GetNextImageProfile(image);
00758   if (name != (char *) NULL)
00759     {
00760       const StringInfo
00761         *profile;
00762 
00763       /*
00764         Identify image profiles.
00765       */
00766       (void) fprintf(file,"  Profiles:\n");
00767       while (name != (char *) NULL)
00768       {
00769         profile=GetImageProfile(image,name);
00770         if (profile == (StringInfo *) NULL)
00771           continue;
00772         (void) fprintf(file,"    Profile-%s: %lu bytes\n",name,(unsigned long)
00773           GetStringInfoLength(profile));
00774 #if defined(MAGICKCORE_LCMS_DELEGATE)
00775         if ((LocaleCompare(name,"icc")