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