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/cache.h"
52 #include "magick/client.h"
53 #include "magick/coder.h"
54 #include "magick/color.h"
55 #include "magick/configure.h"
56 #include "magick/constitute.h"
57 #include "magick/decorate.h"
58 #include "magick/delegate.h"
59 #include "magick/draw.h"
60 #include "magick/effect.h"
61 #include "magick/exception.h"
62 #include "magick/exception-private.h"
63 #include "magick/feature.h"
64 #include "magick/gem.h"
65 #include "magick/geometry.h"
66 #include "magick/histogram.h"
67 #include "magick/identify.h"
68 #include "magick/image.h"
69 #include "magick/image-private.h"
70 #include "magick/list.h"
71 #include "magick/locale_.h"
72 #include "magick/log.h"
73 #include "magick/magic.h"
74 #include "magick/magick.h"
75 #include "magick/memory_.h"
76 #include "magick/module.h"
77 #include "magick/monitor.h"
78 #include "magick/montage.h"
79 #include "magick/option.h"
80 #include "magick/pixel-private.h"
81 #include "magick/prepress.h"
82 #include "magick/profile.h"
83 #include "magick/property.h"
84 #include "magick/quantize.h"
85 #include "magick/quantum.h"
86 #include "magick/random_.h"
87 #include "magick/registry.h"
88 #include "magick/resize.h"
89 #include "magick/resource_.h"
90 #include "magick/signature.h"
91 #include "magick/statistic.h"
92 #include "magick/string_.h"
93 #include "magick/string-private.h"
94 #include "magick/timer.h"
95 #include "magick/token.h"
96 #include "magick/utility.h"
97 #include "magick/version.h"
144 assert(image != (
Image *) NULL);
145 assert(image->signature == MagickCoreSignature);
146 if (IsEventLogging() != MagickFalse)
147 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
148 length=CompositeChannels+1UL;
150 sizeof(*channel_statistics));
152 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
153 (void) memset(channel_statistics,0,length*
154 sizeof(*channel_statistics));
155 for (i=0; i <= (ssize_t) CompositeChannels; i++)
159 case MaximumStatistic:
162 channel_statistics[i].maxima=(-MagickMaximumValue);
165 case MinimumStatistic:
167 channel_statistics[i].minima=MagickMaximumValue;
172 for (y=0; y < (ssize_t) image->rows; y++)
175 *magick_restrict indexes;
183 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
186 indexes=GetVirtualIndexQueue(image);
187 for (x=0; x < (ssize_t) image->columns; x++)
191 case MaximumStatistic:
194 if ((
double) GetPixelRed(p) > channel_statistics[RedChannel].maxima)
195 channel_statistics[RedChannel].maxima=(
double) GetPixelRed(p);
196 if ((
double) GetPixelGreen(p) > channel_statistics[GreenChannel].maxima)
197 channel_statistics[GreenChannel].maxima=(double) GetPixelGreen(p);
198 if ((
double) GetPixelBlue(p) > channel_statistics[BlueChannel].maxima)
199 channel_statistics[BlueChannel].maxima=(
double) GetPixelBlue(p);
200 if ((image->matte != MagickFalse) &&
201 ((
double) GetPixelOpacity(p) > channel_statistics[OpacityChannel].maxima))
202 channel_statistics[OpacityChannel].maxima=(double)
204 if ((image->colorspace == CMYKColorspace) &&
205 ((double) GetPixelIndex(indexes+x) > channel_statistics[BlackChannel].maxima))
206 channel_statistics[BlackChannel].maxima=(double)
207 GetPixelIndex(indexes+x);
210 case MinimumStatistic:
212 if ((
double) GetPixelRed(p) < channel_statistics[RedChannel].minima)
213 channel_statistics[RedChannel].minima=(
double) GetPixelRed(p);
214 if ((
double) GetPixelGreen(p) < channel_statistics[GreenChannel].minima)
215 channel_statistics[GreenChannel].minima=(double) GetPixelGreen(p);
216 if ((
double) GetPixelBlue(p) < channel_statistics[BlueChannel].minima)
217 channel_statistics[BlueChannel].minima=(
double) GetPixelBlue(p);
218 if ((image->matte != MagickFalse) &&
219 ((
double) GetPixelOpacity(p) < channel_statistics[OpacityChannel].minima))
220 channel_statistics[OpacityChannel].minima=(double)
222 if ((image->colorspace == CMYKColorspace) &&
223 ((double) GetPixelIndex(indexes+x) < channel_statistics[BlackChannel].minima))
224 channel_statistics[BlackChannel].minima=(double)
225 GetPixelIndex(indexes+x);
232 return(channel_statistics);
235 static ssize_t PrintChannelFeatures(FILE *file,
const ChannelType channel,
238 #define PrintFeature(feature) \
239 GetMagickPrecision(),(feature)[0], \
240 GetMagickPrecision(),(feature)[1], \
241 GetMagickPrecision(),(feature)[2], \
242 GetMagickPrecision(),(feature)[3], \
243 GetMagickPrecision(),((feature)[0]+(feature)[1]+(feature)[2]+(feature)[3])/4.0 \
245 #define FeaturesFormat " %s:\n" \
246 " Angular Second Moment:\n" \
247 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
249 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
251 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
252 " Sum of Squares Variance:\n" \
253 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
254 " Inverse Difference Moment:\n" \
255 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
257 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
259 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
261 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
263 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
264 " Difference Variance:\n" \
265 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
266 " Difference Entropy:\n" \
267 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
268 " Information Measure of Correlation 1:\n" \
269 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
270 " Information Measure of Correlation 2:\n" \
271 " %.*g, %.*g, %.*g, %.*g, %.*g\n" \
272 " Maximum Correlation Coefficient:\n" \
273 " %.*g, %.*g, %.*g, %.*g, %.*g\n"
278 n=FormatLocaleFile(file,FeaturesFormat,name,
279 PrintFeature(channel_features[channel].angular_second_moment),
280 PrintFeature(channel_features[channel].contrast),
281 PrintFeature(channel_features[channel].correlation),
282 PrintFeature(channel_features[channel].variance_sum_of_squares),
283 PrintFeature(channel_features[channel].inverse_difference_moment),
284 PrintFeature(channel_features[channel].sum_average),
285 PrintFeature(channel_features[channel].sum_variance),
286 PrintFeature(channel_features[channel].sum_entropy),
287 PrintFeature(channel_features[channel].entropy),
288 PrintFeature(channel_features[channel].difference_variance),
289 PrintFeature(channel_features[channel].difference_entropy),
290 PrintFeature(channel_features[channel].measure_of_correlation_1),
291 PrintFeature(channel_features[channel].measure_of_correlation_2),
292 PrintFeature(channel_features[channel].maximum_correlation_coefficient));
296 static ssize_t PrintChannelLocations(FILE *file,
const Image *image,
297 const ChannelType channel,
const char *name,
const StatisticType type,
312 case MaximumStatistic:
315 target=channel_statistics[channel].maxima;
320 target=channel_statistics[channel].mean;
323 case MinimumStatistic:
325 target=channel_statistics[channel].minima;
329 (void) FormatLocaleFile(file,
" %s: %.*g (%.*g)",name,GetMagickPrecision(),
330 target,GetMagickPrecision(),QuantumScale*target);
331 exception=AcquireExceptionInfo();
333 for (y=0; y < (ssize_t) image->rows; y++)
341 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
344 for (x=0; x < (ssize_t) image->columns; x++)
354 match=fabs((
double) (p->red-target)) < 0.5 ? MagickTrue : MagickFalse;
359 match=fabs((
double) (p->green-target)) < 0.5 ? MagickTrue :
365 match=fabs((
double) (p->blue-target)) < 0.5 ? MagickTrue :
371 match=fabs((
double) (p->opacity-target)) < 0.5 ? MagickTrue :
378 if (match != MagickFalse)
380 if ((max_locations != 0) && (n >= (ssize_t) max_locations))
382 (void) FormatLocaleFile(file,
" %.20g,%.20g",(
double) x,(double) y);
387 if (x < (ssize_t) image->columns)
390 (void) FormatLocaleFile(file,
"\n");
394 static ssize_t PrintChannelMoments(FILE *file,
const ChannelType channel,
395 const char *name,
const double scale,
const ChannelMoments *channel_moments)
398 powers[MaximumNumberOfImageMoments] =
399 { 1.0, 2.0, 3.0, 3.0, 6.0, 4.0, 6.0, 4.0 };
407 n=FormatLocaleFile(file,
" %s:\n",name);
408 n+=FormatLocaleFile(file,
" Centroid: %.*g,%.*g\n",
409 GetMagickPrecision(),channel_moments[channel].centroid.x,
410 GetMagickPrecision(),channel_moments[channel].centroid.y);
411 n+=FormatLocaleFile(file,
" Ellipse Semi-Major/Minor axis: %.*g,%.*g\n",
412 GetMagickPrecision(),channel_moments[channel].ellipse_axis.x,
413 GetMagickPrecision(),channel_moments[channel].ellipse_axis.y);
414 n+=FormatLocaleFile(file,
" Ellipse angle: %.*g\n",
415 GetMagickPrecision(),channel_moments[channel].ellipse_angle);
416 n+=FormatLocaleFile(file,
" Ellipse eccentricity: %.*g\n",
417 GetMagickPrecision(),channel_moments[channel].ellipse_eccentricity);
418 n+=FormatLocaleFile(file,
" Ellipse intensity: %.*g (%.*g)\n",
419 GetMagickPrecision(),pow(scale,powers[0])*
420 channel_moments[channel].ellipse_intensity,GetMagickPrecision(),
421 channel_moments[channel].ellipse_intensity);
422 for (i=0; i < MaximumNumberOfImageMoments; i++)
423 n+=FormatLocaleFile(file,
" I%.20g: %.*g (%.*g)\n",i+1.0,
424 GetMagickPrecision(),channel_moments[channel].I[i]/pow(scale,powers[i]),
425 GetMagickPrecision(),channel_moments[channel].I[i]);
429 static ssize_t PrintChannelPerceptualHash(FILE *file,
const ChannelType channel,
438 n=FormatLocaleFile(file,
" %s:\n",name);
439 for (i=0; i < MaximumNumberOfPerceptualHashes; i++)
440 n+=FormatLocaleFile(file,
" PH%.20g: %.*g, %.*g\n",i+1.0,
441 GetMagickPrecision(),channel_phash[channel].P[i],
442 GetMagickPrecision(),channel_phash[channel].Q[i]);
446 static ssize_t PrintChannelStatistics(FILE *file,
const ChannelType channel,
447 const char *name,
const double scale,
450 #define StatisticsFormat " %s:\n min: %.*g (%.*g)\n " \
451 "max: %.*g (%.*g)\n mean: %.*g (%.*g)\n " \
452 "standard deviation: %.*g (%.*g)\n kurtosis: %.*g\n " \
453 "skewness: %.*g\n entropy: %.*g\n"
458 n=FormatLocaleFile(file,StatisticsFormat,name,GetMagickPrecision(),
459 (
double) ClampToQuantum((MagickRealType) (scale*
460 channel_statistics[channel].minima)),GetMagickPrecision(),
461 channel_statistics[channel].minima/(
double) QuantumRange,
462 GetMagickPrecision(),(
double) ClampToQuantum((MagickRealType) (scale*
463 channel_statistics[channel].maxima)),GetMagickPrecision(),
464 channel_statistics[channel].maxima/(
double) QuantumRange,
465 GetMagickPrecision(),scale*channel_statistics[channel].mean,
466 GetMagickPrecision(),channel_statistics[channel].mean/(
double) QuantumRange,
467 GetMagickPrecision(),scale*channel_statistics[channel].standard_deviation,
468 GetMagickPrecision(),channel_statistics[channel].standard_deviation/
469 (
double) QuantumRange,GetMagickPrecision(),
470 channel_statistics[channel].kurtosis,GetMagickPrecision(),
471 channel_statistics[channel].skewness,GetMagickPrecision(),
472 channel_statistics[channel].entropy);
476 MagickExport MagickBooleanType IdentifyImage(
Image *image,FILE *file,
477 const MagickBooleanType verbose)
480 color[MaxTextExtent],
481 format[MaxTextExtent],
538 assert(image != (
Image *) NULL);
539 assert(image->signature == MagickCoreSignature);
540 if (IsEventLogging() != MagickFalse)
541 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
542 if (file == (FILE *) NULL)
544 exception=AcquireExceptionInfo();
545 colorspace=image->colorspace;
546 locate=GetImageArtifact(image,
"identify:locate");
547 if (locate != (
const char *) NULL)
561 statistic_type=(StatisticType) ParseCommandOption(MagickStatisticOptions,
563 limit=GetImageArtifact(image,
"identify:limit");
565 if (limit != (
const char *) NULL)
566 max_locations=StringToUnsignedLong(limit);
567 channel_statistics=GetLocationStatistics(image,statistic_type,exception);
570 (void) FormatLocaleFile(file,
" Channel %s locations:\n",locate);
576 (void) PrintChannelLocations(file,image,RedChannel,
"Red",
577 statistic_type,max_locations,channel_statistics);
578 (void) PrintChannelLocations(file,image,GreenChannel,
"Green",
579 statistic_type,max_locations,channel_statistics);
580 (void) PrintChannelLocations(file,image,BlueChannel,
"Blue",
581 statistic_type,max_locations,channel_statistics);
586 (void) PrintChannelLocations(file,image,CyanChannel,
"Cyan",
587 statistic_type,max_locations,channel_statistics);
588 (void) PrintChannelLocations(file,image,MagentaChannel,
"Magenta",
589 statistic_type,max_locations,channel_statistics);
590 (void) PrintChannelLocations(file,image,YellowChannel,
"Yellow",
591 statistic_type,max_locations,channel_statistics);
592 (void) PrintChannelLocations(file,image,BlackChannel,
"Black",
593 statistic_type,max_locations,channel_statistics);
596 case LinearGRAYColorspace:
599 (void) PrintChannelLocations(file,image,GrayChannel,
"Gray",
600 statistic_type,max_locations,channel_statistics);
604 if (image->matte != MagickFalse)
605 (void) PrintChannelLocations(file,image,AlphaChannel,
"Alpha",
606 statistic_type,max_locations,channel_statistics);
609 exception=DestroyExceptionInfo(exception);
610 return(ferror(file) != 0 ? MagickFalse : MagickTrue);
613 elapsed_time=GetElapsedTime(&image->timer);
614 user_time=GetUserTime(&image->timer);
615 GetTimerInfo(&image->timer);
616 if (verbose == MagickFalse)
621 if (*image->magick_filename !=
'\0')
622 if (LocaleCompare(image->magick_filename,image->filename) != 0)
623 (void) FormatLocaleFile(file,
"%s=>",image->magick_filename);
624 if ((GetPreviousImageInList(image) == (
Image *) NULL) &&
625 (GetNextImageInList(image) == (
Image *) NULL) && (image->scene == 0))
626 (void) FormatLocaleFile(file,
"%s ",image->filename);
628 (
void) FormatLocaleFile(file,
"%s[%.20g] ",image->filename,(
double)
630 (void) FormatLocaleFile(file,
"%s ",image->magick);
631 if ((image->magick_columns != 0) || (image->magick_rows != 0))
632 if ((image->magick_columns != image->columns) ||
633 (image->magick_rows != image->rows))
634 (void) FormatLocaleFile(file,
"%.20gx%.20g=>",(
double)
635 image->magick_columns,(double) image->magick_rows);
636 (void) FormatLocaleFile(file,
"%.20gx%.20g ",(
double) image->columns,
637 (double) image->rows);
638 if ((image->page.width != 0) || (image->page.height != 0) ||
639 (image->page.x != 0) || (image->page.y != 0))
640 (void) FormatLocaleFile(file,
"%.20gx%.20g%+.20g%+.20g ",(
double)
641 image->page.width,(double) image->page.height,(
double) image->page.x,
642 (double) image->page.y);
643 (void) FormatLocaleFile(file,
"%.20g-bit ",(
double) image->depth);
644 if (image->type != UndefinedType)
645 (void) FormatLocaleFile(file,
"%s ",CommandOptionToMnemonic(
646 MagickTypeOptions,(ssize_t) image->type));
647 if (colorspace != UndefinedColorspace)
648 (void) FormatLocaleFile(file,
"%s ",CommandOptionToMnemonic(
649 MagickColorspaceOptions,(ssize_t) colorspace));
650 if (image->storage_class == DirectClass)
652 if (image->total_colors != 0)
654 (void) FormatMagickSize(image->total_colors,MagickFalse,format);
655 (void) FormatLocaleFile(file,
"%s ",format);
659 if (image->total_colors <= image->colors)
660 (void) FormatLocaleFile(file,
"%.20gc ",(
double) image->colors);
662 (
void) FormatLocaleFile(file,
"%.20g=>%.20gc ",(
double)
663 image->total_colors,(
double) image->colors);
664 if (image->error.mean_error_per_pixel != 0.0)
665 (void) FormatLocaleFile(file,
"%.20g/%f/%fdb ",(
double)
666 (image->error.mean_error_per_pixel+0.5),
667 image->error.normalized_mean_error,
668 image->error.normalized_maximum_error);
669 if (image->extent != 0)
671 (void) FormatMagickSize(image->extent,MagickTrue,format);
672 (void) FormatLocaleFile(file,
"%s ",format);
674 (void) FormatLocaleFile(file,
"%0.3fu %lu:%02lu.%03lu",user_time,
675 (
unsigned long) (elapsed_time/60.0),(
unsigned long) floor(fmod(
676 elapsed_time,60.0)),(
unsigned long) (1000.0*(elapsed_time-
677 floor(elapsed_time))));
678 (void) FormatLocaleFile(file,
"\n");
680 exception=DestroyExceptionInfo(exception);
681 return(ferror(file) != 0 ? MagickFalse : MagickTrue);
686 pixels=GetVirtualPixels(image,0,0,1,1,exception);
687 exception=DestroyExceptionInfo(exception);
688 ping=pixels == (
const PixelPacket *) NULL ? MagickTrue : MagickFalse;
689 exception=(&image->exception);
690 (void) SignatureImage(image);
696 if (ping == MagickFalse)
698 depth=GetImageDepth(image,exception);
699 channel_statistics=GetImageChannelStatistics(image,exception);
702 artifact=GetImageArtifact(image,
"identify:moments");
703 if (artifact != (
const char *) NULL)
705 channel_moments=GetImageChannelMoments(image,exception);
706 channel_phash=GetImageChannelPerceptualHash(image,exception);
708 artifact=GetImageArtifact(image,
"identify:features");
709 if (artifact != (
const char *) NULL)
711 distance=StringToUnsignedLong(artifact);
712 channel_features=GetImageChannelFeatures(image,distance,exception);
715 (void) FormatLocaleFile(file,
"Image:\n Filename: %s\n",image->filename);
716 if (*image->magick_filename !=
'\0')
717 if (LocaleCompare(image->magick_filename,image->filename) != 0)
720 filename[MaxTextExtent];
722 GetPathComponent(image->magick_filename,TailPath,filename);
723 (void) FormatLocaleFile(file,
" Base filename: %s\n",filename);
725 magick_info=GetMagickInfo(image->magick,exception);
726 if ((magick_info == (
const MagickInfo *) NULL) ||
727 (GetMagickDescription(magick_info) == (
const char *) NULL))
728 (void) FormatLocaleFile(file,
" Format: %s\n",image->magick);
730 (
void) FormatLocaleFile(file,
" Format: %s (%s)\n",image->magick,
731 GetMagickDescription(magick_info));
732 if ((magick_info != (
const MagickInfo *) NULL) &&
733 (GetMagickMimeType(magick_info) != (
const char *) NULL))
734 (void) FormatLocaleFile(file,
" Mime type: %s\n",GetMagickMimeType(
736 (void) FormatLocaleFile(file,
" Class: %s\n",CommandOptionToMnemonic(
737 MagickClassOptions,(ssize_t) image->storage_class));
738 (void) FormatLocaleFile(file,
" Geometry: %.20gx%.20g%+.20g%+.20g\n",(
double)
739 image->columns,(double) image->rows,(
double) image->tile_offset.x,(double)
740 image->tile_offset.y);
741 if ((image->magick_columns != 0) || (image->magick_rows != 0))
742 if ((image->magick_columns != image->columns) ||
743 (image->magick_rows != image->rows))
744 (void) FormatLocaleFile(file,
" Base geometry: %.20gx%.20g\n",(
double)
745 image->magick_columns,(double) image->magick_rows);
746 if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
748 (void) FormatLocaleFile(file,
" Resolution: %gx%g\n",image->x_resolution,
749 image->y_resolution);
750 (void) FormatLocaleFile(file,
" Print size: %gx%g\n",(
double)
751 image->columns/image->x_resolution,(double) image->rows/
752 image->y_resolution);
754 (void) FormatLocaleFile(file,
" Units: %s\n",CommandOptionToMnemonic(
755 MagickResolutionOptions,(ssize_t) image->units));
756 (void) FormatLocaleFile(file,
" Colorspace: %s\n",CommandOptionToMnemonic(
757 MagickColorspaceOptions,(ssize_t) colorspace));
758 type=IdentifyImageType(image,exception);
759 (void) FormatLocaleFile(file,
" Type: %s\n",CommandOptionToMnemonic(
760 MagickTypeOptions,(ssize_t) type));
761 if (image->type != type)
762 (void) FormatLocaleFile(file,
" Base type: %s\n",CommandOptionToMnemonic(
763 MagickTypeOptions,(ssize_t) image->type));
764 (void) FormatLocaleFile(file,
" Endianness: %s\n",CommandOptionToMnemonic(
765 MagickEndianOptions,(ssize_t) image->endian));
768 if (image->depth == depth)
769 (void) FormatLocaleFile(file,
" Depth: %.20g-bit\n",(
double)
772 (
void) FormatLocaleFile(file,
" Depth: %.20g/%.20g-bit\n",(
double)
773 image->depth,(
double) depth);
780 (void) FormatLocaleFile(file,
" Channel depth:\n");
786 (void) FormatLocaleFile(file,
" red: %.20g-bit\n",(
double)
787 channel_statistics[RedChannel].depth);
788 (void) FormatLocaleFile(file,
" green: %.20g-bit\n",(
double)
789 channel_statistics[GreenChannel].depth);
790 (void) FormatLocaleFile(file,
" blue: %.20g-bit\n",(
double)
791 channel_statistics[BlueChannel].depth);
796 (void) FormatLocaleFile(file,
" cyan: %.20g-bit\n",(
double)
797 channel_statistics[CyanChannel].depth);
798 (void) FormatLocaleFile(file,
" magenta: %.20g-bit\n",(
double)
799 channel_statistics[MagentaChannel].depth);
800 (void) FormatLocaleFile(file,
" yellow: %.20g-bit\n",(
double)
801 channel_statistics[YellowChannel].depth);
802 (void) FormatLocaleFile(file,
" black: %.20g-bit\n",(
double)
803 channel_statistics[BlackChannel].depth);
806 case LinearGRAYColorspace:
809 (void) FormatLocaleFile(file,
" gray: %.20g-bit\n",(
double)
810 channel_statistics[GrayChannel].depth);
814 if (image->matte != MagickFalse)
815 (void) FormatLocaleFile(file,
" alpha: %.20g-bit\n",(
double)
816 channel_statistics[OpacityChannel].depth);
818 if (image->depth <= MAGICKCORE_QUANTUM_DEPTH)
819 scale=(double) QuantumRange/((
size_t) QuantumRange >> ((size_t)
820 MAGICKCORE_QUANTUM_DEPTH-image->depth));
821 (void) FormatLocaleFile(file,
" Channel statistics:\n");
822 (void) FormatLocaleFile(file,
" Pixels: %.20g\n",(
double)
823 image->columns*image->rows);
829 (void) PrintChannelStatistics(file,RedChannel,
"Red",1.0/scale,
831 (void) PrintChannelStatistics(file,GreenChannel,
"Green",1.0/scale,
833 (void) PrintChannelStatistics(file,BlueChannel,
"Blue",1.0/scale,
839 (void) PrintChannelStatistics(file,CyanChannel,
"Cyan",1.0/scale,
841 (void) PrintChannelStatistics(file,MagentaChannel,
"Magenta",1.0/scale,
843 (void) PrintChannelStatistics(file,YellowChannel,
"Yellow",1.0/scale,
845 (void) PrintChannelStatistics(file,BlackChannel,
"Black",1.0/scale,
849 case LinearGRAYColorspace:
852 (void) PrintChannelStatistics(file,GrayChannel,
"Gray",1.0/scale,
857 if (image->matte != MagickFalse)
858 (void) PrintChannelStatistics(file,AlphaChannel,
"Alpha",1.0/scale,
860 if ((colorspace != LinearGRAYColorspace) && (colorspace != GRAYColorspace))
862 (void) FormatLocaleFile(file,
" Image statistics:\n");
863 (void) PrintChannelStatistics(file,CompositeChannels,
"Overall",1.0/
864 scale,channel_statistics);
871 scale=(double) ((1UL << image->depth)-1);
872 (void) FormatLocaleFile(file,
" Channel moments:\n");
878 (void) PrintChannelMoments(file,RedChannel,
"Red",scale,
880 (void) PrintChannelMoments(file,GreenChannel,
"Green",scale,
882 (void) PrintChannelMoments(file,BlueChannel,
"Blue",scale,
888 (void) PrintChannelMoments(file,CyanChannel,
"Cyan",scale,
890 (void) PrintChannelMoments(file,MagentaChannel,
"Magenta",scale,
892 (void) PrintChannelMoments(file,YellowChannel,
"Yellow",scale,
894 (void) PrintChannelMoments(file,BlackChannel,
"Black",scale,
898 case LinearGRAYColorspace:
901 (void) PrintChannelMoments(file,GrayChannel,
"Gray",scale,
906 if (image->matte != MagickFalse)
907 (void) PrintChannelMoments(file,AlphaChannel,
"Alpha",scale,
909 if ((colorspace != LinearGRAYColorspace) && (colorspace != GRAYColorspace))
911 (void) FormatLocaleFile(file,
" Image moments:\n");
912 (void) PrintChannelMoments(file,CompositeChannels,
"Overall",scale,
920 (void) FormatLocaleFile(file,
" Channel perceptual hash:\n");
921 (void) PrintChannelPerceptualHash(file,RedChannel,
"Red, Hue",
923 (void) PrintChannelPerceptualHash(file,GreenChannel,
"Green, Chroma",
925 (void) PrintChannelPerceptualHash(file,BlueChannel,
"Blue, Luma",
927 if (image->matte != MagickFalse)
928 (void) PrintChannelPerceptualHash(file,AlphaChannel,
"Alpha, Alpha",
935 (void) FormatLocaleFile(file,
" Channel features (horizontal, vertical, "
936 "left and right diagonals, average):\n");
942 (void) PrintChannelFeatures(file,RedChannel,
"Red",channel_features);
943 (void) PrintChannelFeatures(file,GreenChannel,
"Green",
945 (void) PrintChannelFeatures(file,BlueChannel,
"Blue",channel_features);
950 (void) PrintChannelFeatures(file,CyanChannel,
"Cyan",channel_features);
951 (void) PrintChannelFeatures(file,MagentaChannel,
"Magenta",
953 (void) PrintChannelFeatures(file,YellowChannel,
"Yellow",
955 (void) PrintChannelFeatures(file,BlackChannel,
"Black",
959 case LinearGRAYColorspace:
962 (void) PrintChannelFeatures(file,GrayChannel,
"Gray",channel_features);
966 if (image->matte != MagickFalse)
967 (void) PrintChannelFeatures(file,AlphaChannel,
"Alpha",channel_features);
971 if (ping == MagickFalse)
973 if (colorspace == CMYKColorspace)
974 (void) FormatLocaleFile(file,
" Total ink density: %.*g%%\n",
975 GetMagickPrecision(),100.0*GetImageTotalInkDensity(image)/(double)
978 if (image->matte != MagickFalse)
990 indexes=(IndexPacket *) NULL;
991 for (y=0; y < (ssize_t) image->rows; y++)
993 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
996 indexes=GetVirtualIndexQueue(image);
997 for (x=0; x < (ssize_t) image->columns; x++)
999 if (GetPixelOpacity(p) == (Quantum) TransparentOpacity)
1006 if (found != MagickFalse)
1009 if (found != MagickFalse)
1012 tuple[MaxTextExtent];
1017 GetMagickPixelPacket(image,&pixel);
1018 SetMagickPixelPacket(image,p,indexes+x,&pixel);
1019 (void) QueryMagickColorname(image,&pixel,SVGCompliance,tuple,
1021 (void) FormatLocaleFile(file,
" Alpha: %s ",tuple);
1022 GetColorTuple(&pixel,MagickTrue,tuple);
1023 (void) FormatLocaleFile(file,
" %s\n",tuple);
1026 artifact=GetImageArtifact(image,
"identify:unique-colors");
1027 if (IsHistogramImage(image,exception) != MagickFalse)
1029 (void) FormatLocaleFile(file,
" Colors: %.20g\n",(
double)
1030 GetNumberColors(image,(FILE *) NULL,exception));
1031 (void) FormatLocaleFile(file,
" Histogram:\n");
1032 (void) GetNumberColors(image,file,exception);
1035 if ((artifact != (
const char *) NULL) &&
1036 (IsMagickTrue(artifact) != MagickFalse))
1037 (void) FormatLocaleFile(file,
" Colors: %.20g\n",(
double)
1038 GetNumberColors(image,(FILE *) NULL,exception));
1040 if (image->storage_class == PseudoClass)
1042 (void) FormatLocaleFile(file,
" Colormap entries: %.20g\n",(
double)
1044 (void) FormatLocaleFile(file,
" Colormap:\n");
1045 if (image->colors <= 1024)
1048 color[MaxTextExtent],
1050 tuple[MaxTextExtent];
1058 GetMagickPixelPacket(image,&pixel);
1060 for (i=0; i < (ssize_t) image->colors; i++)
1062 SetMagickPixelPacket(image,p,(IndexPacket *) NULL,&pixel);
1063 (void) CopyMagickString(tuple,
"(",MaxTextExtent);
1064 ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
1065 (void) ConcatenateMagickString(tuple,
",",MaxTextExtent);
1066 ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
1067 (void) ConcatenateMagickString(tuple,
",",MaxTextExtent);
1068 ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
1069 if (pixel.colorspace == CMYKColorspace)
1071 (void) ConcatenateMagickString(tuple,
",",MaxTextExtent);
1072 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,
1075 if (pixel.matte != MagickFalse)
1077 (void) ConcatenateMagickString(tuple,
",",MaxTextExtent);
1078 ConcatenateColorComponent(&pixel,AlphaChannel,X11Compliance,
1081 (void) ConcatenateMagickString(tuple,
")",MaxTextExtent);
1082 (void) QueryMagickColorname(image,&pixel,SVGCompliance,color,
1084 GetColorTuple(&pixel,MagickTrue,hex);
1085 (void) FormatLocaleFile(file,
" %g: %s %s %s\n",(
double) i,tuple,
1091 if (image->error.mean_error_per_pixel != 0.0)
1092 (void) FormatLocaleFile(file,
" Mean error per pixel: %g\n",
1093 image->error.mean_error_per_pixel);
1094 if (image->error.normalized_mean_error != 0.0)
1095 (void) FormatLocaleFile(file,
" Normalized mean error: %g\n",
1096 image->error.normalized_mean_error);
1097 if (image->error.normalized_maximum_error != 0.0)
1098 (void) FormatLocaleFile(file,
" Normalized maximum error: %g\n",
1099 image->error.normalized_maximum_error);
1100 (void) FormatLocaleFile(file,
" Rendering intent: %s\n",
1101 CommandOptionToMnemonic(MagickIntentOptions,(ssize_t)
1102 image->rendering_intent));
1103 if (image->gamma != 0.0)
1104 (void) FormatLocaleFile(file,
" Gamma: %g\n",image->gamma);
1105 if ((image->chromaticity.red_primary.x != 0.0) ||
1106 (image->chromaticity.green_primary.x != 0.0) ||
1107 (image->chromaticity.blue_primary.x != 0.0) ||
1108 (image->chromaticity.white_point.x != 0.0))
1113 (void) FormatLocaleFile(file,
" Chromaticity:\n");
1114 (void) FormatLocaleFile(file,
" red primary: (%g,%g)\n",
1115 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y);
1116 (void) FormatLocaleFile(file,
" green primary: (%g,%g)\n",
1117 image->chromaticity.green_primary.x,
1118 image->chromaticity.green_primary.y);
1119 (void) FormatLocaleFile(file,
" blue primary: (%g,%g)\n",
1120 image->chromaticity.blue_primary.x,image->chromaticity.blue_primary.y);
1121 (void) FormatLocaleFile(file,
" white point: (%g,%g)\n",
1122 image->chromaticity.white_point.x,image->chromaticity.white_point.y);
1124 if ((image->extract_info.width*image->extract_info.height) != 0)
1125 (
void) FormatLocaleFile(file,
" Tile geometry: %.20gx%.20g%+.20g%+.20g\n",
1126 (
double) image->extract_info.width,(
double) image->extract_info.height,
1127 (
double) image->extract_info.x,(
double) image->extract_info.y);
1128 (void) QueryColorname(image,&image->background_color,SVGCompliance,color,
1130 (void) FormatLocaleFile(file,
" Background color: %s\n",color);
1131 (void) QueryColorname(image,&image->border_color,SVGCompliance,color,
1133 (void) FormatLocaleFile(file,
" Border color: %s\n",color);
1134 (void) QueryColorname(image,&image->matte_color,SVGCompliance,color,
1136 (void) FormatLocaleFile(file,
" Matte color: %s\n",color);
1137 (void) QueryColorname(image,&image->transparent_color,SVGCompliance,color,
1139 (void) FormatLocaleFile(file,
" Transparent color: %s\n",color);
1140 (void) FormatLocaleFile(file,
" Interlace: %s\n",CommandOptionToMnemonic(
1141 MagickInterlaceOptions,(ssize_t) image->interlace));
1142 (void) FormatLocaleFile(file,
" Intensity: %s\n",CommandOptionToMnemonic(
1143 MagickPixelIntensityOptions,(ssize_t) image->intensity));
1144 (void) FormatLocaleFile(file,
" Compose: %s\n",CommandOptionToMnemonic(
1145 MagickComposeOptions,(ssize_t) image->compose));
1146 if ((image->page.width != 0) || (image->page.height != 0) ||
1147 (image->page.x != 0) || (image->page.y != 0))
1148 (void) FormatLocaleFile(file,
" Page geometry: %.20gx%.20g%+.20g%+.20g\n",
1149 (
double) image->page.width,(double) image->page.height,(
double)
1150 image->page.x,(double) image->page.y);
1151 if ((image->page.x != 0) || (image->page.y != 0))
1152 (void) FormatLocaleFile(file,
" Origin geometry: %+.20g%+.20g\n",(
double)
1153 image->page.x,(double) image->page.y);
1154 (void) FormatLocaleFile(file,
" Dispose: %s\n",CommandOptionToMnemonic(
1155 MagickDisposeOptions,(ssize_t) image->dispose));
1156 if (image->delay != 0)
1157 (void) FormatLocaleFile(file,
" Delay: %.20gx%.20g\n",(
double) image->delay,
1158 (double) image->ticks_per_second);
1159 if (image->iterations != 1)
1160 (void) FormatLocaleFile(file,
" Iterations: %.20g\n",(
double)
1162 if (image->duration != 0)
1163 (void) FormatLocaleFile(file,
" Duration: %.20g\n",(
double)
1165 if ((image->next != (
Image *) NULL) || (image->previous != (
Image *) NULL))
1166 (void) FormatLocaleFile(file,
" Scene: %.20g of %.20g\n",(
double)
1167 image->scene,(double) GetImageListLength(image));
1169 if (image->scene != 0)
1170 (void) FormatLocaleFile(file,
" Scene: %.20g\n",(
double) image->scene);
1171 (void) FormatLocaleFile(file,
" Compression: %s\n",CommandOptionToMnemonic(
1172 MagickCompressOptions,(ssize_t) image->compression));
1173 if (image->quality != UndefinedCompressionQuality)
1174 (void) FormatLocaleFile(file,
" Quality: %.20g\n",(
double) image->quality);
1175 (void) FormatLocaleFile(file,
" Orientation: %s\n",CommandOptionToMnemonic(
1176 MagickOrientationOptions,(ssize_t) image->orientation));
1177 if (image->montage != (
char *) NULL)
1178 (
void) FormatLocaleFile(file,
" Montage: %s\n",image->montage);
1179 if (image->directory != (
char *) NULL)
1197 image_info=AcquireImageInfo();
1198 (void) CloneString(&image_info->size,
"64x64");
1199 (void) FormatLocaleFile(file,
" Directory:\n");
1200 for (p=image->directory; *p !=
'\0'; p++)
1203 while ((*q !=
'\xff') && (*q !=
'\0') &&
1204 ((
size_t) (q-p) <
sizeof(image_info->filename)))
1206 (void) CopyMagickString(image_info->filename,p,(
size_t) (q-p+1));
1208 (void) FormatLocaleFile(file,
" %s",image_info->filename);
1209 handler=SetWarningHandler((WarningHandler) NULL);
1210 tile=ReadImage(image_info,exception);
1211 (void) SetWarningHandler(handler);
1212 if (tile == (
Image *) NULL)
1214 (void) FormatLocaleFile(file,
"\n");
1217 (void) FormatLocaleFile(file,
" %.20gx%.20g %s\n",(
double)
1218 tile->magick_columns,(double) tile->magick_rows,tile->magick);
1219 (void) SignatureImage(tile);
1220 ResetImagePropertyIterator(tile);
1221 property=GetNextImageProperty(tile);
1222 while (property != (
const char *) NULL)
1224 (void) FormatLocaleFile(file,
" %s:\n",property);
1225 value=GetImageProperty(tile,property);
1226 if (value != (
const char *) NULL)
1227 (void) FormatLocaleFile(file,
"%s\n",value);
1228 property=GetNextImageProperty(tile);
1230 tile=DestroyImage(tile);
1232 image_info=DestroyImageInfo(image_info);
1234 (void) FormatLocaleString(key,MaxTextExtent,
"8BIM:1999,2998:#1");
1235 value=GetImageProperty(image,key);
1236 if (value != (
const char *) NULL)
1241 (void) FormatLocaleFile(file,
" Clipping path: ");
1242 if (strlen(value) > 80)
1243 (
void) fputc(
'\n',file);
1244 (void) FormatLocaleFile(file,
"%s\n",value);
1246 ResetImageProfileIterator(image);
1247 name=GetNextImageProfile(image);
1248 if (name != (
char *) NULL)
1256 (void) FormatLocaleFile(file,
" Profiles:\n");
1257 while (name != (
char *) NULL)
1259 profile=GetImageProfile(image,name);
1262 (void) FormatLocaleFile(file,
" Profile-%s: %.20g bytes\n",name,
1263 (
double) GetStringInfoLength(profile));
1264 if (LocaleCompare(name,
"iptc") == 0)
1285 profile_length=GetStringInfoLength(profile);
1286 for (i=0; i < (ssize_t) profile_length-5; i+=(ssize_t) length)
1289 sentinel=GetStringInfoDatum(profile)[i++];
1290 if (sentinel != 0x1c)
1292 dataset=GetStringInfoDatum(profile)[i++];
1293 record=GetStringInfoDatum(profile)[i++];
1296 case 5: tag=
"Image Name";
break;
1297 case 7: tag=
"Edit Status";
break;
1298 case 10: tag=
"Priority";
break;
1299 case 15: tag=
"Category";
break;
1300 case 20: tag=
"Supplemental Category";
break;
1301 case 22: tag=
"Fixture Identifier";
break;
1302 case 25: tag=
"Keyword";
break;
1303 case 30: tag=
"Release Date";
break;
1304 case 35: tag=
"Release Time";
break;
1305 case 40: tag=
"Special Instructions";
break;
1306 case 45: tag=
"Reference Service";
break;
1307 case 47: tag=
"Reference Date";
break;
1308 case 50: tag=
"Reference Number";
break;
1309 case 55: tag=
"Created Date";
break;
1310 case 60: tag=
"Created Time";
break;
1311 case 65: tag=
"Originating Program";
break;
1312 case 70: tag=
"Program Version";
break;
1313 case 75: tag=
"Object Cycle";
break;
1314 case 80: tag=
"Byline";
break;
1315 case 85: tag=
"Byline Title";
break;
1316 case 90: tag=
"City";
break;
1317 case 92: tag=
"Sub-Location";
break;
1318 case 95: tag=
"Province State";
break;
1319 case 100: tag=
"Country Code";
break;
1320 case 101: tag=
"Country";
break;
1321 case 103: tag=
"Original Transmission Reference";
break;
1322 case 105: tag=
"Headline";
break;
1323 case 110: tag=
"Credit";
break;
1324 case 115: tag=
"Src";
break;
1325 case 116: tag=
"Copyright String";
break;
1326 case 120: tag=
"Caption";
break;
1327 case 121: tag=
"Local Caption";
break;
1328 case 122: tag=
"Caption Writer";
break;
1329 case 200: tag=
"Custom Field 1";
break;
1330 case 201: tag=
"Custom Field 2";
break;
1331 case 202: tag=
"Custom Field 3";
break;
1332 case 203: tag=
"Custom Field 4";
break;
1333 case 204: tag=
"Custom Field 5";
break;
1334 case 205: tag=
"Custom Field 6";
break;
1335 case 206: tag=
"Custom Field 7";
break;
1336 case 207: tag=
"Custom Field 8";
break;
1337 case 208: tag=
"Custom Field 9";
break;
1338 case 209: tag=
"Custom Field 10";
break;
1339 case 210: tag=
"Custom Field 11";
break;
1340 case 211: tag=
"Custom Field 12";
break;
1341 case 212: tag=
"Custom Field 13";
break;
1342 case 213: tag=
"Custom Field 14";
break;
1343 case 214: tag=
"Custom Field 15";
break;
1344 case 215: tag=
"Custom Field 16";
break;
1345 case 216: tag=
"Custom Field 17";
break;
1346 case 217: tag=
"Custom Field 18";
break;
1347 case 218: tag=
"Custom Field 19";
break;
1348 case 219: tag=
"Custom Field 20";
break;
1349 default: tag=
"unknown";
break;
1351 (void) FormatLocaleFile(file,
" %s[%.20g,%.20g]: ",tag,
1352 (
double) dataset,(double) record);
1353 length=(size_t) (GetStringInfoDatum(profile)[i++] << 8);
1354 length|=GetStringInfoDatum(profile)[i++];
1355 length=MagickMin(length,profile_length-i);
1356 attribute=(
char *) NULL;
1357 if (~length >= (MaxTextExtent-1))
1358 attribute=(
char *) AcquireQuantumMemory(length+
1359 MaxTextExtent,
sizeof(*attribute));
1360 if (attribute != (
char *) NULL)
1362 (void) CopyMagickString(attribute,(
char *)
1363 GetStringInfoDatum(profile)+i,length+1);
1364 attribute_list=StringToList(attribute);
1365 if (attribute_list != (
char **) NULL)
1367 for (j=0; attribute_list[j] != (
char *) NULL; j++)
1369 (void) fputs(attribute_list[j],file);
1370 (void) fputs(
"\n",file);
1371 attribute_list[j]=(
char *) RelinquishMagickMemory(
1374 attribute_list=(
char **) RelinquishMagickMemory(
1377 attribute=DestroyString(attribute);
1381 if (image->debug != MagickFalse)
1382 PrintStringInfo(file,name,profile);
1383 name=GetNextImageProfile(image);
1386 ResetImagePropertyIterator(image);
1387 property=GetNextImageProperty(image);
1388 if (property != (
const char *) NULL)
1393 (void) FormatLocaleFile(file,
" Properties:\n");
1394 while (property != (
const char *) NULL)
1396 (void) FormatLocaleFile(file,
" %s: ",property);
1397 value=GetImageProperty(image,property);
1398 if (value != (
const char *) NULL)
1399 (void) FormatLocaleFile(file,
"%s\n",value);
1400 property=GetNextImageProperty(image);
1403 ResetImageArtifactIterator(image);
1404 artifact=GetNextImageArtifact(image);
1405 if (artifact != (
const char *) NULL)
1410 (void) FormatLocaleFile(file,
" Artifacts:\n");
1411 while (artifact != (
const char *) NULL)
1413 (void) FormatLocaleFile(file,
" %s: ",artifact);
1414 value=GetImageArtifact(image,artifact);
1415 if (value != (
const char *) NULL)
1416 (void) FormatLocaleFile(file,
"%s\n",value);
1417 artifact=GetNextImageArtifact(image);
1420 ResetImageRegistryIterator();
1421 registry=GetNextImageRegistry();
1422 if (registry != (
const char *) NULL)
1427 (void) FormatLocaleFile(file,
" Registry:\n");
1428 while (registry != (
const char *) NULL)
1430 (void) FormatLocaleFile(file,
" %s: ",registry);
1431 value=(
const char *) GetImageRegistry(StringRegistryType,registry,
1433 if (value != (
const char *) NULL)
1434 (
void) FormatLocaleFile(file,
"%s\n",value);
1435 registry=GetNextImageRegistry();
1438 (void) FormatLocaleFile(file,
" Tainted: %s\n",CommandOptionToMnemonic(
1439 MagickBooleanOptions,(ssize_t) image->taint));
1440 (void) FormatMagickSize(image->extent,MagickTrue,format);
1441 (void) FormatLocaleFile(file,
" Filesize: %s\n",format);
1442 (void) FormatMagickSize((MagickSizeType) image->columns*image->rows,
1443 MagickFalse,format);
1444 if (strlen(format) > 1)
1445 format[strlen(format)-1]=
'\0';
1446 (void) FormatLocaleFile(file,
" Number pixels: %s\n",format);
1447 if (elapsed_time > MagickEpsilon)
1449 (void) FormatMagickSize((MagickSizeType) ((double) image->columns*
1450 image->rows/elapsed_time+0.5),MagickFalse,format);
1451 (void) FormatLocaleFile(file,
" Pixels per second: %s\n",format);
1453 (void) FormatLocaleFile(file,
" User time: %0.3fu\n",user_time);
1454 (void) FormatLocaleFile(file,
" Elapsed time: %lu:%02lu.%03lu\n",
1455 (
unsigned long) (elapsed_time/60.0),(
unsigned long) ceil(fmod(
1456 elapsed_time,60.0)),(
unsigned long) (1000.0*(elapsed_time-floor(
1458 (void) FormatLocaleFile(file,
" Version: %s\n",GetMagickVersion((
size_t *)
1460 (void) fflush(file);
1461 return(ferror(file) != 0 ? MagickFalse : MagickTrue);