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"
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;
151 sizeof(*channel_statistics));
153 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
154 (void) memset(channel_statistics,0,length*
155 sizeof(*channel_statistics));
156 for (i=0; i <= (ssize_t) CompositeChannels; i++)
160 case MaximumStatistic:
163 channel_statistics[i].maxima=(-MagickMaximumValue);
166 case MinimumStatistic:
168 channel_statistics[i].minima=MagickMaximumValue;
173 for (y=0; y < (ssize_t) image->rows; y++)
176 *magick_restrict indexes;
184 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
187 indexes=GetVirtualIndexQueue(image);
188 for (x=0; x < (ssize_t) image->columns; x++)
192 case MaximumStatistic:
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)
205 if ((image->colorspace == CMYKColorspace) &&
206 ((double) GetPixelIndex(indexes+x) > channel_statistics[BlackChannel].maxima))
207 channel_statistics[BlackChannel].maxima=(double)
208 GetPixelIndex(indexes+x);
211 case MinimumStatistic:
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)
223 if ((image->colorspace == CMYKColorspace) &&
224 ((double) GetPixelIndex(indexes+x) < channel_statistics[BlackChannel].minima))
225 channel_statistics[BlackChannel].minima=(double)
226 GetPixelIndex(indexes+x);
233 return(channel_statistics);
236 static ssize_t PrintChannelFeatures(FILE *file,
const ChannelType channel,
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 \
246 #define FeaturesFormat " %s:\n" \
247 " Angular Second Moment:\n" \
248 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
250 " %.*g, %.*g, %.*g, %.*g, %.*g\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" \
258 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
260 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
262 " %.*g, %.*g, %.*g, %.*g, %.*g\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"
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));
297 static ssize_t PrintChannelLocations(FILE *file,
const Image *image,
298 const ChannelType channel,
const char *name,
const StatisticType type,
313 case MaximumStatistic:
316 target=channel_statistics[channel].maxima;
321 target=channel_statistics[channel].mean;
324 case MinimumStatistic:
326 target=channel_statistics[channel].minima;
330 (void) FormatLocaleFile(file,
" %s: %.*g (%.*g)",name,GetMagickPrecision(),
331 target,GetMagickPrecision(),QuantumScale*target);
332 exception=AcquireExceptionInfo();
334 for (y=0; y < (ssize_t) image->rows; y++)
342 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
345 for (x=0; x < (ssize_t) image->columns; x++)
355 match=fabs((
double) (p->red-target)) < 0.5 ? MagickTrue : MagickFalse;
360 match=fabs((
double) (p->green-target)) < 0.5 ? MagickTrue :
366 match=fabs((
double) (p->blue-target)) < 0.5 ? MagickTrue :
372 match=fabs((
double) (p->opacity-target)) < 0.5 ? MagickTrue :
379 if (match != MagickFalse)
381 if ((max_locations != 0) && (n >= (ssize_t) max_locations))
383 (void) FormatLocaleFile(file,
" %.20g,%.20g",(
double) x,(double) y);
388 if (x < (ssize_t) image->columns)
391 (void) FormatLocaleFile(file,
"\n");
395 static ssize_t PrintChannelMoments(FILE *file,
const ChannelType channel,
396 const char *name,
const double scale,
const ChannelMoments *channel_moments)
399 powers[MaximumNumberOfImageMoments] =
400 { 1.0, 2.0, 3.0, 3.0, 6.0, 4.0, 6.0, 4.0 };
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]);
430 static ssize_t PrintChannelPerceptualHash(FILE *file,
const ChannelType channel,
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]);
447 static ssize_t PrintChannelStatistics(FILE *file,
const ChannelType channel,
448 const char *name,
const double scale,
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"
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);
477 MagickExport MagickBooleanType IdentifyImage(
Image *image,FILE *file,
478 const MagickBooleanType verbose)
481 color[MaxTextExtent],
482 format[MaxTextExtent],
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)
546 exception=AcquireExceptionInfo();
547 colorspace=image->colorspace;
548 locate=GetImageArtifact(image,
"identify:locate");
549 if (locate != (
const char *) NULL)
563 statistic_type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
565 limit=GetImageArtifact(image,
"identify:limit");
567 if (limit != (
const char *) NULL)
568 max_locations=StringToUnsignedLong(limit);
569 channel_statistics=GetLocationStatistics(image,statistic_type,exception);
572 (void) FormatLocaleFile(file,
" Channel %s locations:\n",locate);
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);
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);
598 case LinearGRAYColorspace:
601 (void) PrintChannelLocations(file,image,GrayChannel,
"Gray",
602 statistic_type,max_locations,channel_statistics);
606 if (image->matte != MagickFalse)
607 (void) PrintChannelLocations(file,image,AlphaChannel,
"Alpha",
608 statistic_type,max_locations,channel_statistics);
611 exception=DestroyExceptionInfo(exception);
612 return(ferror(file) != 0 ? MagickFalse : MagickTrue);
615 elapsed_time=GetElapsedTime(&image->timer);
616 user_time=GetUserTime(&image->timer);
617 GetTimerInfo(&image->timer);
618 if (verbose == MagickFalse)
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);
630 (
void) FormatLocaleFile(file,
"%s[%.20g] ",image->filename,(
double)
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)
654 if (image->total_colors != 0)
656 (void) FormatMagickSize(image->total_colors,MagickFalse,format);
657 (void) FormatLocaleFile(file,
"%s ",format);
661 if (image->total_colors <= image->colors)
662 (void) FormatLocaleFile(file,
"%.20gc ",(
double) image->colors);
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)
673 (void) FormatMagickSize(image->extent,MagickTrue,format);
674 (void) FormatLocaleFile(file,
"%s ",format);
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");
682 exception=DestroyExceptionInfo(exception);
683 return(ferror(file) != 0 ? MagickFalse : MagickTrue);
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);
698 if (ping == MagickFalse)
700 depth=GetImageDepth(image,exception);
701 channel_statistics=GetImageChannelStatistics(image,exception);
704 artifact=GetImageArtifact(image,
"identify:moments");
705 if (artifact != (
const char *) NULL)
707 channel_moments=GetImageChannelMoments(image,exception);
708 channel_phash=GetImageChannelPerceptualHash(image,exception);
710 artifact=GetImageArtifact(image,
"identify:features");
711 if (artifact != (
const char *) NULL)
713 distance=StringToUnsignedLong(artifact);
714 channel_features=GetImageChannelFeatures(image,distance,exception);
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)
722 filename[MaxTextExtent];
724 GetPathComponent(image->magick_filename,TailPath,filename);
725 (void) FormatLocaleFile(file,
" Base filename: %s\n",filename);
727 properties=(*GetBlobProperties(image));
728 if (properties.st_mode != 0)
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]);
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);
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(
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))
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);
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));
780 if (image->depth == depth)
781 (void) FormatLocaleFile(file,
" Depth: %.20g-bit\n",(
double)
784 (
void) FormatLocaleFile(file,
" Depth: %.20g/%.20g-bit\n",(
double)
785 image->depth,(
double) depth);
792 (void) FormatLocaleFile(file,
" Channel depth:\n");
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);
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);
818 case LinearGRAYColorspace:
821 (void) FormatLocaleFile(file,
" gray: %.20g-bit\n",(
double)
822 channel_statistics[GrayChannel].depth);
826 if (image->matte != MagickFalse)
827 (void) FormatLocaleFile(file,
" alpha: %.20g-bit\n",(
double)
828 channel_statistics[OpacityChannel].depth);
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);
841 (void) PrintChannelStatistics(file,RedChannel,
"Red",1.0/scale,
843 (void) PrintChannelStatistics(file,GreenChannel,
"Green",1.0/scale,
845 (void) PrintChannelStatistics(file,BlueChannel,
"Blue",1.0/scale,
851 (void) PrintChannelStatistics(file,CyanChannel,
"Cyan",1.0/scale,
853 (void) PrintChannelStatistics(file,MagentaChannel,
"Magenta",1.0/scale,
855 (void) PrintChannelStatistics(file,YellowChannel,
"Yellow",1.0/scale,
857 (void) PrintChannelStatistics(file,BlackChannel,
"Black",1.0/scale,
861 case LinearGRAYColorspace:
864 (void) PrintChannelStatistics(file,GrayChannel,
"Gray",1.0/scale,
869 if (image->matte != MagickFalse)
870 (void) PrintChannelStatistics(file,AlphaChannel,
"Alpha",1.0/scale,
872 if ((colorspace != LinearGRAYColorspace) && (colorspace != GRAYColorspace))
874 (void) FormatLocaleFile(file,
" Image statistics:\n");
875 (void) PrintChannelStatistics(file,CompositeChannels,
"Overall",1.0/
876 scale,channel_statistics);
883 scale=(double) ((1UL << image->depth)-1);
884 (void) FormatLocaleFile(file,
" Channel moments:\n");
890 (void) PrintChannelMoments(file,RedChannel,
"Red",scale,
892 (void) PrintChannelMoments(file,GreenChannel,
"Green",scale,
894 (void) PrintChannelMoments(file,BlueChannel,
"Blue",scale,
900 (void) PrintChannelMoments(file,CyanChannel,
"Cyan",scale,
902 (void) PrintChannelMoments(file,MagentaChannel,
"Magenta",scale,
904 (void) PrintChannelMoments(file,YellowChannel,
"Yellow",scale,
906 (void) PrintChannelMoments(file,BlackChannel,
"Black",scale,
910 case LinearGRAYColorspace:
913 (void) PrintChannelMoments(file,GrayChannel,
"Gray",scale,
918 if (image->matte != MagickFalse)
919 (void) PrintChannelMoments(file,AlphaChannel,
"Alpha",scale,
921 if ((colorspace != LinearGRAYColorspace) && (colorspace != GRAYColorspace))
923 (void) FormatLocaleFile(file,
" Image moments:\n");
924 (void) PrintChannelMoments(file,CompositeChannels,
"Overall",scale,
932 (void) FormatLocaleFile(file,
" Channel perceptual hash:\n");
933 (void) PrintChannelPerceptualHash(file,RedChannel,
"Red, Hue",
935 (void) PrintChannelPerceptualHash(file,GreenChannel,
"Green, Chroma",
937 (void) PrintChannelPerceptualHash(file,BlueChannel,
"Blue, Luma",
939 if (image->matte != MagickFalse)
940 (void) PrintChannelPerceptualHash(file,AlphaChannel,
"Alpha, Alpha",
947 (void) FormatLocaleFile(file,
" Channel features (horizontal, vertical, "
948 "left and right diagonals, average):\n");
954 (void) PrintChannelFeatures(file,RedChannel,
"Red",channel_features);
955 (void) PrintChannelFeatures(file,GreenChannel,
"Green",
957 (void) PrintChannelFeatures(file,BlueChannel,
"Blue",channel_features);
962 (void) PrintChannelFeatures(file,CyanChannel,
"Cyan",channel_features);
963 (void) PrintChannelFeatures(file,MagentaChannel,
"Magenta",
965 (void) PrintChannelFeatures(file,YellowChannel,
"Yellow",
967 (void) PrintChannelFeatures(file,BlackChannel,
"Black",
971 case LinearGRAYColorspace:
974 (void) PrintChannelFeatures(file,GrayChannel,
"Gray",channel_features);
978 if (image->matte != MagickFalse)
979 (void) PrintChannelFeatures(file,AlphaChannel,
"Alpha",channel_features);
983 if (ping == MagickFalse)
985 if (colorspace == CMYKColorspace)
986 (void) FormatLocaleFile(file,
" Total ink density: %.*g%%\n",
987 GetMagickPrecision(),100.0*GetImageTotalInkDensity(image)/(double)
990 if (image->matte != MagickFalse)
1002 indexes=(IndexPacket *) NULL;
1003 for (y=0; y < (ssize_t) image->rows; y++)
1005 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1008 indexes=GetVirtualIndexQueue(image);
1009 for (x=0; x < (ssize_t) image->columns; x++)
1011 if (GetPixelOpacity(p) == (Quantum) TransparentOpacity)
1018 if (found != MagickFalse)
1021 if (found != MagickFalse)
1024 tuple[MaxTextExtent];
1029 GetMagickPixelPacket(image,&pixel);
1030 SetMagickPixelPacket(image,p,indexes+x,&pixel);
1031 (void) QueryMagickColorname(image,&pixel,SVGCompliance,tuple,
1033 (void) FormatLocaleFile(file,
" Alpha: %s ",tuple);
1034 GetColorTuple(&pixel,MagickTrue,tuple);
1035 (void) FormatLocaleFile(file,
" %s\n",tuple);
1038 artifact=GetImageArtifact(image,
"identify:unique-colors");
1039 if (IsHistogramImage(image,exception) != MagickFalse)
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);
1047 if ((artifact != (
const char *) NULL) &&
1048 (IsMagickTrue(artifact) != MagickFalse))
1049 (void) FormatLocaleFile(file,
" Colors: %.20g\n",(
double)
1050 GetNumberColors(image,(FILE *) NULL,exception));
1052 if (image->storage_class == PseudoClass)
1054 (void) FormatLocaleFile(file,
" Colormap entries: %.20g\n",(
double)
1056 (void) FormatLocaleFile(file,
" Colormap:\n");
1057 if (image->colors <= 1024)
1060 color[MaxTextExtent],
1062 tuple[MaxTextExtent];
1070 GetMagickPixelPacket(image,&pixel);
1072 for (i=0; i < (ssize_t) image->colors; i++)
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)
1083 (void) ConcatenateMagickString(tuple,
",",MaxTextExtent);
1084 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,
1087 if (pixel.matte != MagickFalse)
1089 (void) ConcatenateMagickString(tuple,
",",MaxTextExtent);
1090 ConcatenateColorComponent(&pixel,AlphaChannel,X11Compliance,
1093 (void) ConcatenateMagickString(tuple,
")",MaxTextExtent);
1094 (void) QueryMagickColorname(image,&pixel,SVGCompliance,color,
1096 GetColorTuple(&pixel,MagickTrue,hex);
1097 (void) FormatLocaleFile(file,
" %g: %s %s %s\n",(
double) i,tuple,
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))
1125 (void) FormatLocaleFile(file,
" Chromaticity:\n");
1126 (void) FormatLocaleFile(file,
" red primary: (%g,%g)\n",
1127 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y);
1128 (void) FormatLocaleFile(file,
" green primary: (%g,%g)\n",
1129 image->chromaticity.green_primary.x,
1130 image->chromaticity.green_primary.y);
1131 (void) FormatLocaleFile(file,
" blue primary: (%g,%g)\n",
1132 image->chromaticity.blue_primary.x,image->chromaticity.blue_primary.y);
1133 (void) FormatLocaleFile(file,
" white point: (%g,%g)\n",
1134 image->chromaticity.white_point.x,image->chromaticity.white_point.y);
1136 if ((image->extract_info.width*image->extract_info.height) != 0)
1137 (
void) FormatLocaleFile(file,
" Tile geometry: %.20gx%.20g%+.20g%+.20g\n",
1138 (
double) image->extract_info.width,(
double) image->extract_info.height,
1139 (
double) image->extract_info.x,(
double) image->extract_info.y);
1140 (void) QueryColorname(image,&image->background_color,SVGCompliance,color,
1142 (void) FormatLocaleFile(file,
" Background color: %s\n",color);
1143 (void) QueryColorname(image,&image->border_color,SVGCompliance,color,
1145 (void) FormatLocaleFile(file,
" Border color: %s\n",color);
1146 (void) QueryColorname(image,&image->matte_color,SVGCompliance,color,
1148 (void) FormatLocaleFile(file,
" Matte color: %s\n",color);
1149 (void) QueryColorname(image,&image->transparent_color,SVGCompliance,color,
1151 (void) FormatLocaleFile(file,
" Transparent color: %s\n",color);
1152 (void) FormatLocaleFile(file,
" Interlace: %s\n",CommandOptionToMnemonic(
1153 MagickInterlaceOptions,(ssize_t) image->interlace));
1154 (void) FormatLocaleFile(file,
" Intensity: %s\n",CommandOptionToMnemonic(
1155 MagickPixelIntensityOptions,(ssize_t) image->intensity));
1156 (void) FormatLocaleFile(file,
" Compose: %s\n",CommandOptionToMnemonic(
1157 MagickComposeOptions,(ssize_t) image->compose));
1158 if ((image->page.width != 0) || (image->page.height != 0) ||
1159 (image->page.x != 0) || (image->page.y != 0))
1160 (void) FormatLocaleFile(file,
" Page geometry: %.20gx%.20g%+.20g%+.20g\n",
1161 (
double) image->page.width,(double) image->page.height,(
double)
1162 image->page.x,(double) image->page.y);
1163 if ((image->page.x != 0) || (image->page.y != 0))
1164 (void) FormatLocaleFile(file,
" Origin geometry: %+.20g%+.20g\n",(
double)
1165 image->page.x,(double) image->page.y);
1166 (void) FormatLocaleFile(file,
" Dispose: %s\n",CommandOptionToMnemonic(
1167 MagickDisposeOptions,(ssize_t) image->dispose));
1168 if (image->delay != 0)
1169 (void) FormatLocaleFile(file,
" Delay: %.20gx%.20g\n",(
double) image->delay,
1170 (double) image->ticks_per_second);
1171 if (image->iterations != 1)
1172 (void) FormatLocaleFile(file,
" Iterations: %.20g\n",(
double)
1174 if (image->duration != 0)
1175 (void) FormatLocaleFile(file,
" Duration: %.20g\n",(
double)
1177 if ((image->next != (
Image *) NULL) || (image->previous != (
Image *) NULL))
1178 (void) FormatLocaleFile(file,
" Scene: %.20g of %.20g\n",(
double)
1179 image->scene,(double) GetImageListLength(image));
1181 if (image->scene != 0)
1182 (void) FormatLocaleFile(file,
" Scene: %.20g\n",(
double) image->scene);
1183 (void) FormatLocaleFile(file,
" Compression: %s\n",CommandOptionToMnemonic(
1184 MagickCompressOptions,(ssize_t) image->compression));
1185 if (image->quality != UndefinedCompressionQuality)
1186 (void) FormatLocaleFile(file,
" Quality: %.20g\n",(
double) image->quality);
1187 (void) FormatLocaleFile(file,
" Orientation: %s\n",CommandOptionToMnemonic(
1188 MagickOrientationOptions,(ssize_t) image->orientation));
1189 if (image->montage != (
char *) NULL)
1190 (
void) FormatLocaleFile(file,
" Montage: %s\n",image->montage);
1191 if (image->directory != (
char *) NULL)
1209 image_info=AcquireImageInfo();
1210 (void) CloneString(&image_info->size,
"64x64");
1211 (void) FormatLocaleFile(file,
" Directory:\n");
1212 for (p=image->directory; *p !=
'\0'; p++)
1215 while ((*q !=
'\xff') && (*q !=
'\0') &&
1216 ((
size_t) (q-p) <
sizeof(image_info->filename)))
1218 (void) CopyMagickString(image_info->filename,p,(
size_t) (q-p+1));
1220 (void) FormatLocaleFile(file,
" %s",image_info->filename);
1221 handler=SetWarningHandler((WarningHandler) NULL);
1222 tile=ReadImage(image_info,exception);
1223 (void) SetWarningHandler(handler);
1224 if (tile == (
Image *) NULL)
1226 (void) FormatLocaleFile(file,
"\n");
1229 (void) FormatLocaleFile(file,
" %.20gx%.20g %s\n",(
double)
1230 tile->magick_columns,(double) tile->magick_rows,tile->magick);
1231 (void) SignatureImage(tile);
1232 ResetImagePropertyIterator(tile);
1233 property=GetNextImageProperty(tile);
1234 while (property != (
const char *) NULL)
1236 (void) FormatLocaleFile(file,
" %s:\n",property);
1237 value=GetImageProperty(tile,property);
1238 if (value != (
const char *) NULL)
1239 (void) FormatLocaleFile(file,
"%s\n",value);
1240 property=GetNextImageProperty(tile);
1242 tile=DestroyImage(tile);
1244 image_info=DestroyImageInfo(image_info);
1246 (void) FormatLocaleString(key,MaxTextExtent,
"8BIM:1999,2998:#1");
1247 value=GetImageProperty(image,key);
1248 if (value != (
const char *) NULL)
1253 (void) FormatLocaleFile(file,
" Clipping path: ");
1254 if (strlen(value) > 80)
1255 (
void) fputc(
'\n',file);
1256 (void) FormatLocaleFile(file,
"%s\n",value);
1258 ResetImageProfileIterator(image);
1259 name=GetNextImageProfile(image);
1260 if (name != (
char *) NULL)
1268 (void) FormatLocaleFile(file,
" Profiles:\n");
1269 while (name != (
char *) NULL)
1271 profile=GetImageProfile(image,name);
1274 (void) FormatLocaleFile(file,
" Profile-%s: %.20g bytes\n",name,
1275 (
double) GetStringInfoLength(profile));
1276 if (LocaleCompare(name,
"iptc") == 0)
1297 profile_length=GetStringInfoLength(profile);
1298 for (i=0; i < (ssize_t) profile_length-5; i+=(ssize_t) length)
1301 sentinel=GetStringInfoDatum(profile)[i++];
1302 if (sentinel != 0x1c)
1304 dataset=GetStringInfoDatum(profile)[i++];
1305 record=GetStringInfoDatum(profile)[i++];
1308 case 5: tag=
"Image Name";
break;
1309 case 7: tag=
"Edit Status";
break;
1310 case 10: tag=
"Priority";
break;
1311 case 15: tag=
"Category";
break;
1312 case 20: tag=
"Supplemental Category";
break;
1313 case 22: tag=
"Fixture Identifier";
break;
1314 case 25: tag=
"Keyword";
break;
1315 case 30: tag=
"Release Date";
break;
1316 case 35: tag=
"Release Time";
break;
1317 case 40: tag=
"Special Instructions";
break;
1318 case 45: tag=
"Reference Service";
break;
1319 case 47: tag=
"Reference Date";
break;
1320 case 50: tag=
"Reference Number";
break;
1321 case 55: tag=
"Created Date";
break;
1322 case 60: tag=
"Created Time";
break;
1323 case 65: tag=
"Originating Program";
break;
1324 case 70: tag=
"Program Version";
break;
1325 case 75: tag=
"Object Cycle";
break;
1326 case 80: tag=
"Byline";
break;
1327 case 85: tag=
"Byline Title";
break;
1328 case 90: tag=
"City";
break;
1329 case 92: tag=
"Sub-Location";
break;
1330 case 95: tag=
"Province State";
break;
1331 case 100: tag=
"Country Code";
break;
1332 case 101: tag=
"Country";
break;
1333 case 103: tag=
"Original Transmission Reference";
break;
1334 case 105: tag=
"Headline";
break;
1335 case 110: tag=
"Credit";
break;
1336 case 115: tag=
"Src";
break;
1337 case 116: tag=
"Copyright String";
break;
1338 case 120: tag=
"Caption";
break;
1339 case 121: tag=
"Local Caption";
break;
1340 case 122: tag=
"Caption Writer";
break;
1341 case 200: tag=
"Custom Field 1";
break;
1342 case 201: tag=
"Custom Field 2";
break;
1343 case 202: tag=
"Custom Field 3";
break;
1344 case 203: tag=
"Custom Field 4";
break;
1345 case 204: tag=
"Custom Field 5";
break;
1346 case 205: tag=
"Custom Field 6";
break;
1347 case 206: tag=
"Custom Field 7";
break;
1348 case 207: tag=
"Custom Field 8";
break;
1349 case 208: tag=
"Custom Field 9";
break;
1350 case 209: tag=
"Custom Field 10";
break;
1351 case 210: tag=
"Custom Field 11";
break;
1352 case 211: tag=
"Custom Field 12";
break;
1353 case 212: tag=
"Custom Field 13";
break;
1354 case 213: tag=
"Custom Field 14";
break;
1355 case 214: tag=
"Custom Field 15";
break;
1356 case 215: tag=
"Custom Field 16";
break;
1357 case 216: tag=
"Custom Field 17";
break;
1358 case 217: tag=
"Custom Field 18";
break;
1359 case 218: tag=
"Custom Field 19";
break;
1360 case 219: tag=
"Custom Field 20";
break;
1361 default: tag=
"unknown";
break;
1363 (void) FormatLocaleFile(file,
" %s[%.20g,%.20g]: ",tag,
1364 (
double) dataset,(double) record);
1365 length=(size_t) (GetStringInfoDatum(profile)[i++] << 8);
1366 length|=GetStringInfoDatum(profile)[i++];
1367 length=MagickMin(length,profile_length-i);
1368 attribute=(
char *) NULL;
1369 if (~length >= (MaxTextExtent-1))
1370 attribute=(
char *) AcquireQuantumMemory(length+
1371 MaxTextExtent,
sizeof(*attribute));
1372 if (attribute != (
char *) NULL)
1374 (void) CopyMagickString(attribute,(
char *)
1375 GetStringInfoDatum(profile)+i,length+1);
1376 attribute_list=StringToList(attribute);
1377 if (attribute_list != (
char **) NULL)
1379 for (j=0; attribute_list[j] != (
char *) NULL; j++)
1381 (void) fputs(attribute_list[j],file);
1382 (void) fputs(
"\n",file);
1383 attribute_list[j]=(
char *) RelinquishMagickMemory(
1386 attribute_list=(
char **) RelinquishMagickMemory(
1389 attribute=DestroyString(attribute);
1393 if (image->debug != MagickFalse)
1394 PrintStringInfo(file,name,profile);
1395 name=GetNextImageProfile(image);
1398 ResetImagePropertyIterator(image);
1399 property=GetNextImageProperty(image);
1400 if (property != (
const char *) NULL)
1405 (void) FormatLocaleFile(file,
" Properties:\n");
1406 while (property != (
const char *) NULL)
1408 (void) FormatLocaleFile(file,
" %s: ",property);
1409 value=GetImageProperty(image,property);
1410 if (value != (
const char *) NULL)
1411 (void) FormatLocaleFile(file,
"%s\n",value);
1412 property=GetNextImageProperty(image);
1415 ResetImageArtifactIterator(image);
1416 artifact=GetNextImageArtifact(image);
1417 if (artifact != (
const char *) NULL)
1422 (void) FormatLocaleFile(file,
" Artifacts:\n");
1423 while (artifact != (
const char *) NULL)
1425 (void) FormatLocaleFile(file,
" %s: ",artifact);
1426 value=GetImageArtifact(image,artifact);
1427 if (value != (
const char *) NULL)
1428 (void) FormatLocaleFile(file,
"%s\n",value);
1429 artifact=GetNextImageArtifact(image);
1432 ResetImageRegistryIterator();
1433 registry=GetNextImageRegistry();
1434 if (registry != (
const char *) NULL)
1439 (void) FormatLocaleFile(file,
" Registry:\n");
1440 while (registry != (
const char *) NULL)
1442 (void) FormatLocaleFile(file,
" %s: ",registry);
1443 value=(
const char *) GetImageRegistry(StringRegistryType,registry,
1445 if (value != (
const char *) NULL)
1446 (
void) FormatLocaleFile(file,
"%s\n",value);
1447 registry=GetNextImageRegistry();
1450 (void) FormatLocaleFile(file,
" Tainted: %s\n",CommandOptionToMnemonic(
1451 MagickBooleanOptions,(ssize_t) image->taint));
1452 (void) FormatMagickSize(image->extent,MagickTrue,format);
1453 (void) FormatLocaleFile(file,
" Filesize: %s\n",format);
1454 (void) FormatMagickSize((MagickSizeType) image->columns*image->rows,
1455 MagickFalse,format);
1456 if (strlen(format) > 1)
1457 format[strlen(format)-1]=
'\0';
1458 (void) FormatLocaleFile(file,
" Number pixels: %s\n",format);
1459 if (elapsed_time > MagickEpsilon)
1461 (void) FormatMagickSize((MagickSizeType) ((double) image->columns*
1462 image->rows/elapsed_time+0.5),MagickFalse,format);
1463 (void) FormatLocaleFile(file,
" Pixels per second: %s\n",format);
1465 (void) FormatLocaleFile(file,
" User time: %0.3fu\n",user_time);
1466 (void) FormatLocaleFile(file,
" Elapsed time: %lu:%02lu.%03lu\n",
1467 (
unsigned long) (elapsed_time/60.0),(
unsigned long) ceil(fmod(
1468 elapsed_time,60.0)),(
unsigned long) (1000.0*(elapsed_time-floor(
1470 (void) FormatLocaleFile(file,
" Version: %s\n",GetMagickVersion((
size_t *)
1472 (void) fflush(file);
1473 return(ferror(file) != 0 ? MagickFalse : MagickTrue);