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,%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);
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,
1145 (void) FormatLocaleFile(file,
" Background color: %s\n",color);
1146 (void) QueryColorname(image,&image->border_color,SVGCompliance,color,
1148 (void) FormatLocaleFile(file,
" Border color: %s\n",color);
1149 (void) QueryColorname(image,&image->matte_color,SVGCompliance,color,
1151 (void) FormatLocaleFile(file,
" Matte color: %s\n",color);
1152 (void) QueryColorname(image,&image->transparent_color,SVGCompliance,color,
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)
1177 if (image->duration != 0)
1178 (void) FormatLocaleFile(file,
" Duration: %.20g\n",(
double)
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));
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)
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++)
1218 while ((*q !=
'\xff') && (*q !=
'\0') &&
1219 ((
size_t) (q-p) <
sizeof(image_info->filename)))
1221 (void) CopyMagickString(image_info->filename,p,(
size_t) (q-p+1));
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)
1229 (void) FormatLocaleFile(file,
"\n");
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)
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);
1245 tile=DestroyImage(tile);
1247 image_info=DestroyImageInfo(image_info);
1249 (void) FormatLocaleString(key,MaxTextExtent,
"8BIM:1999,2998:#1");
1250 value=GetImageProperty(image,key);
1251 if (value != (
const char *) NULL)
1256 (void) FormatLocaleFile(file,
" Clipping path: ");
1257 if (strlen(value) > 80)
1258 (
void) fputc(
'\n',file);
1259 (void) FormatLocaleFile(file,
"%s\n",value);
1261 ResetImageProfileIterator(image);
1262 name=GetNextImageProfile(image);
1263 if (name != (
char *) NULL)
1271 (void) FormatLocaleFile(file,
" Profiles:\n");
1272 while (name != (
char *) NULL)
1274 profile=GetImageProfile(image,name);
1277 (void) FormatLocaleFile(file,
" Profile-%s: %.20g bytes\n",name,
1278 (
double) GetStringInfoLength(profile));
1279 if (LocaleCompare(name,
"iptc") == 0)
1300 profile_length=GetStringInfoLength(profile);
1301 for (i=0; i < (ssize_t) profile_length-5; i+=(ssize_t) length)
1304 sentinel=GetStringInfoDatum(profile)[i++];
1305 if (sentinel != 0x1c)
1307 dataset=GetStringInfoDatum(profile)[i++];
1308 record=GetStringInfoDatum(profile)[i++];
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;
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)
1377 (void) CopyMagickString(attribute,(
char *)
1378 GetStringInfoDatum(profile)+i,length+1);
1379 attribute_list=StringToList(attribute);
1380 if (attribute_list != (
char **) NULL)
1382 for (j=0; attribute_list[j] != (
char *) NULL; j++)
1384 (void) fputs(attribute_list[j],file);
1385 (void) fputs(
"\n",file);
1386 attribute_list[j]=(
char *) RelinquishMagickMemory(
1389 attribute_list=(
char **) RelinquishMagickMemory(
1392 attribute=DestroyString(attribute);
1396 if (image->debug != MagickFalse)
1397 PrintStringInfo(file,name,profile);
1398 name=GetNextImageProfile(image);
1401 ResetImagePropertyIterator(image);
1402 property=GetNextImageProperty(image);
1403 if (property != (
const char *) NULL)
1408 (void) FormatLocaleFile(file,
" Properties:\n");
1409 while (property != (
const char *) NULL)
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);
1418 ResetImageArtifactIterator(image);
1419 artifact=GetNextImageArtifact(image);
1420 if (artifact != (
const char *) NULL)
1425 (void) FormatLocaleFile(file,
" Artifacts:\n");
1426 while (artifact != (
const char *) NULL)
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);
1435 ResetImageRegistryIterator();
1436 registry=GetNextImageRegistry();
1437 if (registry != (
const char *) NULL)
1442 (void) FormatLocaleFile(file,
" Registry:\n");
1443 while (registry != (
const char *) NULL)
1445 (void) FormatLocaleFile(file,
" %s: ",registry);
1446 value=(
const char *) GetImageRegistry(StringRegistryType,registry,
1448 if (value != (
const char *) NULL)
1449 (
void) FormatLocaleFile(file,
"%s\n",value);
1450 registry=GetNextImageRegistry();
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)
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);
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(
1473 (void) FormatLocaleFile(file,
" Version: %s\n",GetMagickVersion((
size_t *)
1475 (void) fflush(file);
1476 return(ferror(file) != 0 ? MagickFalse : MagickTrue);