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/attribute.h"
00049 #include "magick/blob.h"
00050 #include "magick/cache.h"
00051 #include "magick/client.h"
00052 #include "magick/coder.h"
00053 #include "magick/color.h"
00054 #include "magick/configure.h"
00055 #include "magick/constitute.h"
00056 #include "magick/decorate.h"
00057 #include "magick/delegate.h"
00058 #include "magick/draw.h"
00059 #include "magick/effect.h"
00060 #include "magick/exception.h"
00061 #include "magick/exception-private.h"
00062 #include "magick/feature.h"
00063 #include "magick/gem.h"
00064 #include "magick/geometry.h"
00065 #include "magick/histogram.h"
00066 #include "magick/identify.h"
00067 #include "magick/image.h"
00068 #include "magick/image-private.h"
00069 #include "magick/list.h"
00070 #include "magick/locale_.h"
00071 #include "magick/log.h"
00072 #include "magick/magic.h"
00073 #include "magick/magick.h"
00074 #include "magick/memory_.h"
00075 #include "magick/module.h"
00076 #include "magick/monitor.h"
00077 #include "magick/montage.h"
00078 #include "magick/option.h"
00079 #include "magick/pixel-private.h"
00080 #include "magick/prepress.h"
00081 #include "magick/profile.h"
00082 #include "magick/property.h"
00083 #include "magick/quantize.h"
00084 #include "magick/quantum.h"
00085 #include "magick/random_.h"
00086 #include "magick/registry.h"
00087 #include "magick/resize.h"
00088 #include "magick/resource_.h"
00089 #include "magick/signature.h"
00090 #include "magick/statistic.h"
00091 #include "magick/string_.h"
00092 #include "magick/string-private.h"
00093 #include "magick/timer.h"
00094 #include "magick/utility.h"
00095 #include "magick/version.h"
00096 #if defined(MAGICKCORE_LCMS_DELEGATE)
00097 #if defined(MAGICKCORE_HAVE_LCMS_LCMS_H)
00098 #include <lcms/lcms.h>
00099 #else
00100 #include "lcms.h"
00101 #endif
00102 #endif
00103 
00104 /*
00105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00106 %                                                                             %
00107 %                                                                             %
00108 %                                                                             %
00109 %   I d e n t i f y I m a g e                                                 %
00110 %                                                                             %
00111 %                                                                             %
00112 %                                                                             %
00113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00114 %
00115 %  IdentifyImage() identifies an image by printing its attributes to the file.
00116 %  Attributes include the image width, height, size, and others.
00117 %
00118 %  The format of the IdentifyImage method is:
00119 %
00120 %      MagickBooleanType IdentifyImage(Image *image,FILE *file,
00121 %        const MagickBooleanType verbose)
00122 %
00123 %  A description of each parameter follows:
00124 %
00125 %    o image: the image.
00126 %
00127 %    o file: the file, typically stdout.
00128 %
00129 %    o verbose: A value other than zero prints more detailed information
00130 %      about the image.
00131 %
00132 */
00133 
00134 static int PrintChannelFeatures(FILE *file,const ChannelType channel,
00135   const char *name,const ChannelFeatures *channel_features)
00136 {
00137 #define PrintFeature(feature) \
00138   GetMagickPrecision(),(feature)[0], \
00139   GetMagickPrecision(),(feature)[1], \
00140   GetMagickPrecision(),(feature)[2], \
00141   GetMagickPrecision(),(feature)[3], \
00142   GetMagickPrecision(),((feature)[0]+(feature)[1]+(feature)[2]+(feature)[3])/4.0 \
00143 
00144 #define FeaturesFormat "    %s:\n" \
00145   "      Angular Second Moment:\n" \
00146   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00147   "      Contrast:\n" \
00148   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00149   "      Correlation:\n" \
00150   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00151   "      Sum of Squares: Variance:\n" \
00152   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00153   "      Inverse Difference Moment:\n" \
00154   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00155   "      Sum Average:\n" \
00156   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00157   "      Sum Variance:\n" \
00158   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00159   "      Sum Entropy:\n" \
00160   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00161   "      Entropy:\n" \
00162   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00163   "      Difference Variance:\n" \
00164   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00165   "      Difference Entropy:\n" \
00166   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00167   "      Information Measure of Correlation 1:\n" \
00168   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00169   "      Information Measure of Correlation 2:\n" \
00170   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" \
00171   "      Maximum Correlation Coefficient:\n" \
00172   "        %.*g, %.*g, %.*g, %.*g, %.*g\n" 
00173 
00174   int
00175     status;
00176 
00177   status=fprintf(file,FeaturesFormat,name,
00178     PrintFeature(channel_features[channel].angular_second_moment),
00179     PrintFeature(channel_features[channel].contrast),
00180     PrintFeature(channel_features[channel].correlation),
00181     PrintFeature(channel_features[channel].variance_sum_of_squares),
00182     PrintFeature(channel_features[channel].inverse_difference_moment),
00183     PrintFeature(channel_features[channel].sum_average),
00184     PrintFeature(channel_features[channel].sum_variance),
00185     PrintFeature(channel_features[channel].sum_entropy),
00186     PrintFeature(channel_features[channel].entropy),
00187     PrintFeature(channel_features[channel].difference_variance),
00188     PrintFeature(channel_features[channel].difference_entropy),
00189     PrintFeature(channel_features[channel].measure_of_correlation_1),
00190     PrintFeature(channel_features[channel].measure_of_correlation_2),
00191     PrintFeature(channel_features[channel].maximum_correlation_coefficient));
00192   return(status);
00193 }
00194 
00195 static int PrintChannelStatistics(FILE *file,const ChannelType channel,
00196   const char *name,const double scale,
00197   const ChannelStatistics *channel_statistics)
00198 {
00199 #define StatisticsFormat "    %s:\n      min: " QuantumFormat  \
00200   " (%g)\n      max: " QuantumFormat " (%g)\n"  \
00201   "      mean: %g (%g)\n      standard deviation: %g (%g)\n"  \
00202   "      kurtosis: %g\n      skewness: %g\n"
00203 
00204   int
00205     status;
00206 
00207   status=fprintf(file,StatisticsFormat,name,(Quantum) (scale*
00208     channel_statistics[channel].minima+0.5),channel_statistics[channel].minima/
00209     (double) QuantumRange,(Quantum) (scale*channel_statistics[channel].maxima+
00210     0.5),channel_statistics[channel].maxima/(double) QuantumRange,scale*
00211     channel_statistics[channel].mean,channel_statistics[channel].mean/
00212     (double) QuantumRange,scale*channel_statistics[channel].standard_deviation,
00213     channel_statistics[channel].standard_deviation/(double) QuantumRange,
00214     channel_statistics[channel].kurtosis,channel_statistics[channel].skewness);
00215   return(status);
00216 }
00217 
00218 MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
00219   const MagickBooleanType verbose)
00220 {
00221   char
00222     color[MaxTextExtent],
00223     format[MaxTextExtent],
00224     key[MaxTextExtent];
00225 
00226   ChannelFeatures
00227     *channel_features;
00228 
00229   ChannelStatistics
00230     *channel_statistics;
00231 
00232   ColorspaceType
00233     colorspace;
00234 
00235   const char
00236     *artifact,
00237     *name,
00238     *property,
00239     *registry,
00240     *value;
00241 
00242   const MagickInfo
00243     *magick_info;
00244 
00245   const PixelPacket
00246     *pixels;
00247 
00248   double
00249     elapsed_time,
00250     user_time;
00251 
00252   ExceptionInfo
00253     *exception;
00254 
00255   ImageType
00256     type;
00257 
00258   long
00259     y;
00260 
00261   MagickBooleanType
00262     ping;
00263 
00264   register long
00265     i,
00266     x;
00267 
00268   unsigned long
00269     distance,
00270     scale;
00271 
00272   assert(image != (Image *) NULL);
00273   assert(image->signature == MagickSignature);
00274   if (image->debug != MagickFalse)
00275     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00276   if (file == (FILE *) NULL)
00277     file=stdout;
00278   *format='\0';
00279   elapsed_time=GetElapsedTime(&image->timer);
00280   user_time=GetUserTime(&image->timer);
00281   GetTimerInfo(&image->timer);
00282   if (verbose == MagickFalse)
00283     {
00284       /*
00285         Display summary info about the image.
00286       */
00287       if (*image->magick_filename != '\0')
00288         if (LocaleCompare(image->magick_filename,image->filename) != 0)
00289           (void) fprintf(file,"%s=>",image->magick_filename);
00290        if ((GetPreviousImageInList(image) == (Image *) NULL) &&
00291            (GetNextImageInList(image) == (Image *) NULL) &&
00292            (image->scene == 0))
00293         (void) fprintf(file,"%s ",image->filename);
00294       else
00295         (void) fprintf(file,"%s[%lu] ",image->filename,image->scene);
00296       (void) fprintf(file,"%s ",image->magick);
00297       if ((image->magick_columns != 0) || (image->magick_rows != 0))
00298         if ((image->magick_columns != image->columns) ||
00299             (image->magick_rows != image->rows))
00300           (void) fprintf(file,"%lux%lu=>",image->magick_columns,
00301             image->magick_rows);
00302       (void) fprintf(file,"%lux%lu ",image->columns,image->rows);
00303       if ((image->page.width != 0) || (image->page.height != 0) ||
00304           (image->page.x != 0) || (image->page.y != 0))
00305         (void) fprintf(file,"%lux%lu%+ld%+ld ",image->page.width,
00306           image->page.height,image->page.x,image->page.y);
00307       (void) fprintf(file,"%lu-bit ",image->depth);
00308       if (image->type != UndefinedType)
00309         (void) fprintf(file,"%s ",MagickOptionToMnemonic(MagickTypeOptions,
00310           (long) image->type));
00311       if (image->storage_class == DirectClass)
00312         {
00313           (void) fprintf(file,"DirectClass ");
00314           if (image->total_colors != 0)
00315             {
00316               (void) FormatMagickSize(image->total_colors,MagickFalse,format);
00317               (void) fprintf(file,"%s ",format);
00318             }
00319         }
00320       else
00321         if (image->total_colors <= image->colors)
00322           (void) fprintf(file,"PseudoClass %luc ",image->colors);
00323         else
00324           (void) fprintf(file,"PseudoClass %lu=>%luc ",image->total_colors,
00325             image->colors);
00326       if (image->error.mean_error_per_pixel != 0.0)
00327         (void) fprintf(file,"%ld/%f/%fdb ",(long)
00328           (image->error.mean_error_per_pixel+0.5),
00329           image->error.normalized_mean_error,
00330           image->error.normalized_maximum_error);
00331       if (GetBlobSize(image) != 0)
00332         {
00333           (void) FormatMagickSize(GetBlobSize(image),MagickFalse,format);
00334           (void) fprintf(file,"%sB ",format);
00335         }
00336       (void) fprintf(file,"%0.3fu %ld:%02ld.%03ld",user_time,(long)
00337         (elapsed_time/60.0),(long) floor(fmod(elapsed_time,60.0)),
00338         (long) (1000.0*(elapsed_time-floor(elapsed_time))));
00339       (void) fprintf(file,"\n");
00340       (void) fflush(file);
00341       return(ferror(file) != 0 ? MagickFalse : MagickTrue);
00342     }
00343   /*
00344     Display verbose info about the image.
00345   */
00346   exception=AcquireExceptionInfo();
00347   pixels=GetVirtualPixels(image,0,0,1,1,exception);
00348   exception=DestroyExceptionInfo(exception);
00349   ping=pixels == (const PixelPacket *) NULL ? MagickTrue : MagickFalse;
00350   type=GetImageType(image,&image->exception);
00351   (void) SignatureImage(image);
00352   (void) fprintf(file,"Image: %s\n",image->filename);
00353   if (*image->magick_filename != '\0')
00354     if (LocaleCompare(image->magick_filename,image->filename) != 0)
00355       {
00356         char
00357           filename[MaxTextExtent];
00358 
00359         GetPathComponent(image->magick_filename,TailPath,filename);
00360         (void) fprintf(file,"  Base filename: %s\n",filename);
00361       }
00362   magick_info=GetMagickInfo(image->magick,&image->exception);
00363   if ((magick_info == (const MagickInfo *) NULL) ||
00364       (*GetMagickDescription(magick_info) == '\0'))
00365     (void) fprintf(file,"  Format: %s\n",image->magick);
00366   else
00367     (void) fprintf(file,"  Format: %s (%s)\n",image->magick,
00368       GetMagickDescription(magick_info));
00369   (void) fprintf(file,"  Class: %s\n",MagickOptionToMnemonic(MagickClassOptions,
00370     (long) image->storage_class));
00371   (void) fprintf(file,"  Geometry: %lux%lu%+ld%+ld\n",image->columns,
00372     image->rows,image->tile_offset.x,image->tile_offset.y);
00373   if ((image->magick_columns != 0) || (image->magick_rows != 0))
00374     if ((image->magick_columns != image->columns) ||
00375         (image->magick_rows != image->rows))
00376       (void) fprintf(file,"  Base geometry: %lux%lu\n",image->magick_columns,
00377         image->magick_rows);
00378   if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
00379     {
00380       (void) fprintf(file,"  Resolution: %gx%g\n",image->x_resolution,
00381         image->y_resolution);
00382       (void) fprintf(file,"  Print size: %gx%g\n",(double) image->columns/
00383         image->x_resolution,(double) image->rows/image->y_resolution);
00384     }
00385   (void) fprintf(file,"  Units: %s\n",MagickOptionToMnemonic(
00386     MagickResolutionOptions,(long) image->units));
00387   (void) fprintf(file,"  Type: %s\n",MagickOptionToMnemonic(MagickTypeOptions,
00388     (long) type));
00389   if (image->type != UndefinedType)
00390     (void) fprintf(file,"  Base type: %s\n",MagickOptionToMnemonic(
00391       MagickTypeOptions,(long) image->type));
00392   (void) fprintf(file,"  Endianess: %s\n",MagickOptionToMnemonic(
00393     MagickEndianOptions,(long) image->endian));
00394   /*
00395     Detail channel depth and extrema.
00396   */
00397   (void) fprintf(file,"  Colorspace: %s\n",MagickOptionToMnemonic(
00398     MagickColorspaceOptions,(long) image->colorspace));
00399   channel_statistics=(ChannelStatistics *) NULL;
00400   channel_features=(ChannelFeatures *) NULL;
00401   colorspace=image->colorspace;
00402   if (ping == MagickFalse)
00403     {
00404       unsigned long
00405         depth;
00406 
00407       channel_statistics=GetImageChannelStatistics(image,&image->exception);
00408       artifact=GetImageArtifact(image,"identify:features");
00409       if (artifact != (const char *) NULL)
00410         {
00411           distance=StringToUnsignedLong(artifact);
00412           channel_features=GetImageChannelFeatures(image,distance,
00413             &image->exception);
00414         }
00415       depth=GetImageDepth(image,&image->exception);
00416       if (image->depth == depth)
00417         (void) fprintf(file,"  Depth: %lu-bit\n",image->depth);
00418       else
00419         (void) fprintf(file,"  Depth: %lu/%lu-bit\n",image->depth,depth);
00420       (void) fprintf(file,"  Channel depth:\n");
00421       if (IsGrayImage(image,&image->exception) != MagickFalse)
00422         colorspace=GRAYColorspace;
00423       switch (colorspace)
00424       {
00425         case RGBColorspace:
00426         default:
00427         {
00428           (void) fprintf(file,"    red: %lu-bit\n",
00429             channel_statistics[RedChannel].depth);
00430           (void) fprintf(file,"    green: %lu-bit\n",
00431             channel_statistics[GreenChannel].depth);
00432           (void) fprintf(file,"    blue: %lu-bit\n",
00433             channel_statistics[BlueChannel].depth);
00434           if (image->matte != MagickFalse)
00435             (void) fprintf(file,"    alpha: %lu-bit\n",
00436               channel_statistics[OpacityChannel].depth);
00437           break;
00438         }
00439         case CMYKColorspace:
00440         {
00441           (void) fprintf(file,"    cyan: %lu-bit\n",
00442             channel_statistics[CyanChannel].depth);
00443           (void) fprintf(file,"    magenta: %lu-bit\n",
00444             channel_statistics[MagentaChannel].depth);
00445           (void) fprintf(file,"    yellow: %lu-bit\n",
00446             channel_statistics[YellowChannel].depth);
00447           (void) fprintf(file,"    black: %lu-bit\n",
00448             channel_statistics[BlackChannel].depth);
00449           if (image->matte != MagickFalse)
00450             (void) fprintf(file,"    alpha: %lu-bit\n",
00451               channel_statistics[OpacityChannel].depth);
00452           break;
00453         }
00454         case GRAYColorspace:
00455         {
00456           (void) fprintf(file,"    gray: %lu-bit\n",
00457             channel_statistics[GrayChannel].depth);
00458           if (image->matte != MagickFalse)
00459             (void) fprintf(file,"    alpha: %lu-bit\n",
00460               channel_statistics[OpacityChannel].depth);
00461           break;
00462         }
00463       }
00464       scale=1;
00465       if (image->depth <= MAGICKCORE_QUANTUM_DEPTH)
00466         scale=QuantumRange/((unsigned long) QuantumRange >> ((unsigned long)
00467           MAGICKCORE_QUANTUM_DEPTH-image->depth));
00468     }
00469   if (channel_statistics != (ChannelStatistics *) NULL)
00470     {
00471       (void) fprintf(file,"  Channel statistics:\n");
00472       switch (colorspace)
00473       {
00474         case RGBColorspace:
00475         default:
00476         {
00477           (void) PrintChannelStatistics(file,RedChannel,"Red",1.0/scale,
00478             channel_statistics);
00479           (void) PrintChannelStatistics(file,GreenChannel,"Green",1.0/scale,
00480             channel_statistics);
00481           (void) PrintChannelStatistics(file,BlueChannel,"Blue",1.0/scale,
00482             channel_statistics);
00483           break;
00484         }
00485         case CMYKColorspace:
00486         {
00487           (void) PrintChannelStatistics(file,CyanChannel,"Cyan",1.0/scale,
00488             channel_statistics);
00489           (void) PrintChannelStatistics(file,MagentaChannel,"Magenta",1.0/scale,
00490             channel_statistics);
00491           (void) PrintChannelStatistics(file,YellowChannel,"Yellow",1.0/scale,
00492             channel_statistics);
00493           (void) PrintChannelStatistics(file,BlackChannel,"Black",1.0/scale,
00494             channel_statistics);
00495           break;
00496         }
00497         case GRAYColorspace:
00498         {
00499           (void) PrintChannelStatistics(file,GrayChannel,"Gray",1.0/scale,
00500             channel_statistics);
00501           break;
00502         }
00503       }
00504       if (image->matte != MagickFalse)
00505         (void) PrintChannelStatistics(file,AlphaChannel,"Alpha",1.0/scale,
00506           channel_statistics);
00507       if (colorspace != GRAYColorspace)
00508         {
00509           (void) fprintf(file,"  Image statistics:\n");
00510           (void) PrintChannelStatistics(file,AllChannels,"Overall",1.0/scale,
00511             channel_statistics);
00512         }
00513       channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
00514         channel_statistics);
00515     }
00516   if (channel_features != (ChannelFeatures *) NULL)
00517     {
00518       (void) fprintf(file,"  Channel features (horizontal, vertical, left and right diagonals, average):\n");
00519       switch (colorspace)
00520       {
00521         case RGBColorspace:
00522         default:
00523         {
00524           (void) PrintChannelFeatures(file,RedChannel,"Red",channel_features);
00525           (void) PrintChannelFeatures(file,GreenChannel,"Green",
00526             channel_features);
00527           (void) PrintChannelFeatures(file,BlueChannel,"Blue",channel_features);
00528           break;
00529         }
00530         case CMYKColorspace:
00531         {
00532           (void) PrintChannelFeatures(file,CyanChannel,"Cyan",channel_features);
00533           (void) PrintChannelFeatures(file,MagentaChannel,"Magenta",
00534             channel_features);
00535           (void) PrintChannelFeatures(file,YellowChannel,"Yellow",
00536             channel_features);
00537           (void) PrintChannelFeatures(file,BlackChannel,"Black",
00538             channel_features);
00539           break;
00540         }
00541         case GRAYColorspace:
00542         {
00543           (void) PrintChannelFeatures(file,GrayChannel,"Gray",channel_features);
00544           break;
00545         }
00546       }
00547       if (image->matte != MagickFalse)
00548         (void) PrintChannelFeatures(file,AlphaChannel,"Alpha",channel_features);
00549       channel_features=(ChannelFeatures *) RelinquishMagickMemory(
00550         channel_features);
00551     }
00552   if (ping == MagickFalse)
00553     {
00554       if (image->colorspace == CMYKColorspace)
00555         (void) fprintf(file,"  Total ink density: %.0f%%\n",100.0*
00556           GetImageTotalInkDensity(image)/(double) QuantumRange);
00557       x=0;
00558       if (image->matte != MagickFalse)
00559         {
00560           register const IndexPacket
00561             *indexes;
00562 
00563           register const PixelPacket
00564             *p;
00565 
00566           p=(PixelPacket *) NULL;
00567           indexes=(IndexPacket *) NULL;
00568           for (y=0; y < (long) image->rows; y++)
00569           {
00570             p=GetVirtualPixels(image,0,y,image->columns,1,exception);
00571             if (p == (const PixelPacket *) NULL)
00572               break;
00573             indexes=GetVirtualIndexQueue(image);
00574             for (x=0; x < (long) image->columns; x++)
00575             {
00576               if (p->opacity == (Quantum) TransparentOpacity)
00577                 break;
00578               p++;
00579             }
00580             if (x < (long) image->columns)
00581               break;
00582           }
00583           if ((x < (long) image->columns) || (y < (long) image->rows))
00584             {
00585               char
00586                 tuple[MaxTextExtent];
00587 
00588               MagickPixelPacket
00589                 pixel;
00590 
00591               GetMagickPixelPacket(image,&pixel);
00592               SetMagickPixelPacket(image,p,indexes+x,&pixel);
00593               (void) QueryMagickColorname(image,&pixel,SVGCompliance,tuple,
00594                 &image->exception);
00595               (void) fprintf(file,"  Alpha: %s ",tuple);
00596               GetColorTuple(&pixel,MagickTrue,tuple);
00597               (void) fprintf(file,"  %s\n",tuple);
00598             }
00599         }
00600       artifact=GetImageArtifact(image,"identify:unique");
00601       if ((artifact != (const char *) NULL) &&
00602           (IsMagickTrue(artifact) != MagickFalse))
00603         (void) fprintf(file,"  Colors: %lu\n",GetNumberColors(image,
00604           (FILE *) NULL,&image->exception));
00605       if (IsHistogramImage(image,&image->exception) != MagickFalse)
00606         {
00607           (void) fprintf(file,"  Histogram:\n");
00608           (void) GetNumberColors(image,file,&image->exception);
00609         }
00610     }
00611   if (image->storage_class == PseudoClass)
00612     {
00613       (void) fprintf(file,"  Colormap: %lu\n",image->colors);
00614       if (image->colors <= 1024)
00615         {
00616           char
00617             color[MaxTextExtent],
00618             hex[MaxTextExtent],
00619             tuple[MaxTextExtent];
00620 
00621           MagickPixelPacket
00622             pixel;
00623 
00624           register PixelPacket
00625             *restrict p;
00626 
00627           GetMagickPixelPacket(image,&pixel);
00628           p=image->colormap;
00629           for (i=0; i < (long) image->colors; i++)
00630           {
00631             SetMagickPixelPacket(image,p,(IndexPacket *) NULL,&pixel);
00632             (void) CopyMagickString(tuple,"(",MaxTextExtent);
00633             ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
00634             (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
00635             ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
00636             (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
00637             ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
00638             if (pixel.colorspace == CMYKColorspace)
00639               {
00640                 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
00641                 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,
00642                   tuple);
00643               }
00644             if (pixel.matte != MagickFalse)
00645               {
00646                 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
00647                 ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,
00648                   tuple);
00649               }
00650             (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
00651             (void) QueryMagickColorname(image,&pixel,SVGCompliance,color,
00652               &image->exception);
00653             GetColorTuple(&pixel,MagickTrue,hex);
00654             (void) fprintf(file,"  %8ld: %s %s %s\n",i,tuple,hex,color);
00655             p++;
00656           }
00657         }
00658     }
00659   if (image->error.mean_error_per_pixel != 0.0)
00660     (void) fprintf(file,"  Mean error per pixel: %g\n",
00661       image->error.mean_error_per_pixel);
00662   if (image->error.normalized_mean_error != 0.0)
00663     (void) fprintf(file,"  Normalized mean error: %g\n",
00664       image->error.normalized_mean_error);
00665   if (image->error.normalized_maximum_error != 0.0)
00666     (void) fprintf(file,"  Normalized maximum error: %g\n",
00667       image->error.normalized_maximum_error);
00668   (void) fprintf(file,"  Rendering intent: %s\n",MagickOptionToMnemonic(
00669     MagickIntentOptions,(long) image->rendering_intent));
00670   if (image->gamma != 0.0)
00671     (void) fprintf(file,"  Gamma: %g\n",image->gamma);
00672   if ((image->chromaticity.red_primary.x != 0.0) ||
00673       (image->chromaticity.green_primary.x != 0.0) ||
00674       (image->chromaticity.blue_primary.x != 0.0) ||
00675       (image->chromaticity.white_point.x != 0.0))
00676     {
00677       /*
00678         Display image chromaticity.
00679       */
00680       (void) fprintf(file,"  Chromaticity:\n");
00681       (void) fprintf(file,"    red primary: (%g,%g)\n",
00682         image->chromaticity.red_primary.x,image->chromaticity.red_primary.y);
00683       (void) fprintf(file,"    green primary: (%g,%g)\n",
00684         image->chromaticity.green_primary.x,
00685         image->chromaticity.green_primary.y);
00686       (void) fprintf(file,"    blue primary: (%g,%g)\n",
00687         image->chromaticity.blue_primary.x,image->chromaticity.blue_primary.y);
00688       (void) fprintf(file,"    white point: (%g,%g)\n",
00689         image->chromaticity.white_point.x,image->chromaticity.white_point.y);
00690     }
00691   if ((image->extract_info.width*image->extract_info.height) != 0)
00692     (void) fprintf(file,"  Tile geometry: %lux%lu%+ld%+ld\n",
00693       image->extract_info.width,image->extract_info.height,
00694       image->extract_info.x,image->extract_info.y);
00695   (void) fprintf(file,"  Interlace: %s\n",MagickOptionToMnemonic(
00696     MagickInterlaceOptions,(long) image->interlace));
00697   (void) QueryColorname(image,&image->background_color,SVGCompliance,color,
00698     &image->exception);
00699   (void) fprintf(file,"  Background color: %s\n",color);
00700   (void) QueryColorname(image,&image->border_color,SVGCompliance,color,
00701     &image->exception);
00702   (void) fprintf(file,"  Border color: %s\n",color);
00703   (void) QueryColorname(image,&image->matte_color,SVGCompliance,color,
00704     &image->exception);
00705   (void) fprintf(file,"  Matte color: %s\n",color);
00706   (void) QueryColorname(image,&image->transparent_color,SVGCompliance,color,
00707     &image->exception);
00708   (void) fprintf(file,"  Transparent color: %s\n",color);
00709   (void) fprintf(file,"  Compose: %s\n",MagickOptionToMnemonic(
00710     MagickComposeOptions,(long) image->compose));
00711   if ((image->page.width != 0) || (image->page.height != 0) ||
00712       (image->page.x != 0) || (image->page.y != 0))
00713     (void) fprintf(file,"  Page geometry: %lux%lu%+ld%+ld\n",image->page.width,
00714       image->page.height,image->page.x,image->page.y);
00715   if ((image->page.x != 0) || (image->page.y != 0))
00716     (void) fprintf(file,"  Origin geometry: %+ld%+ld\n",image->page.x,
00717       image->page.y);
00718   (void) fprintf(file,"  Dispose: %s\n",MagickOptionToMnemonic(
00719     MagickDisposeOptions,(long) image->dispose));
00720   if (image->delay != 0)
00721     (void) fprintf(file,"  Delay: %lux%ld\n",image->delay,
00722       image->ticks_per_second);
00723   if (image->iterations != 1)
00724     (void) fprintf(file,"  Iterations: %lu\n",image->iterations);
00725   if ((image->next != (Image *) NULL) || (image->previous != (Image *) NULL))
00726     (void) fprintf(file,"  Scene: %lu of %lu\n",image->scene,
00727       GetImageListLength(image));
00728   else
00729     if (image->scene != 0)
00730       (void) fprintf(file,"  Scene: %lu\n",image->scene);
00731   (void) fprintf(file,"  Compression: %s\n",MagickOptionToMnemonic(
00732     MagickCompressOptions,(long) image->compression));
00733   if (image->quality != UndefinedCompressionQuality)
00734     (void) fprintf(file,"  Quality: %lu\n",image->quality);
00735   (void) fprintf(file,"  Orientation: %s\n",MagickOptionToMnemonic(
00736     MagickOrientationOptions,(long) image->orientation));
00737   if (image->montage != (char *) NULL)
00738     (void) fprintf(file,"  Montage: %s\n",image->montage);
00739   if (image->directory != (char *) NULL)
00740     {
00741       Image
00742         *tile;
00743 
00744       ImageInfo
00745         *image_info;
00746 
00747       register char
00748         *p,
00749         *q;
00750 
00751       WarningHandler
00752         handler;
00753 
00754       /*
00755         Display visual image directory.
00756       */
00757       image_info=AcquireImageInfo();
00758       (void) CloneString(&image_info->size,"64x64");
00759       (void) fprintf(file,"  Directory:\n");
00760       for (p=image->directory; *p != '\0'; p++)
00761       {
00762         q=p;
00763         while ((*q != '\n') && (*q != '\0'))
00764           q++;
00765         (void) CopyMagickString(image_info->filename,p,(size_t) (q-p+1));
00766         p=q;
00767         (void) fprintf(file,"    %s",image_info->filename);
00768         handler=SetWarningHandler((WarningHandler) NULL);
00769         tile=ReadImage(image_info,&image->exception);
00770         (void) SetWarningHandler(handler);
00771         if (tile == (Image *) NULL)
00772           {
00773             (void) fprintf(file,"\n");
00774             continue;
00775           }
00776         (void) fprintf(file," %lux%lu %s\n",tile->magick_columns,
00777           tile->magick_rows,tile->magick);
00778         (void) SignatureImage(tile);
00779         ResetImagePropertyIterator(tile);
00780         property=GetNextImageProperty(tile);
00781         while (property != (const char *) NULL)
00782         {
00783           (void) fprintf(file,"  %s:\n",property);
00784           value=GetImageProperty(tile,property);
00785           if (value != (const char *) NULL)
00786             (void) fprintf(file,"%s\n",value);
00787           property=GetNextImageProperty(tile);
00788         }
00789         tile=DestroyImage(tile);
00790       }
00791       image_info=DestroyImageInfo(image_info);
00792     }
00793   (void) GetImageProperty(image,"exif:*");
00794   ResetImagePropertyIterator(image);
00795   property=GetNextImageProperty(image);
00796   if (property != (const char *) NULL)
00797     {
00798       /*
00799         Display image properties.
00800       */
00801       (void) fprintf(file,"  Properties:\n");
00802       while (property != (const char *) NULL)
00803       {
00804         (void) fprintf(file,"    %c",*property);
00805         if (strlen(property) > 1)
00806           (void) fprintf(file,"%s: ",property+1);
00807         if (strlen(property) > 80)
00808           (void) fputc('\n',file);
00809         value=GetImageProperty(image,property);
00810         if (value != (const char *) NULL)
00811           (void) fprintf(file,"%s\n",value);
00812         property=GetNextImageProperty(image);
00813       }
00814     }
00815   (void) FormatMagickString(key,MaxTextExtent,"8BIM:1999,2998:#1");
00816   value=GetImageProperty(image,key);
00817   if (value != (const char *) NULL)
00818     {
00819       /*
00820         Display clipping path.
00821       */
00822       (void) fprintf(file,"  Clipping path: ");
00823       if (strlen(value) > 80)
00824         (void) fputc('\n',file);
00825       (void) fprintf(file,"%s\n",value);
00826     }
00827   ResetImageProfileIterator(image);
00828   name=GetNextImageProfile(image);
00829   if (name != (char *) NULL)
00830     {
00831       const StringInfo
00832         *profile;
00833 
00834       /*
00835         Identify image profiles.
00836       */
00837       (void) fprintf(file,"  Profiles:\n");
00838       while (name != (char *) NULL)
00839       {
00840         profile=GetImageProfile(image,name);
00841         if (profile == (StringInfo *) NULL)
00842           continue;
00843         (void) fprintf(file,"    Profile-%s: %lu bytes\n",name,(unsigned long)
00844           GetStringInfoLength(profile));
00845 #if defined(MAGICKCORE_LCMS_DELEGATE)
00846         if ((LocaleCompare(name,"icc") == 0) ||
00847             (LocaleCompare(name,"icm") == 0))
00848           {
00849             cmsHPROFILE
00850               icc_profile;
00851 
00852             icc_profile=cmsOpenProfileFromMem(GetStringInfoDatum(profile),
00853               (DWORD) GetStringInfoLength(profile));
00854             if (icc_profile != (cmsHPROFILE *) NULL)
00855               {
00856                 const char
00857                   *name;
00858 
00859                 name=cmsTakeProductName(icc_profile);
00860                 if (name != (const char *) NULL)
00861                   (void) fprintf(file,"      %s\n",name);
00862                 (void) cmsCloseProfile(icc_profile);
00863               }
00864           }
00865 #endif
00866         if (LocaleCompare(name,"iptc") == 0)
00867           {
00868             char
00869               *attribute,
00870               **attribute_list;
00871 
00872             const char
00873               *tag;
00874 
00875             long
00876               dataset,
00877               record,
00878               sentinel;
00879 
00880             register long
00881               j;
00882 
00883             size_t
00884               length,
00885               profile_length;
00886 
00887             profile_length=GetStringInfoLength(profile);
00888             for (i=0; i < (long) profile_length; i+=(long) length)
00889             {
00890               length=1;
00891               sentinel=GetStringInfoDatum(profile)[i++];
00892               if (sentinel != 0x1c)
00893                 continue;
00894               dataset=GetStringInfoDatum(profile)[i++];
00895               record=GetStringInfoDatum(profile)[i++];
00896               switch (record)
00897               {
00898                 case 5: tag="Image Name"; break;
00899                 case 7: tag="Edit Status"; break;
00900                 case 10: tag="Priority"; break;
00901                 case 15: tag="Category"; break;
00902                 case 20: tag="Supplemental Category"; break;
00903                 case 22: tag="Fixture Identifier"; break;
00904                 case 25: tag="Keyword"; break;
00905                 case 30: tag="Release Date"; break;
00906                 case 35: tag="Release Time"; break;
00907                 case 40: tag="Special Instructions"; break;
00908                 case 45: tag="Reference Service"; break;
00909                 case 47: tag="Reference Date"; break;
00910                 case 50: tag="Reference Number"; break;
00911                 case 55: tag="Created Date"; break;
00912                 case 60: tag="Created Time"; break;
00913                 case 65: tag="Originating Program"; break;
00914                 case 70: tag="Program Version"; break;
00915                 case 75: tag="Object Cycle"; break;
00916                 case 80: tag="Byline"; break;
00917                 case 85: tag="Byline Title"; break;
00918                 case 90: tag="City"; break;
00919                 case 95: tag="Province State"; break;
00920                 case 100: tag="Country Code"; break;
00921                 case 101: tag="Country"; break;
00922                 case 103: tag="Original Transmission Reference"; break;
00923                 case 105: tag="Headline"; break;
00924                 case 110: tag="Credit"; break;
00925                 case 115: tag="Src"; break;
00926                 case 116: tag="Copyright String"; break;
00927                 case 120: tag="Caption"; break;
00928                 case 121: tag="Local Caption"; break;
00929                 case 122: tag="Caption Writer"; break;
00930                 case 200: tag="Custom Field 1"; break;
00931                 case 201: tag="Custom Field 2"; break;
00932                 case 202: tag="Custom Field 3"; break;
00933                 case 203: tag="Custom Field 4"; break;
00934                 case 204: tag="Custom Field 5"; break;
00935                 case 205: tag="Custom Field 6"; break;
00936                 case 206: tag="Custom Field 7"; break;
00937                 case 207: tag="Custom Field 8"; break;
00938                 case 208: tag="Custom Field 9"; break;
00939                 case 209: tag="Custom Field 10"; break;
00940                 case 210: tag="Custom Field 11"; break;
00941                 case 211: tag="Custom Field 12"; break;
00942                 case 212: tag="Custom Field 13"; break;
00943                 case 213: tag="Custom Field 14"; break;
00944                 case 214: tag="Custom Field 15"; break;
00945                 case 215: tag="Custom Field 16"; break;
00946                 case 216: tag="Custom Field 17"; break;
00947                 case 217: tag="Custom Field 18"; break;
00948                 case 218: tag="Custom Field 19"; break;
00949                 case 219: tag="Custom Field 20"; break;
00950                 default: tag="unknown"; break;
00951               }
00952               (void) fprintf(file,"      %s[%ld,%ld]: ",tag,dataset,record);
00953               length=(size_t) (GetStringInfoDatum(profile)[i++] << 8);
00954               length|=GetStringInfoDatum(profile)[i++];
00955               attribute=(char *) NULL;
00956               if (~length >= MaxTextExtent)
00957                 attribute=(char *) AcquireQuantumMemory(length+
00958                   MaxTextExtent,sizeof(*attribute));
00959               if (attribute != (char *) NULL)
00960                 {
00961                   (void) CopyMagickString(attribute,(char *)
00962                     GetStringInfoDatum(profile)+i,length+1);
00963                   attribute_list=StringToList(attribute);
00964                   if (attribute_list != (char **) NULL)
00965                     {
00966                       for (j=0; attribute_list[j] != (char *) NULL; j++)
00967                       {
00968                         (void) fputs(attribute_list[j],file);
00969                         (void) fputs("\n",file);
00970                         attribute_list[j]=(char *) RelinquishMagickMemory(
00971                           attribute_list[j]);
00972                       }
00973                       attribute_list=(char **) RelinquishMagickMemory(
00974                         attribute_list);
00975                     }
00976                   attribute=DestroyString(attribute);
00977                 }
00978             }
00979           }
00980         if (image->debug != MagickFalse)
00981           PrintStringInfo(file,name,profile);
00982         name=GetNextImageProfile(image);
00983       }
00984     }
00985   ResetImageArtifactIterator(image);
00986   artifact=GetNextImageArtifact(image);
00987   if (artifact != (const char *) NULL)
00988     {
00989       /*
00990         Display image artifacts.
00991       */
00992       (void) fprintf(file,"  Artifacts:\n");
00993       while (artifact != (const char *) NULL)
00994       {
00995         (void) fprintf(file,"    %c",*artifact);
00996         if (strlen(artifact) > 1)
00997           (void) fprintf(file,"%s: ",artifact+1);
00998         if (strlen(artifact) > 80)
00999           (void) fputc('\n',file);
01000         value=GetImageArtifact(image,artifact);
01001         if (value != (const char *) NULL)
01002           (void) fprintf(file,"%s\n",value);
01003         artifact=GetNextImageArtifact(image);
01004       }
01005     }
01006   ResetImageRegistryIterator();
01007   registry=GetNextImageRegistry();
01008   if (registry != (const char *) NULL)
01009     {
01010       /*
01011         Display image registry.
01012       */
01013       (void) fprintf(file,"  Registry:\n");
01014       while (registry != (const char *) NULL)
01015       {
01016         (void) fprintf(file,"    %c",*registry);
01017         if (strlen(registry) > 1)
01018           (void) fprintf(file,"%s: ",registry+1);
01019         if (strlen(registry) > 80)
01020           (void) fputc('\n',file);
01021         value=(const char *) GetImageRegistry(StringRegistryType,registry,
01022           &image->exception);
01023         if (value != (const char *) NULL)
01024           (void) fprintf(file,"%s\n",value);
01025         registry=GetNextImageRegistry();
01026       }
01027     }
01028   (void) fprintf(file,"  Tainted: %s\n",MagickOptionToMnemonic(
01029     MagickBooleanOptions,(long) image->taint));
01030   (void) FormatMagickSize(GetBlobSize(image),MagickFalse,format);
01031   (void) fprintf(file,"  Filesize: %sB\n",format);
01032   (void) FormatMagickSize((MagickSizeType) image->columns*image->rows,
01033      MagickFalse,format);
01034   (void) fprintf(file,"  Number pixels: %s\n",format);
01035   (void) FormatMagickSize((MagickSizeType) ((double) image->columns*image->rows/
01036     elapsed_time+0.5),MagickFalse,format);
01037   (void) fprintf(file,"  Pixels per second: %s\n",format);
01038   (void) fprintf(file,"  User time: %0.3fu\n",user_time);
01039   (void) fprintf(file,"  Elapsed time: %ld:%02ld.%03ld\n",(long)
01040     (elapsed_time/60.0),(long) ceil(fmod(elapsed_time,60.0)),(long)
01041     (1000.0*(elapsed_time-floor(elapsed_time))));
01042   (void) fprintf(file,"  Version: %s\n",GetMagickVersion((unsigned long *)
01043     NULL));
01044   (void) fflush(file);
01045   return(ferror(file) != 0 ? MagickFalse : MagickTrue);
01046 }
Generated by  doxygen 1.6.2-20100208