MagickCore  6.9.12-91
Convert, Edit, Or Compose Bitmap Images
 All Data Structures
identify.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % IIIII DDDD EEEEE N N TTTTT IIIII FFFFF Y Y %
7 % I D D E NN N T I F Y Y %
8 % I D D EEE N N N T I FFF Y %
9 % I D D E N NN T I F Y %
10 % IIIII DDDD EEEEE N N T IIIII F Y %
11 % %
12 % %
13 % Identify an Image Format and Characteristics. %
14 % %
15 % Software Design %
16 % Cristy %
17 % September 1994 %
18 % %
19 % %
20 % Copyright 1999 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 % Identify describes the format and characteristics of one or more image
37 % files. It will also report if an image is incomplete or corrupt.
38 %
39 %
40 */
41 
42 
43 /*
44  Include declarations.
45 */
46 #include "magick/studio.h"
47 #include "magick/annotate.h"
48 #include "magick/artifact.h"
49 #include "magick/attribute.h"
50 #include "magick/blob.h"
51 #include "magick/blob-private.h"
52 #include "magick/cache.h"
53 #include "magick/client.h"
54 #include "magick/coder.h"
55 #include "magick/color.h"
56 #include "magick/configure.h"
57 #include "magick/constitute.h"
58 #include "magick/decorate.h"
59 #include "magick/delegate.h"
60 #include "magick/draw.h"
61 #include "magick/effect.h"
62 #include "magick/exception.h"
63 #include "magick/exception-private.h"
64 #include "magick/feature.h"
65 #include "magick/gem.h"
66 #include "magick/geometry.h"
67 #include "magick/histogram.h"
68 #include "magick/identify.h"
69 #include "magick/image.h"
70 #include "magick/image-private.h"
71 #include "magick/list.h"
72 #include "magick/locale_.h"
73 #include "magick/log.h"
74 #include "magick/magic.h"
75 #include "magick/magick.h"
76 #include "magick/memory_.h"
77 #include "magick/module.h"
78 #include "magick/monitor.h"
79 #include "magick/montage.h"
80 #include "magick/option.h"
81 #include "magick/pixel-private.h"
82 #include "magick/prepress.h"
83 #include "magick/profile.h"
84 #include "magick/property.h"
85 #include "magick/quantize.h"
86 #include "magick/quantum.h"
87 #include "magick/random_.h"
88 #include "magick/registry.h"
89 #include "magick/resize.h"
90 #include "magick/resource_.h"
91 #include "magick/signature.h"
92 #include "magick/statistic.h"
93 #include "magick/string_.h"
94 #include "magick/string-private.h"
95 #include "magick/timer.h"
96 #include "magick/token.h"
97 #include "magick/utility.h"
98 #include "magick/version.h"
99 
100 /*
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 % %
103 % %
104 % %
105 % I d e n t i f y I m a g e %
106 % %
107 % %
108 % %
109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 %
111 % IdentifyImage() identifies an image by printing its attributes to the file.
112 % Attributes include the image width, height, size, and others.
113 %
114 % The format of the IdentifyImage method is:
115 %
116 % MagickBooleanType IdentifyImage(Image *image,FILE *file,
117 % const MagickBooleanType verbose)
118 %
119 % A description of each parameter follows:
120 %
121 % o image: the image.
122 %
123 % o file: the file, typically stdout.
124 %
125 % o verbose: A value other than zero prints more detailed information
126 % about the image.
127 %
128 */
129 
130 static ChannelStatistics *GetLocationStatistics(const Image *image,
131  const StatisticType type,ExceptionInfo *exception)
132 {
134  *channel_statistics;
135 
136  ssize_t
137  i;
138 
139  size_t
140  length;
141 
142  ssize_t
143  y;
144 
145  assert(image != (Image *) NULL);
146  assert(image->signature == MagickCoreSignature);
147  if (IsEventLogging() != MagickFalse)
148  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
149  length=CompositeChannels+1UL;
150  channel_statistics=(ChannelStatistics *) AcquireQuantumMemory(length,
151  sizeof(*channel_statistics));
152  if (channel_statistics == (ChannelStatistics *) NULL)
153  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
154  (void) memset(channel_statistics,0,length*
155  sizeof(*channel_statistics));
156  for (i=0; i <= (ssize_t) CompositeChannels; i++)
157  {
158  switch (type)
159  {
160  case MaximumStatistic:
161  default:
162  {
163  channel_statistics[i].maxima=(-MagickMaximumValue);
164  break;
165  }
166  case MinimumStatistic:
167  {
168  channel_statistics[i].minima=MagickMaximumValue;
169  break;
170  }
171  }
172  }
173  for (y=0; y < (ssize_t) image->rows; y++)
174  {
175  const IndexPacket
176  *magick_restrict indexes;
177 
178  const PixelPacket
179  *magick_restrict p;
180 
181  ssize_t
182  x;
183 
184  p=GetVirtualPixels(image,0,y,image->columns,1,exception);
185  if (p == (const PixelPacket *) NULL)
186  break;
187  indexes=GetVirtualIndexQueue(image);
188  for (x=0; x < (ssize_t) image->columns; x++)
189  {
190  switch (type)
191  {
192  case MaximumStatistic:
193  default:
194  {
195  if ((double) GetPixelRed(p) > channel_statistics[RedChannel].maxima)
196  channel_statistics[RedChannel].maxima=(double) GetPixelRed(p);
197  if ((double) GetPixelGreen(p) > channel_statistics[GreenChannel].maxima)
198  channel_statistics[GreenChannel].maxima=(double) GetPixelGreen(p);
199  if ((double) GetPixelBlue(p) > channel_statistics[BlueChannel].maxima)
200  channel_statistics[BlueChannel].maxima=(double) GetPixelBlue(p);
201  if ((image->matte != MagickFalse) &&
202  ((double) GetPixelOpacity(p) > channel_statistics[OpacityChannel].maxima))
203  channel_statistics[OpacityChannel].maxima=(double)
204  GetPixelOpacity(p);
205  if ((image->colorspace == CMYKColorspace) &&
206  ((double) GetPixelIndex(indexes+x) > channel_statistics[BlackChannel].maxima))
207  channel_statistics[BlackChannel].maxima=(double)
208  GetPixelIndex(indexes+x);
209  break;
210  }
211  case MinimumStatistic:
212  {
213  if ((double) GetPixelRed(p) < channel_statistics[RedChannel].minima)
214  channel_statistics[RedChannel].minima=(double) GetPixelRed(p);
215  if ((double) GetPixelGreen(p) < channel_statistics[GreenChannel].minima)
216  channel_statistics[GreenChannel].minima=(double) GetPixelGreen(p);
217  if ((double) GetPixelBlue(p) < channel_statistics[BlueChannel].minima)
218  channel_statistics[BlueChannel].minima=(double) GetPixelBlue(p);
219  if ((image->matte != MagickFalse) &&
220  ((double) GetPixelOpacity(p) < channel_statistics[OpacityChannel].minima))
221  channel_statistics[OpacityChannel].minima=(double)
222  GetPixelOpacity(p);
223  if ((image->colorspace == CMYKColorspace) &&
224  ((double) GetPixelIndex(indexes+x) < channel_statistics[BlackChannel].minima))
225  channel_statistics[BlackChannel].minima=(double)
226  GetPixelIndex(indexes+x);
227  break;
228  }
229  }
230  p++;
231  }
232  }
233  return(channel_statistics);
234 }
235 
236 static ssize_t PrintChannelFeatures(FILE *file,const ChannelType channel,
237  const char *name,const ChannelFeatures *channel_features)
238 {
239 #define PrintFeature(feature) \
240  GetMagickPrecision(),(feature)[0], \
241  GetMagickPrecision(),(feature)[1], \
242  GetMagickPrecision(),(feature)[2], \
243  GetMagickPrecision(),(feature)[3], \
244  GetMagickPrecision(),((feature)[0]+(feature)[1]+(feature)[2]+(feature)[3])/4.0 \
245 
246 #define FeaturesFormat " %s:\n" \
247  " Angular Second Moment:\n" \
248  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
249  " Contrast:\n" \
250  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
251  " Correlation:\n" \
252  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
253  " Sum of Squares Variance:\n" \
254  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
255  " Inverse Difference Moment:\n" \
256  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
257  " Sum Average:\n" \
258  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
259  " Sum Variance:\n" \
260  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
261  " Sum Entropy:\n" \
262  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
263  " Entropy:\n" \
264  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
265  " Difference Variance:\n" \
266  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
267  " Difference Entropy:\n" \
268  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
269  " Information Measure of Correlation 1:\n" \
270  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
271  " Information Measure of Correlation 2:\n" \
272  " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
273  " Maximum Correlation Coefficient:\n" \
274  " %.*g, %.*g, %.*g, %.*g, %.*g\n"
275 
276  ssize_t
277  n;
278 
279  n=FormatLocaleFile(file,FeaturesFormat,name,
280  PrintFeature(channel_features[channel].angular_second_moment),
281  PrintFeature(channel_features[channel].contrast),
282  PrintFeature(channel_features[channel].correlation),
283  PrintFeature(channel_features[channel].variance_sum_of_squares),
284  PrintFeature(channel_features[channel].inverse_difference_moment),
285  PrintFeature(channel_features[channel].sum_average),
286  PrintFeature(channel_features[channel].sum_variance),
287  PrintFeature(channel_features[channel].sum_entropy),
288  PrintFeature(channel_features[channel].entropy),
289  PrintFeature(channel_features[channel].difference_variance),
290  PrintFeature(channel_features[channel].difference_entropy),
291  PrintFeature(channel_features[channel].measure_of_correlation_1),
292  PrintFeature(channel_features[channel].measure_of_correlation_2),
293  PrintFeature(channel_features[channel].maximum_correlation_coefficient));
294  return(n);
295 }
296 
297 static ssize_t PrintChannelLocations(FILE *file,const Image *image,
298  const ChannelType channel,const char *name,const StatisticType type,
299  const size_t max_locations,const ChannelStatistics *channel_statistics)
300 {
301  double
302  target;
303 
305  *exception;
306 
307  ssize_t
308  n,
309  y;
310 
311  switch (type)
312  {
313  case MaximumStatistic:
314  default:
315  {
316  target=channel_statistics[channel].maxima;
317  break;
318  }
319  case MeanStatistic:
320  {
321  target=channel_statistics[channel].mean;
322  break;
323  }
324  case MinimumStatistic:
325  {
326  target=channel_statistics[channel].minima;
327  break;
328  }
329  }
330  (void) FormatLocaleFile(file," %s: %.*g (%.*g)",name,GetMagickPrecision(),
331  target,GetMagickPrecision(),QuantumScale*target);
332  exception=AcquireExceptionInfo();
333  n=0;
334  for (y=0; y < (ssize_t) image->rows; y++)
335  {
336  const PixelPacket
337  *p;
338 
339  ssize_t
340  x;
341 
342  p=GetVirtualPixels(image,0,y,image->columns,1,exception);
343  if (p == (const PixelPacket *) NULL)
344  break;
345  for (x=0; x < (ssize_t) image->columns; x++)
346  {
347  MagickBooleanType
348  match;
349 
350  match=MagickFalse;
351  switch (channel)
352  {
353  case RedChannel:
354  {
355  match=fabs((double) (p->red-target)) < 0.5 ? MagickTrue : MagickFalse;
356  break;
357  }
358  case GreenChannel:
359  {
360  match=fabs((double) (p->green-target)) < 0.5 ? MagickTrue :
361  MagickFalse;
362  break;
363  }
364  case BlueChannel:
365  {
366  match=fabs((double) (p->blue-target)) < 0.5 ? MagickTrue :
367  MagickFalse;
368  break;
369  }
370  case AlphaChannel:
371  {
372  match=fabs((double) (p->opacity-target)) < 0.5 ? MagickTrue :
373  MagickFalse;
374  break;
375  }
376  default:
377  break;
378  }
379  if (match != MagickFalse)
380  {
381  if ((max_locations != 0) && (n >= (ssize_t) max_locations))
382  break;
383  (void) FormatLocaleFile(file," %.20g,%.20g",(double) x,(double) y);
384  n++;
385  }
386  p++;
387  }
388  if (x < (ssize_t) image->columns)
389  break;
390  }
391  (void) FormatLocaleFile(file,"\n");
392  return(n);
393 }
394 
395 static ssize_t PrintChannelMoments(FILE *file,const ChannelType channel,
396  const char *name,const double scale,const ChannelMoments *channel_moments)
397 {
398  double
399  powers[MaximumNumberOfImageMoments] =
400  { 1.0, 2.0, 3.0, 3.0, 6.0, 4.0, 6.0, 4.0 };
401 
402  ssize_t
403  i;
404 
405  ssize_t
406  n;
407 
408  n=FormatLocaleFile(file," %s:\n",name);
409  n+=FormatLocaleFile(file," Centroid: %.*g,%.*g\n",
410  GetMagickPrecision(),channel_moments[channel].centroid.x,
411  GetMagickPrecision(),channel_moments[channel].centroid.y);
412  n+=FormatLocaleFile(file," Ellipse Semi-Major/Minor axis: %.*g,%.*g\n",
413  GetMagickPrecision(),channel_moments[channel].ellipse_axis.x,
414  GetMagickPrecision(),channel_moments[channel].ellipse_axis.y);
415  n+=FormatLocaleFile(file," Ellipse angle: %.*g\n",
416  GetMagickPrecision(),channel_moments[channel].ellipse_angle);
417  n+=FormatLocaleFile(file," Ellipse eccentricity: %.*g\n",
418  GetMagickPrecision(),channel_moments[channel].ellipse_eccentricity);
419  n+=FormatLocaleFile(file," Ellipse intensity: %.*g (%.*g)\n",
420  GetMagickPrecision(),pow(scale,powers[0])*
421  channel_moments[channel].ellipse_intensity,GetMagickPrecision(),
422  channel_moments[channel].ellipse_intensity);
423  for (i=0; i < MaximumNumberOfImageMoments; i++)
424  n+=FormatLocaleFile(file," I%.20g: %.*g (%.*g)\n",i+1.0,
425  GetMagickPrecision(),channel_moments[channel].I[i]/pow(scale,powers[i]),
426  GetMagickPrecision(),channel_moments[channel].I[i]);
427  return(n);
428 }
429 
430 static ssize_t PrintChannelPerceptualHash(FILE *file,const ChannelType channel,
431  const char *name,const ChannelPerceptualHash *channel_phash)
432 {
433  ssize_t
434  i;
435 
436  ssize_t
437  n;
438 
439  n=FormatLocaleFile(file," %s:\n",name);
440  for (i=0; i < MaximumNumberOfPerceptualHashes; i++)
441  n+=FormatLocaleFile(file," PH%.20g: %.*g, %.*g\n",i+1.0,
442  GetMagickPrecision(),channel_phash[channel].P[i],
443  GetMagickPrecision(),channel_phash[channel].Q[i]);
444  return(n);
445 }
446 
447 static ssize_t PrintChannelStatistics(FILE *file,const ChannelType channel,
448  const char *name,const double scale,
449  const ChannelStatistics *channel_statistics)
450 {
451 #define StatisticsFormat " %s:\n min: %.*g (%.*g)\n " \
452  "max: %.*g (%.*g)\n mean: %.*g (%.*g)\n " \
453  "standard deviation: %.*g (%.*g)\n kurtosis: %.*g\n " \
454  "skewness: %.*g\n entropy: %.*g\n"
455 
456  ssize_t
457  n;
458 
459  n=FormatLocaleFile(file,StatisticsFormat,name,GetMagickPrecision(),
460  (double) ClampToQuantum((MagickRealType) (scale*
461  channel_statistics[channel].minima)),GetMagickPrecision(),
462  channel_statistics[channel].minima/(double) QuantumRange,
463  GetMagickPrecision(),(double) ClampToQuantum((MagickRealType) (scale*
464  channel_statistics[channel].maxima)),GetMagickPrecision(),
465  channel_statistics[channel].maxima/(double) QuantumRange,
466  GetMagickPrecision(),scale*channel_statistics[channel].mean,
467  GetMagickPrecision(),channel_statistics[channel].mean/(double) QuantumRange,
468  GetMagickPrecision(),scale*channel_statistics[channel].standard_deviation,
469  GetMagickPrecision(),channel_statistics[channel].standard_deviation/
470  (double) QuantumRange,GetMagickPrecision(),
471  channel_statistics[channel].kurtosis,GetMagickPrecision(),
472  channel_statistics[channel].skewness,GetMagickPrecision(),
473  channel_statistics[channel].entropy);
474  return(n);
475 }
476 
477 MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
478  const MagickBooleanType verbose)
479 {
480  char
481  color[MaxTextExtent],
482  format[MaxTextExtent],
483  key[MaxTextExtent];
484 
486  *channel_features;
487 
489  *channel_moments;
490 
492  *channel_phash;
493 
495  *channel_statistics;
496 
497  ColorspaceType
498  colorspace;
499 
500  const char
501  *artifact,
502  *locate,
503  *name,
504  *property,
505  *registry,
506  *value;
507 
508  const MagickInfo
509  *magick_info;
510 
511  const PixelPacket
512  *pixels;
513 
514  double
515  elapsed_time,
516  scale,
517  user_time;
518 
520  *exception;
521 
522  ImageType
523  type;
524 
525  MagickBooleanType
526  ping;
527 
528  size_t
529  depth,
530  distance;
531 
532  ssize_t
533  i,
534  x,
535  y;
536 
537  struct stat
538  properties;
539 
540  assert(image != (Image *) NULL);
541  assert(image->signature == MagickCoreSignature);
542  if (IsEventLogging() != MagickFalse)
543  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
544  if (file == (FILE *) NULL)
545  file=stdout;
546  exception=AcquireExceptionInfo();
547  colorspace=image->colorspace;
548  locate=GetImageArtifact(image,"identify:locate");
549  if (locate != (const char *) NULL)
550  {
551  const char
552  *limit;
553 
554  size_t
555  max_locations;
556 
557  StatisticType
558  statistic_type;
559 
560  /*
561  Display minimum, maximum, or mean pixel locations.
562  */
563  statistic_type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
564  MagickFalse,locate);
565  limit=GetImageArtifact(image,"identify:limit");
566  max_locations=0;
567  if (limit != (const char *) NULL)
568  max_locations=StringToUnsignedLong(limit);
569  channel_statistics=GetLocationStatistics(image,statistic_type,exception);
570  if (channel_statistics == (ChannelStatistics *) NULL)
571  return(MagickFalse);
572  (void) FormatLocaleFile(file," Channel %s locations:\n",locate);
573  switch (colorspace)
574  {
575  case RGBColorspace:
576  default:
577  {
578  (void) PrintChannelLocations(file,image,RedChannel,"Red",
579  statistic_type,max_locations,channel_statistics);
580  (void) PrintChannelLocations(file,image,GreenChannel,"Green",
581  statistic_type,max_locations,channel_statistics);
582  (void) PrintChannelLocations(file,image,BlueChannel,"Blue",
583  statistic_type,max_locations,channel_statistics);
584  break;
585  }
586  case CMYKColorspace:
587  {
588  (void) PrintChannelLocations(file,image,CyanChannel,"Cyan",
589  statistic_type,max_locations,channel_statistics);
590  (void) PrintChannelLocations(file,image,MagentaChannel,"Magenta",
591  statistic_type,max_locations,channel_statistics);
592  (void) PrintChannelLocations(file,image,YellowChannel,"Yellow",
593  statistic_type,max_locations,channel_statistics);
594  (void) PrintChannelLocations(file,image,BlackChannel,"Black",
595  statistic_type,max_locations,channel_statistics);
596  break;
597  }
598  case LinearGRAYColorspace:
599  case GRAYColorspace:
600  {
601  (void) PrintChannelLocations(file,image,GrayChannel,"Gray",
602  statistic_type,max_locations,channel_statistics);
603  break;
604  }
605  }
606  if (image->matte != MagickFalse)
607  (void) PrintChannelLocations(file,image,AlphaChannel,"Alpha",
608  statistic_type,max_locations,channel_statistics);
609  channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
610  channel_statistics);
611  exception=DestroyExceptionInfo(exception);
612  return(ferror(file) != 0 ? MagickFalse : MagickTrue);
613  }
614  *format='\0';
615  elapsed_time=GetElapsedTime(&image->timer);
616  user_time=GetUserTime(&image->timer);
617  GetTimerInfo(&image->timer);
618  if (verbose == MagickFalse)
619  {
620  /*
621  Display summary info about the image.
622  */
623  if (*image->magick_filename != '\0')
624  if (LocaleCompare(image->magick_filename,image->filename) != 0)
625  (void) FormatLocaleFile(file,"%s=>",image->magick_filename);
626  if ((GetPreviousImageInList(image) == (Image *) NULL) &&
627  (GetNextImageInList(image) == (Image *) NULL) && (image->scene == 0))
628  (void) FormatLocaleFile(file,"%s ",image->filename);
629  else
630  (void) FormatLocaleFile(file,"%s[%.20g] ",image->filename,(double)
631  image->scene);
632  (void) FormatLocaleFile(file,"%s ",image->magick);
633  if ((image->magick_columns != 0) || (image->magick_rows != 0))
634  if ((image->magick_columns != image->columns) ||
635  (image->magick_rows != image->rows))
636  (void) FormatLocaleFile(file,"%.20gx%.20g=>",(double)
637  image->magick_columns,(double) image->magick_rows);
638  (void) FormatLocaleFile(file,"%.20gx%.20g ",(double) image->columns,
639  (double) image->rows);
640  if ((image->page.width != 0) || (image->page.height != 0) ||
641  (image->page.x != 0) || (image->page.y != 0))
642  (void) FormatLocaleFile(file,"%.20gx%.20g%+.20g%+.20g ",(double)
643  image->page.width,(double) image->page.height,(double) image->page.x,
644  (double) image->page.y);
645  (void) FormatLocaleFile(file,"%.20g-bit ",(double) image->depth);
646  if (image->type != UndefinedType)
647  (void) FormatLocaleFile(file,"%s ",CommandOptionToMnemonic(
648  MagickTypeOptions,(ssize_t) image->type));
649  if (colorspace != UndefinedColorspace)
650  (void) FormatLocaleFile(file,"%s ",CommandOptionToMnemonic(
651  MagickColorspaceOptions,(ssize_t) colorspace));
652  if (image->storage_class == DirectClass)
653  {
654  if (image->total_colors != 0)
655  {
656  (void) FormatMagickSize(image->total_colors,MagickFalse,format);
657  (void) FormatLocaleFile(file,"%s ",format);
658  }
659  }
660  else
661  if (image->total_colors <= image->colors)
662  (void) FormatLocaleFile(file,"%.20gc ",(double) image->colors);
663  else
664  (void) FormatLocaleFile(file,"%.20g=>%.20gc ",(double)
665  image->total_colors,(double) image->colors);
666  if (image->error.mean_error_per_pixel != 0.0)
667  (void) FormatLocaleFile(file,"%.20g/%f/%fdb ",(double)
668  (image->error.mean_error_per_pixel+0.5),
669  image->error.normalized_mean_error,
670  image->error.normalized_maximum_error);
671  if (image->extent != 0)
672  {
673  (void) FormatMagickSize(image->extent,MagickTrue,format);
674  (void) FormatLocaleFile(file,"%s ",format);
675  }
676  (void) FormatLocaleFile(file,"%0.3fu %lu:%02lu.%03lu",user_time,
677  (unsigned long) (elapsed_time/60.0),(unsigned long) floor(fmod(
678  elapsed_time,60.0)),(unsigned long) (1000.0*(elapsed_time-
679  floor(elapsed_time))));
680  (void) FormatLocaleFile(file,"\n");
681  (void) fflush(file);
682  exception=DestroyExceptionInfo(exception);
683  return(ferror(file) != 0 ? MagickFalse : MagickTrue);
684  }
685  /*
686  Display verbose info about the image.
687  */
688  pixels=GetVirtualPixels(image,0,0,1,1,exception);
689  exception=DestroyExceptionInfo(exception);
690  ping=pixels == (const PixelPacket *) NULL ? MagickTrue : MagickFalse;
691  exception=(&image->exception);
692  (void) SignatureImage(image);
693  channel_statistics=(ChannelStatistics *) NULL;
694  channel_moments=(ChannelMoments *) NULL;
695  channel_phash=(ChannelPerceptualHash *) NULL;
696  channel_features=(ChannelFeatures *) NULL;
697  depth=0;
698  if (ping == MagickFalse)
699  {
700  depth=GetImageDepth(image,exception);
701  channel_statistics=GetImageChannelStatistics(image,exception);
702  if (channel_statistics == (ChannelStatistics *) NULL)
703  return(MagickFalse);
704  artifact=GetImageArtifact(image,"identify:moments");
705  if (artifact != (const char *) NULL)
706  {
707  channel_moments=GetImageChannelMoments(image,exception);
708  channel_phash=GetImageChannelPerceptualHash(image,exception);
709  }
710  artifact=GetImageArtifact(image,"identify:features");
711  if (artifact != (const char *) NULL)
712  {
713  distance=StringToUnsignedLong(artifact);
714  channel_features=GetImageChannelFeatures(image,distance,exception);
715  }
716  }
717  (void) FormatLocaleFile(file,"Image:\n Filename: %s\n",image->filename);
718  if (*image->magick_filename != '\0')
719  if (LocaleCompare(image->magick_filename,image->filename) != 0)
720  {
721  char
722  filename[MaxTextExtent];
723 
724  GetPathComponent(image->magick_filename,TailPath,filename);
725  (void) FormatLocaleFile(file," Base filename: %s\n",filename);
726  }
727  properties=(*GetBlobProperties(image));
728  if (properties.st_mode != 0)
729  {
730  static const char *rwx[] =
731  { "---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
732  (void) FormatLocaleFile(file," Permissions: %s%s%s\n",
733  rwx[(properties.st_mode >> 6) & 0x07],
734  rwx[(properties.st_mode >> 3) & 0x07],
735  rwx[(properties.st_mode >> 0) & 0x07]);
736  }
737  magick_info=GetMagickInfo(image->magick,exception);
738  if ((magick_info == (const MagickInfo *) NULL) ||
739  (GetMagickDescription(magick_info) == (const char *) NULL))
740  (void) FormatLocaleFile(file," Format: %s\n",image->magick);
741  else
742  (void) FormatLocaleFile(file," Format: %s (%s)\n",image->magick,
743  GetMagickDescription(magick_info));
744  if ((magick_info != (const MagickInfo *) NULL) &&
745  (GetMagickMimeType(magick_info) != (const char *) NULL))
746  (void) FormatLocaleFile(file," Mime type: %s\n",GetMagickMimeType(
747  magick_info));
748  (void) FormatLocaleFile(file," Class: %s\n",CommandOptionToMnemonic(
749  MagickClassOptions,(ssize_t) image->storage_class));
750  (void) FormatLocaleFile(file," Geometry: %.20gx%.20g%+.20g%+.20g\n",(double)
751  image->columns,(double) image->rows,(double) image->tile_offset.x,(double)
752  image->tile_offset.y);
753  if ((image->magick_columns != 0) || (image->magick_rows != 0))
754  if ((image->magick_columns != image->columns) ||
755  (image->magick_rows != image->rows))
756  (void) FormatLocaleFile(file," Base geometry: %.20gx%.20g\n",(double)
757  image->magick_columns,(double) image->magick_rows);
758  if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
759  {
760  (void) FormatLocaleFile(file," Resolution: %gx%g\n",image->x_resolution,
761  image->y_resolution);
762  (void) FormatLocaleFile(file," Print size: %gx%g\n",(double)
763  image->columns/image->x_resolution,(double) image->rows/
764  image->y_resolution);
765  }
766  (void) FormatLocaleFile(file," Units: %s\n",CommandOptionToMnemonic(
767  MagickResolutionOptions,(ssize_t) image->units));
768  (void) FormatLocaleFile(file," Colorspace: %s\n",CommandOptionToMnemonic(
769  MagickColorspaceOptions,(ssize_t) colorspace));
770  type=IdentifyImageType(image,exception);
771  (void) FormatLocaleFile(file," Type: %s\n",CommandOptionToMnemonic(
772  MagickTypeOptions,(ssize_t) type));
773  if (image->type != type)
774  (void) FormatLocaleFile(file," Base type: %s\n",CommandOptionToMnemonic(
775  MagickTypeOptions,(ssize_t) image->type));
776  (void) FormatLocaleFile(file," Endianness: %s\n",CommandOptionToMnemonic(
777  MagickEndianOptions,(ssize_t) image->endian));
778  if (depth != 0)
779  {
780  if (image->depth == depth)
781  (void) FormatLocaleFile(file," Depth: %.20g-bit\n",(double)
782  image->depth);
783  else
784  (void) FormatLocaleFile(file," Depth: %.20g/%.20g-bit\n",(double)
785  image->depth,(double) depth);
786  }
787  if (channel_statistics != (ChannelStatistics *) NULL)
788  {
789  /*
790  Detail channel depth and extrema.
791  */
792  (void) FormatLocaleFile(file," Channel depth:\n");
793  switch (colorspace)
794  {
795  case RGBColorspace:
796  default:
797  {
798  (void) FormatLocaleFile(file," red: %.20g-bit\n",(double)
799  channel_statistics[RedChannel].depth);
800  (void) FormatLocaleFile(file," green: %.20g-bit\n",(double)
801  channel_statistics[GreenChannel].depth);
802  (void) FormatLocaleFile(file," blue: %.20g-bit\n",(double)
803  channel_statistics[BlueChannel].depth);
804  break;
805  }
806  case CMYKColorspace:
807  {
808  (void) FormatLocaleFile(file," cyan: %.20g-bit\n",(double)
809  channel_statistics[CyanChannel].depth);
810  (void) FormatLocaleFile(file," magenta: %.20g-bit\n",(double)
811  channel_statistics[MagentaChannel].depth);
812  (void) FormatLocaleFile(file," yellow: %.20g-bit\n",(double)
813  channel_statistics[YellowChannel].depth);
814  (void) FormatLocaleFile(file," black: %.20g-bit\n",(double)
815  channel_statistics[BlackChannel].depth);
816  break;
817  }
818  case LinearGRAYColorspace:
819  case GRAYColorspace:
820  {
821  (void) FormatLocaleFile(file," gray: %.20g-bit\n",(double)
822  channel_statistics[GrayChannel].depth);
823  break;
824  }
825  }
826  if (image->matte != MagickFalse)
827  (void) FormatLocaleFile(file," alpha: %.20g-bit\n",(double)
828  channel_statistics[OpacityChannel].depth);
829  scale=1.0;
830  if (image->depth <= MAGICKCORE_QUANTUM_DEPTH)
831  scale=(double) QuantumRange/((size_t) QuantumRange >> ((size_t)
832  MAGICKCORE_QUANTUM_DEPTH-image->depth));
833  (void) FormatLocaleFile(file," Channel statistics:\n");
834  (void) FormatLocaleFile(file," Pixels: %.20g\n",(double)
835  image->columns*image->rows);
836  switch (colorspace)
837  {
838  case RGBColorspace:
839  default:
840  {
841  (void) PrintChannelStatistics(file,RedChannel,"Red",1.0/scale,
842  channel_statistics);
843  (void) PrintChannelStatistics(file,GreenChannel,"Green",1.0/scale,
844  channel_statistics);
845  (void) PrintChannelStatistics(file,BlueChannel,"Blue",1.0/scale,
846  channel_statistics);
847  break;
848  }
849  case CMYKColorspace:
850  {
851  (void) PrintChannelStatistics(file,CyanChannel,"Cyan",1.0/scale,
852  channel_statistics);
853  (void) PrintChannelStatistics(file,MagentaChannel,"Magenta",1.0/scale,
854  channel_statistics);
855  (void) PrintChannelStatistics(file,YellowChannel,"Yellow",1.0/scale,
856  channel_statistics);
857  (void) PrintChannelStatistics(file,BlackChannel,"Black",1.0/scale,
858  channel_statistics);
859  break;
860  }
861  case LinearGRAYColorspace:
862  case GRAYColorspace:
863  {
864  (void) PrintChannelStatistics(file,GrayChannel,"Gray",1.0/scale,
865  channel_statistics);
866  break;
867  }
868  }
869  if (image->matte != MagickFalse)
870  (void) PrintChannelStatistics(file,AlphaChannel,"Alpha",1.0/scale,
871  channel_statistics);
872  if ((colorspace != LinearGRAYColorspace) && (colorspace != GRAYColorspace))
873  {
874  (void) FormatLocaleFile(file," Image statistics:\n");
875  (void) PrintChannelStatistics(file,CompositeChannels,"Overall",1.0/
876  scale,channel_statistics);
877  }
878  channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
879  channel_statistics);
880  }
881  if (channel_moments != (ChannelMoments *) NULL)
882  {
883  scale=(double) ((1UL << image->depth)-1);
884  (void) FormatLocaleFile(file," Channel moments:\n");
885  switch (colorspace)
886  {
887  case RGBColorspace:
888  default:
889  {
890  (void) PrintChannelMoments(file,RedChannel,"Red",scale,
891  channel_moments);
892  (void) PrintChannelMoments(file,GreenChannel,"Green",scale,
893  channel_moments);
894  (void) PrintChannelMoments(file,BlueChannel,"Blue",scale,
895  channel_moments);
896  break;
897  }
898  case CMYKColorspace:
899  {
900  (void) PrintChannelMoments(file,CyanChannel,"Cyan",scale,
901  channel_moments);
902  (void) PrintChannelMoments(file,MagentaChannel,"Magenta",scale,
903  channel_moments);
904  (void) PrintChannelMoments(file,YellowChannel,"Yellow",scale,
905  channel_moments);
906  (void) PrintChannelMoments(file,BlackChannel,"Black",scale,
907  channel_moments);
908  break;
909  }
910  case LinearGRAYColorspace:
911  case GRAYColorspace:
912  {
913  (void) PrintChannelMoments(file,GrayChannel,"Gray",scale,
914  channel_moments);
915  break;
916  }
917  }
918  if (image->matte != MagickFalse)
919  (void) PrintChannelMoments(file,AlphaChannel,"Alpha",scale,
920  channel_moments);
921  if ((colorspace != LinearGRAYColorspace) && (colorspace != GRAYColorspace))
922  {
923  (void) FormatLocaleFile(file," Image moments:\n");
924  (void) PrintChannelMoments(file,CompositeChannels,"Overall",scale,
925  channel_moments);
926  }
927  channel_moments=(ChannelMoments *) RelinquishMagickMemory(
928  channel_moments);
929  }
930  if (channel_phash != (ChannelPerceptualHash *) NULL)
931  {
932  (void) FormatLocaleFile(file," Channel perceptual hash:\n");
933  (void) PrintChannelPerceptualHash(file,RedChannel,"Red, Hue",
934  channel_phash);
935  (void) PrintChannelPerceptualHash(file,GreenChannel,"Green, Chroma",
936  channel_phash);
937  (void) PrintChannelPerceptualHash(file,BlueChannel,"Blue, Luma",
938  channel_phash);
939  if (image->matte != MagickFalse)
940  (void) PrintChannelPerceptualHash(file,AlphaChannel,"Alpha, Alpha",
941  channel_phash);
942  channel_phash=(ChannelPerceptualHash *) RelinquishMagickMemory(
943  channel_phash);
944  }
945  if (channel_features != (ChannelFeatures *) NULL)
946  {
947  (void) FormatLocaleFile(file," Channel features (horizontal, vertical, "
948  "left and right diagonals, average):\n");
949  switch (colorspace)
950  {
951  case RGBColorspace:
952  default:
953  {
954  (void) PrintChannelFeatures(file,RedChannel,"Red",channel_features);
955  (void) PrintChannelFeatures(file,GreenChannel,"Green",
956  channel_features);
957  (void) PrintChannelFeatures(file,BlueChannel,"Blue",channel_features);
958  break;
959  }
960  case CMYKColorspace:
961  {
962  (void) PrintChannelFeatures(file,CyanChannel,"Cyan",channel_features);
963  (void) PrintChannelFeatures(file,MagentaChannel,"Magenta",
964  channel_features);
965  (void) PrintChannelFeatures(file,YellowChannel,"Yellow",
966  channel_features);
967  (void) PrintChannelFeatures(file,BlackChannel,"Black",
968  channel_features);
969  break;
970  }
971  case LinearGRAYColorspace:
972  case GRAYColorspace:
973  {
974  (void) PrintChannelFeatures(file,GrayChannel,"Gray",channel_features);
975  break;
976  }
977  }
978  if (image->matte != MagickFalse)
979  (void) PrintChannelFeatures(file,AlphaChannel,"Alpha",channel_features);
980  channel_features=(ChannelFeatures *) RelinquishMagickMemory(
981  channel_features);
982  }
983  if (ping == MagickFalse)
984  {
985  if (colorspace == CMYKColorspace)
986  (void) FormatLocaleFile(file," Total ink density: %.*g%%\n",
987  GetMagickPrecision(),100.0*GetImageTotalInkDensity(image)/(double)
988  QuantumRange);
989  x=0;
990  if (image->matte != MagickFalse)
991  {
992  MagickBooleanType
993  found = MagickFalse;
994 
995  const IndexPacket
996  *indexes;
997 
998  const PixelPacket
999  *p;
1000 
1001  p=(PixelPacket *) NULL;
1002  indexes=(IndexPacket *) NULL;
1003  for (y=0; y < (ssize_t) image->rows; y++)
1004  {
1005  p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1006  if (p == (const PixelPacket *) NULL)
1007  break;
1008  indexes=GetVirtualIndexQueue(image);
1009  for (x=0; x < (ssize_t) image->columns; x++)
1010  {
1011  if (GetPixelOpacity(p) == (Quantum) TransparentOpacity)
1012  {
1013  found=MagickTrue;
1014  break;
1015  }
1016  p++;
1017  }
1018  if (found != MagickFalse)
1019  break;
1020  }
1021  if (found != MagickFalse)
1022  {
1023  char
1024  tuple[MaxTextExtent];
1025 
1027  pixel;
1028 
1029  GetMagickPixelPacket(image,&pixel);
1030  SetMagickPixelPacket(image,p,indexes+x,&pixel);
1031  (void) QueryMagickColorname(image,&pixel,SVGCompliance,tuple,
1032  exception);
1033  (void) FormatLocaleFile(file," Alpha: %s ",tuple);
1034  GetColorTuple(&pixel,MagickTrue,tuple);
1035  (void) FormatLocaleFile(file," %s\n",tuple);
1036  }
1037  }
1038  artifact=GetImageArtifact(image,"identify:unique-colors");
1039  if (IsHistogramImage(image,exception) != MagickFalse)
1040  {
1041  (void) FormatLocaleFile(file," Colors: %.20g\n",(double)
1042  GetNumberColors(image,(FILE *) NULL,exception));
1043  (void) FormatLocaleFile(file," Histogram:\n");
1044  (void) GetNumberColors(image,file,exception);
1045  }
1046  else
1047  if ((artifact != (const char *) NULL) &&
1048  (IsMagickTrue(artifact) != MagickFalse))
1049  (void) FormatLocaleFile(file," Colors: %.20g\n",(double)
1050  GetNumberColors(image,(FILE *) NULL,exception));
1051  }
1052  if (image->storage_class == PseudoClass)
1053  {
1054  (void) FormatLocaleFile(file," Colormap entries: %.20g\n",(double)
1055  image->colors);
1056  (void) FormatLocaleFile(file," Colormap:\n");
1057  if (image->colors <= 1024)
1058  {
1059  char
1060  color[MaxTextExtent],
1061  hex[MaxTextExtent],
1062  tuple[MaxTextExtent];
1063 
1065  pixel;
1066 
1067  PixelPacket
1068  *magick_restrict p;
1069 
1070  GetMagickPixelPacket(image,&pixel);
1071  p=image->colormap;
1072  for (i=0; i < (ssize_t) image->colors; i++)
1073  {
1074  SetMagickPixelPacket(image,p,(IndexPacket *) NULL,&pixel);
1075  (void) CopyMagickString(tuple,"(",MaxTextExtent);
1076  ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
1077  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1078  ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
1079  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1080  ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
1081  if (pixel.colorspace == CMYKColorspace)
1082  {
1083  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1084  ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,
1085  tuple);
1086  }
1087  if (pixel.matte != MagickFalse)
1088  {
1089  (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
1090  ConcatenateColorComponent(&pixel,AlphaChannel,X11Compliance,
1091  tuple);
1092  }
1093  (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
1094  (void) QueryMagickColorname(image,&pixel,SVGCompliance,color,
1095  exception);
1096  GetColorTuple(&pixel,MagickTrue,hex);
1097  (void) FormatLocaleFile(file," %g: %s %s %s\n",(double) i,tuple,
1098  hex,color);
1099  p++;
1100  }
1101  }
1102  }
1103  if (image->error.mean_error_per_pixel != 0.0)
1104  (void) FormatLocaleFile(file," Mean error per pixel: %g\n",
1105  image->error.mean_error_per_pixel);
1106  if (image->error.normalized_mean_error != 0.0)
1107  (void) FormatLocaleFile(file," Normalized mean error: %g\n",
1108  image->error.normalized_mean_error);
1109  if (image->error.normalized_maximum_error != 0.0)
1110  (void) FormatLocaleFile(file," Normalized maximum error: %g\n",
1111  image->error.normalized_maximum_error);
1112  (void) FormatLocaleFile(file," Rendering intent: %s\n",
1113  CommandOptionToMnemonic(MagickIntentOptions,(ssize_t)
1114  image->rendering_intent));
1115  if (image->gamma != 0.0)
1116  (void) FormatLocaleFile(file," Gamma: %g\n",image->gamma);
1117  if ((image->chromaticity.red_primary.x != 0.0) ||
1118  (image->chromaticity.green_primary.x != 0.0) ||
1119  (image->chromaticity.blue_primary.x != 0.0) ||
1120  (image->chromaticity.white_point.x != 0.0))
1121  {
1122  /*
1123  Display image chromaticity.
1124  */
1125  (void) FormatLocaleFile(file," Chromaticity:\n");
1126  (void) FormatLocaleFile(file," red primary: (%g,%g,%g)\n",
1127  image->chromaticity.red_primary.x,image->chromaticity.red_primary.y,
1128  image->chromaticity.red_primary.z);
1129  (void) FormatLocaleFile(file," green primary: (%g,%g,%g)\n",
1130  image->chromaticity.green_primary.x,image->chromaticity.green_primary.y,
1131  image->chromaticity.green_primary.z);
1132  (void) FormatLocaleFile(file," blue primary: (%g,%g,%g)\n",
1133  image->chromaticity.blue_primary.x,image->chromaticity.blue_primary.y,
1134  image->chromaticity.blue_primary.z);
1135  (void) FormatLocaleFile(file," white point: (%g,%g,%g)\n",
1136  image->chromaticity.white_point.x,image->chromaticity.white_point.y,
1137  image->chromaticity.white_point.z);
1138  }
1139  if ((image->extract_info.width*image->extract_info.height) != 0)
1140  (void) FormatLocaleFile(file," Tile geometry: %.20gx%.20g%+.20g%+.20g\n",
1141  (double) image->extract_info.width,(double) image->extract_info.height,
1142  (double) image->extract_info.x,(double) image->extract_info.y);
1143  (void) QueryColorname(image,&image->background_color,SVGCompliance,color,
1144  exception);
1145  (void) FormatLocaleFile(file," Background color: %s\n",color);
1146  (void) QueryColorname(image,&image->border_color,SVGCompliance,color,
1147  exception);
1148  (void) FormatLocaleFile(file," Border color: %s\n",color);
1149  (void) QueryColorname(image,&image->matte_color,SVGCompliance,color,
1150  exception);
1151  (void) FormatLocaleFile(file," Matte color: %s\n",color);
1152  (void) QueryColorname(image,&image->transparent_color,SVGCompliance,color,
1153  exception);
1154  (void) FormatLocaleFile(file," Transparent color: %s\n",color);
1155  (void) FormatLocaleFile(file," Interlace: %s\n",CommandOptionToMnemonic(
1156  MagickInterlaceOptions,(ssize_t) image->interlace));
1157  (void) FormatLocaleFile(file," Intensity: %s\n",CommandOptionToMnemonic(
1158  MagickPixelIntensityOptions,(ssize_t) image->intensity));
1159  (void) FormatLocaleFile(file," Compose: %s\n",CommandOptionToMnemonic(
1160  MagickComposeOptions,(ssize_t) image->compose));
1161  if ((image->page.width != 0) || (image->page.height != 0) ||
1162  (image->page.x != 0) || (image->page.y != 0))
1163  (void) FormatLocaleFile(file," Page geometry: %.20gx%.20g%+.20g%+.20g\n",
1164  (double) image->page.width,(double) image->page.height,(double)
1165  image->page.x,(double) image->page.y);
1166  if ((image->page.x != 0) || (image->page.y != 0))
1167  (void) FormatLocaleFile(file," Origin geometry: %+.20g%+.20g\n",(double)
1168  image->page.x,(double) image->page.y);
1169  (void) FormatLocaleFile(file," Dispose: %s\n",CommandOptionToMnemonic(
1170  MagickDisposeOptions,(ssize_t) image->dispose));
1171  if (image->delay != 0)
1172  (void) FormatLocaleFile(file," Delay: %.20gx%.20g\n",(double) image->delay,
1173  (double) image->ticks_per_second);
1174  if (image->iterations != 1)
1175  (void) FormatLocaleFile(file," Iterations: %.20g\n",(double)
1176  image->iterations);
1177  if (image->duration != 0)
1178  (void) FormatLocaleFile(file," Duration: %.20g\n",(double)
1179  image->duration);
1180  if ((image->next != (Image *) NULL) || (image->previous != (Image *) NULL))
1181  (void) FormatLocaleFile(file," Scene: %.20g of %.20g\n",(double)
1182  image->scene,(double) GetImageListLength(image));
1183  else
1184  if (image->scene != 0)
1185  (void) FormatLocaleFile(file," Scene: %.20g\n",(double) image->scene);
1186  (void) FormatLocaleFile(file," Compression: %s\n",CommandOptionToMnemonic(
1187  MagickCompressOptions,(ssize_t) image->compression));
1188  if (image->quality != UndefinedCompressionQuality)
1189  (void) FormatLocaleFile(file," Quality: %.20g\n",(double) image->quality);
1190  (void) FormatLocaleFile(file," Orientation: %s\n",CommandOptionToMnemonic(
1191  MagickOrientationOptions,(ssize_t) image->orientation));
1192  if (image->montage != (char *) NULL)
1193  (void) FormatLocaleFile(file," Montage: %s\n",image->montage);
1194  if (image->directory != (char *) NULL)
1195  {
1196  Image
1197  *tile;
1198 
1199  ImageInfo
1200  *image_info;
1201 
1202  char
1203  *p,
1204  *q;
1205 
1206  WarningHandler
1207  handler;
1208 
1209  /*
1210  Display visual image directory.
1211  */
1212  image_info=AcquireImageInfo();
1213  (void) CloneString(&image_info->size,"64x64");
1214  (void) FormatLocaleFile(file," Directory:\n");
1215  for (p=image->directory; *p != '\0'; p++)
1216  {
1217  q=p;
1218  while ((*q != '\xff') && (*q != '\0') &&
1219  ((size_t) (q-p) < sizeof(image_info->filename)))
1220  q++;
1221  (void) CopyMagickString(image_info->filename,p,(size_t) (q-p+1));
1222  p=q;
1223  (void) FormatLocaleFile(file," %s",image_info->filename);
1224  handler=SetWarningHandler((WarningHandler) NULL);
1225  tile=ReadImage(image_info,exception);
1226  (void) SetWarningHandler(handler);
1227  if (tile == (Image *) NULL)
1228  {
1229  (void) FormatLocaleFile(file,"\n");
1230  continue;
1231  }
1232  (void) FormatLocaleFile(file," %.20gx%.20g %s\n",(double)
1233  tile->magick_columns,(double) tile->magick_rows,tile->magick);
1234  (void) SignatureImage(tile);
1235  ResetImagePropertyIterator(tile);
1236  property=GetNextImageProperty(tile);
1237  while (property != (const char *) NULL)
1238  {
1239  (void) FormatLocaleFile(file," %s:\n",property);
1240  value=GetImageProperty(tile,property);
1241  if (value != (const char *) NULL)
1242  (void) FormatLocaleFile(file,"%s\n",value);
1243  property=GetNextImageProperty(tile);
1244  }
1245  tile=DestroyImage(tile);
1246  }
1247  image_info=DestroyImageInfo(image_info);
1248  }
1249  (void) FormatLocaleString(key,MaxTextExtent,"8BIM:1999,2998:#1");
1250  value=GetImageProperty(image,key);
1251  if (value != (const char *) NULL)
1252  {
1253  /*
1254  Display clipping path.
1255  */
1256  (void) FormatLocaleFile(file," Clipping path: ");
1257  if (strlen(value) > 80)
1258  (void) fputc('\n',file);
1259  (void) FormatLocaleFile(file,"%s\n",value);
1260  }
1261  ResetImageProfileIterator(image);
1262  name=GetNextImageProfile(image);
1263  if (name != (char *) NULL)
1264  {
1265  const StringInfo
1266  *profile;
1267 
1268  /*
1269  Identify image profiles.
1270  */
1271  (void) FormatLocaleFile(file," Profiles:\n");
1272  while (name != (char *) NULL)
1273  {
1274  profile=GetImageProfile(image,name);
1275  if (profile == (StringInfo *) NULL)
1276  continue;
1277  (void) FormatLocaleFile(file," Profile-%s: %.20g bytes\n",name,
1278  (double) GetStringInfoLength(profile));
1279  if (LocaleCompare(name,"iptc") == 0)
1280  {
1281  char
1282  *attribute,
1283  **attribute_list;
1284 
1285  const char
1286  *tag;
1287 
1288  long
1289  dataset,
1290  record,
1291  sentinel;
1292 
1293  ssize_t
1294  j;
1295 
1296  size_t
1297  length,
1298  profile_length;
1299 
1300  profile_length=GetStringInfoLength(profile);
1301  for (i=0; i < (ssize_t) profile_length-5; i+=(ssize_t) length)
1302  {
1303  length=1;
1304  sentinel=GetStringInfoDatum(profile)[i++];
1305  if (sentinel != 0x1c)
1306  continue;
1307  dataset=GetStringInfoDatum(profile)[i++];
1308  record=GetStringInfoDatum(profile)[i++];
1309  switch (record)
1310  {
1311  case 5: tag="Image Name"; break;
1312  case 7: tag="Edit Status"; break;
1313  case 10: tag="Priority"; break;
1314  case 15: tag="Category"; break;
1315  case 20: tag="Supplemental Category"; break;
1316  case 22: tag="Fixture Identifier"; break;
1317  case 25: tag="Keyword"; break;
1318  case 30: tag="Release Date"; break;
1319  case 35: tag="Release Time"; break;
1320  case 40: tag="Special Instructions"; break;
1321  case 45: tag="Reference Service"; break;
1322  case 47: tag="Reference Date"; break;
1323  case 50: tag="Reference Number"; break;
1324  case 55: tag="Created Date"; break;
1325  case 60: tag="Created Time"; break;
1326  case 65: tag="Originating Program"; break;
1327  case 70: tag="Program Version"; break;
1328  case 75: tag="Object Cycle"; break;
1329  case 80: tag="Byline"; break;
1330  case 85: tag="Byline Title"; break;
1331  case 90: tag="City"; break;
1332  case 92: tag="Sub-Location"; break;
1333  case 95: tag="Province State"; break;
1334  case 100: tag="Country Code"; break;
1335  case 101: tag="Country"; break;
1336  case 103: tag="Original Transmission Reference"; break;
1337  case 105: tag="Headline"; break;
1338  case 110: tag="Credit"; break;
1339  case 115: tag="Src"; break;
1340  case 116: tag="Copyright String"; break;
1341  case 120: tag="Caption"; break;
1342  case 121: tag="Local Caption"; break;
1343  case 122: tag="Caption Writer"; break;
1344  case 200: tag="Custom Field 1"; break;
1345  case 201: tag="Custom Field 2"; break;
1346  case 202: tag="Custom Field 3"; break;
1347  case 203: tag="Custom Field 4"; break;
1348  case 204: tag="Custom Field 5"; break;
1349  case 205: tag="Custom Field 6"; break;
1350  case 206: tag="Custom Field 7"; break;
1351  case 207: tag="Custom Field 8"; break;
1352  case 208: tag="Custom Field 9"; break;
1353  case 209: tag="Custom Field 10"; break;
1354  case 210: tag="Custom Field 11"; break;
1355  case 211: tag="Custom Field 12"; break;
1356  case 212: tag="Custom Field 13"; break;
1357  case 213: tag="Custom Field 14"; break;
1358  case 214: tag="Custom Field 15"; break;
1359  case 215: tag="Custom Field 16"; break;
1360  case 216: tag="Custom Field 17"; break;
1361  case 217: tag="Custom Field 18"; break;
1362  case 218: tag="Custom Field 19"; break;
1363  case 219: tag="Custom Field 20"; break;
1364  default: tag="unknown"; break;
1365  }
1366  (void) FormatLocaleFile(file," %s[%.20g,%.20g]: ",tag,
1367  (double) dataset,(double) record);
1368  length=(size_t) (GetStringInfoDatum(profile)[i++] << 8);
1369  length|=GetStringInfoDatum(profile)[i++];
1370  length=MagickMin(length,profile_length-i);
1371  attribute=(char *) NULL;
1372  if (~length >= (MaxTextExtent-1))
1373  attribute=(char *) AcquireQuantumMemory(length+
1374  MaxTextExtent,sizeof(*attribute));
1375  if (attribute != (char *) NULL)
1376  {
1377  (void) CopyMagickString(attribute,(char *)
1378  GetStringInfoDatum(profile)+i,length+1);
1379  attribute_list=StringToList(attribute);
1380  if (attribute_list != (char **) NULL)
1381  {
1382  for (j=0; attribute_list[j] != (char *) NULL; j++)
1383  {
1384  (void) fputs(attribute_list[j],file);
1385  (void) fputs("\n",file);
1386  attribute_list[j]=(char *) RelinquishMagickMemory(
1387  attribute_list[j]);
1388  }
1389  attribute_list=(char **) RelinquishMagickMemory(
1390  attribute_list);
1391  }
1392  attribute=DestroyString(attribute);
1393  }
1394  }
1395  }
1396  if (image->debug != MagickFalse)
1397  PrintStringInfo(file,name,profile);
1398  name=GetNextImageProfile(image);
1399  }
1400  }
1401  ResetImagePropertyIterator(image);
1402  property=GetNextImageProperty(image);
1403  if (property != (const char *) NULL)
1404  {
1405  /*
1406  Display image properties.
1407  */
1408  (void) FormatLocaleFile(file," Properties:\n");
1409  while (property != (const char *) NULL)
1410  {
1411  (void) FormatLocaleFile(file," %s: ",property);
1412  value=GetImageProperty(image,property);
1413  if (value != (const char *) NULL)
1414  (void) FormatLocaleFile(file,"%s\n",value);
1415  property=GetNextImageProperty(image);
1416  }
1417  }
1418  ResetImageArtifactIterator(image);
1419  artifact=GetNextImageArtifact(image);
1420  if (artifact != (const char *) NULL)
1421  {
1422  /*
1423  Display image artifacts.
1424  */
1425  (void) FormatLocaleFile(file," Artifacts:\n");
1426  while (artifact != (const char *) NULL)
1427  {
1428  (void) FormatLocaleFile(file," %s: ",artifact);
1429  value=GetImageArtifact(image,artifact);
1430  if (value != (const char *) NULL)
1431  (void) FormatLocaleFile(file,"%s\n",value);
1432  artifact=GetNextImageArtifact(image);
1433  }
1434  }
1435  ResetImageRegistryIterator();
1436  registry=GetNextImageRegistry();
1437  if (registry != (const char *) NULL)
1438  {
1439  /*
1440  Display image registry.
1441  */
1442  (void) FormatLocaleFile(file," Registry:\n");
1443  while (registry != (const char *) NULL)
1444  {
1445  (void) FormatLocaleFile(file," %s: ",registry);
1446  value=(const char *) GetImageRegistry(StringRegistryType,registry,
1447  exception);
1448  if (value != (const char *) NULL)
1449  (void) FormatLocaleFile(file,"%s\n",value);
1450  registry=GetNextImageRegistry();
1451  }
1452  }
1453  (void) FormatLocaleFile(file," Tainted: %s\n",CommandOptionToMnemonic(
1454  MagickBooleanOptions,(ssize_t) image->taint));
1455  (void) FormatMagickSize(image->extent,MagickTrue,format);
1456  (void) FormatLocaleFile(file," Filesize: %s\n",format);
1457  (void) FormatMagickSize((MagickSizeType) image->columns*image->rows,
1458  MagickFalse,format);
1459  if (strlen(format) > 1)
1460  format[strlen(format)-1]='\0';
1461  (void) FormatLocaleFile(file," Number pixels: %s\n",format);
1462  if (elapsed_time > MagickEpsilon)
1463  {
1464  (void) FormatMagickSize((MagickSizeType) ((double) image->columns*
1465  image->rows/elapsed_time+0.5),MagickFalse,format);
1466  (void) FormatLocaleFile(file," Pixels per second: %s\n",format);
1467  }
1468  (void) FormatLocaleFile(file," User time: %0.3fu\n",user_time);
1469  (void) FormatLocaleFile(file," Elapsed time: %lu:%02lu.%03lu\n",
1470  (unsigned long) (elapsed_time/60.0),(unsigned long) ceil(fmod(
1471  elapsed_time,60.0)),(unsigned long) (1000.0*(elapsed_time-floor(
1472  elapsed_time))));
1473  (void) FormatLocaleFile(file," Version: %s\n",GetMagickVersion((size_t *)
1474  NULL));
1475  (void) fflush(file);
1476  return(ferror(file) != 0 ? MagickFalse : MagickTrue);
1477 }
Definition: image.h:152