From: cristy Date: Tue, 7 Jan 2014 15:09:37 +0000 (+0000) Subject: (no commit message) X-Git-Tag: 7.0.1-0~2953 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bd4a3c228c0e785517b8ab630b2cc6095373f710;p=imagemagick --- diff --git a/MagickCore/identify.c b/MagickCore/identify.c index 3e9f9f11d..9b834b424 100644 --- a/MagickCore/identify.c +++ b/MagickCore/identify.c @@ -368,6 +368,32 @@ static ssize_t PrintChannelLocations(FILE *file,const Image *image, return(n); } +static ssize_t PrintChannelMoments(FILE *file,const PixelChannel channel, + const char *name,const ChannelMoments *channel_moments) +{ + ssize_t + n; + + n=FormatLocaleFile(file,"%s:\n",name); + n+=FormatLocaleFile(file," i1: %.*g",GetMagickPrecision(), + channel_moments[channel].I1); + n+=FormatLocaleFile(file," i2: %.*g",GetMagickPrecision(), + channel_moments[channel].I2); + n+=FormatLocaleFile(file," i3: %.*g",GetMagickPrecision(), + channel_moments[channel].I3); + n+=FormatLocaleFile(file," i4: %.*g",GetMagickPrecision(), + channel_moments[channel].I4); + n+=FormatLocaleFile(file," i5: %.*g",GetMagickPrecision(), + channel_moments[channel].I5); + n+=FormatLocaleFile(file," i6: %.*g",GetMagickPrecision(), + channel_moments[channel].I6); + n+=FormatLocaleFile(file," i7: %.*g",GetMagickPrecision(), + channel_moments[channel].I7); + n+=FormatLocaleFile(file," i8: %.*g",GetMagickPrecision(), + channel_moments[channel].I8); + return(n); +} + static ssize_t PrintChannelStatistics(FILE *file,const PixelChannel channel, const char *name,const double scale, const ChannelStatistics *channel_statistics) @@ -403,6 +429,9 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file, ChannelFeatures *channel_features; + ChannelMoments + *channel_moments; + ChannelStatistics *channel_statistics; @@ -650,6 +679,7 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file, (void) FormatLocaleFile(file," Colorspace: %s\n",CommandOptionToMnemonic( MagickColorspaceOptions,(ssize_t) image->colorspace)); channel_statistics=(ChannelStatistics *) NULL; + channel_moments=(ChannelMoments *) NULL; channel_features=(ChannelFeatures *) NULL; colorspace=image->colorspace; scale=1; @@ -661,6 +691,9 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file, channel_statistics=GetImageStatistics(image,exception); if (channel_statistics == (ChannelStatistics *) NULL) return(MagickFalse); + artifact=GetImageArtifact(image,"identify:moments"); + if (artifact != (const char *) NULL) + channel_moments=GetImageMoments(image,exception); artifact=GetImageArtifact(image,"identify:features"); if (artifact != (const char *) NULL) { @@ -766,6 +799,47 @@ MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file, channel_statistics=(ChannelStatistics *) RelinquishMagickMemory( channel_statistics); } + if (channel_moments != (ChannelMoments *) NULL) + { + (void) FormatLocaleFile(file," Channel moments\n"); + switch (colorspace) + { + case RGBColorspace: + default: + { + (void) PrintChannelMoments(file,RedPixelChannel,"Red", + channel_moments); + (void) PrintChannelMoments(file,GreenPixelChannel,"Green", + channel_moments); + (void) PrintChannelMoments(file,BluePixelChannel,"Blue", + channel_moments); + break; + } + case CMYKColorspace: + { + (void) PrintChannelMoments(file,CyanPixelChannel,"Cyan", + channel_moments); + (void) PrintChannelMoments(file,MagentaPixelChannel,"Magenta", + channel_moments); + (void) PrintChannelMoments(file,YellowPixelChannel,"Yellow", + channel_moments); + (void) PrintChannelMoments(file,BlackPixelChannel,"Black", + channel_moments); + break; + } + case GRAYColorspace: + { + (void) PrintChannelMoments(file,GrayPixelChannel,"Gray", + channel_moments); + break; + } + } + if (image->alpha_trait == BlendPixelTrait) + (void) PrintChannelMoments(file,AlphaPixelChannel,"Alpha", + channel_moments); + channel_moments=(ChannelMoments *) RelinquishMagickMemory( + channel_moments); + } if (channel_features != (ChannelFeatures *) NULL) { (void) FormatLocaleFile(file," Channel features (horizontal, vertical, " diff --git a/MagickCore/option.c b/MagickCore/option.c index a6de8a8af..94915a331 100644 --- a/MagickCore/option.c +++ b/MagickCore/option.c @@ -509,6 +509,8 @@ static const OptionInfo { "-metric", 1L, ListOperatorFlag | FireOptionFlag, MagickFalse }, { "+minimum", 0L, DeprecateOptionFlag | FireOptionFlag, MagickTrue }, { "-minimum", 0L, DeprecateOptionFlag | FireOptionFlag, MagickTrue }, + { "+moments", 0L, SimpleOperatorFlag | FireOptionFlag, MagickFalse }, + { "-moments", 0L, SimpleOperatorFlag | FireOptionFlag, MagickFalse }, { "+mode", 1L, NonMagickOptionFlag, MagickFalse }, { "-mode", 1L, ReplacedOptionFlag | SimpleOperatorFlag, MagickTrue }, { "+modulate", 1L, DeprecateOptionFlag, MagickTrue }, diff --git a/MagickCore/statistic.c b/MagickCore/statistic.c index 5099b03b1..017b4f631 100644 --- a/MagickCore/statistic.c +++ b/MagickCore/statistic.c @@ -1127,6 +1127,144 @@ MagickExport MagickBooleanType GetImageExtrema(const Image *image, % % % % % % +% G e t I m a g e K u r t o s i s % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% GetImageKurtosis() returns the kurtosis and skewness of one or more image +% channels. +% +% The format of the GetImageKurtosis method is: +% +% MagickBooleanType GetImageKurtosis(const Image *image,double *kurtosis, +% double *skewness,ExceptionInfo *exception) +% +% A description of each parameter follows: +% +% o image: the image. +% +% o kurtosis: the kurtosis of the channel. +% +% o skewness: the skewness of the channel. +% +% o exception: return any errors or warnings in this structure. +% +*/ +MagickExport MagickBooleanType GetImageKurtosis(const Image *image, + double *kurtosis,double *skewness,ExceptionInfo *exception) +{ + CacheView + *image_view; + + double + area, + mean, + standard_deviation, + sum_squares, + sum_cubes, + sum_fourth_power; + + MagickBooleanType + status; + + ssize_t + y; + + assert(image != (Image *) NULL); + assert(image->signature == MagickSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + status=MagickTrue; + *kurtosis=0.0; + *skewness=0.0; + area=0.0; + mean=0.0; + standard_deviation=0.0; + sum_squares=0.0; + sum_cubes=0.0; + sum_fourth_power=0.0; + image_view=AcquireVirtualCacheView(image,exception); +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp parallel for schedule(static,4) shared(status) \ + magick_threads(image,image,image->rows,1) +#endif + for (y=0; y < (ssize_t) image->rows; y++) + { + register const Quantum + *restrict p; + + register ssize_t + x; + + if (status == MagickFalse) + continue; + p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception); + if (p == (const Quantum *) NULL) + { + status=MagickFalse; + continue; + } + for (x=0; x < (ssize_t) image->columns; x++) + { + register ssize_t + i; + + if (GetPixelReadMask(image,p) == 0) + { + p+=GetPixelChannels(image); + continue; + } + for (i=0; i < (ssize_t) GetPixelChannels(image); i++) + { + PixelChannel channel=GetPixelChannelChannel(image,i); + PixelTrait traits=GetPixelChannelTraits(image,channel); + if (traits == UndefinedPixelTrait) + continue; + if ((traits & UpdatePixelTrait) == 0) + continue; +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp critical (MagickCore_GetImageKurtosis) +#endif + { + mean+=p[i]; + sum_squares+=(double) p[i]*p[i]; + sum_cubes+=(double) p[i]*p[i]*p[i]; + sum_fourth_power+=(double) p[i]*p[i]*p[i]*p[i]; + area++; + } + } + p+=GetPixelChannels(image); + } + } + image_view=DestroyCacheView(image_view); + if (area != 0.0) + { + mean/=area; + sum_squares/=area; + sum_cubes/=area; + sum_fourth_power/=area; + } + standard_deviation=sqrt(sum_squares-(mean*mean)); + if (standard_deviation != 0.0) + { + *kurtosis=sum_fourth_power-4.0*mean*sum_cubes+6.0*mean*mean*sum_squares- + 3.0*mean*mean*mean*mean; + *kurtosis/=standard_deviation*standard_deviation*standard_deviation* + standard_deviation; + *kurtosis-=3.0; + *skewness=sum_cubes-3.0*mean*sum_squares+2.0*mean*mean*mean; + *skewness/=standard_deviation*standard_deviation*standard_deviation; + } + return(status); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % % G e t I m a g e M e a n % % % % % @@ -1204,48 +1342,44 @@ MagickExport MagickBooleanType GetImageMean(const Image *image,double *mean, % % % % % % -% G e t I m a g e K u r t o s i s % +% G e t I m a g e M o m e n t s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% GetImageKurtosis() returns the kurtosis and skewness of one or more image -% channels. +% GetImageMoments() returns the moments of one or more image channels. % -% The format of the GetImageKurtosis method is: +% The format of the GetImageMoments method is: % -% MagickBooleanType GetImageKurtosis(const Image *image,double *kurtosis, -% double *skewness,ExceptionInfo *exception) +% ChannelMoments *GetImageMoments(const Image *image, +% ExceptionInfo *exception) % % A description of each parameter follows: % % o image: the image. % -% o kurtosis: the kurtosis of the channel. -% -% o skewness: the skewness of the channel. -% % o exception: return any errors or warnings in this structure. % */ -MagickExport MagickBooleanType GetImageKurtosis(const Image *image, - double *kurtosis,double *skewness,ExceptionInfo *exception) +MagickExport ChannelMoments *GetImageMoments(const Image *image, + ExceptionInfo *exception) { +#define MaxNumberImageMoments 8 + CacheView *image_view; - double - area, - mean, - standard_deviation, - sum_squares, - sum_cubes, - sum_fourth_power; + ChannelMoments + *channel_moments; MagickBooleanType + initialize, status; + register ssize_t + i; + ssize_t y; @@ -1253,18 +1387,27 @@ MagickExport MagickBooleanType GetImageKurtosis(const Image *image, assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + channel_moments=(ChannelMoments *) AcquireQuantumMemory(MaxPixelChannels+1, + sizeof(*channel_moments)); + if (channel_moments == (ChannelMoments *) NULL) + return(channel_moments); + (void) ResetMagickMemory(channel_moments,0,length*sizeof(*channel_moments)); + for (i=0; i <= (ssize_t) MaxPixelChannels; i++) + { + channel_moments[i].I1=0.0; + channel_moments[i].I2=0.0; + channel_moments[i].I3=0.0; + channel_moments[i].I4=0.0; + channel_moments[i].I5=0.0; + channel_moments[i].I6=0.0; + channel_moments[i].I7=0.0; + channel_moments[i].I8=0.0; + } status=MagickTrue; - *kurtosis=0.0; - *skewness=0.0; - area=0.0; - mean=0.0; - standard_deviation=0.0; - sum_squares=0.0; - sum_cubes=0.0; - sum_fourth_power=0.0; + initialize=MagickTrue; image_view=AcquireVirtualCacheView(image,exception); #if defined(MAGICKCORE_OPENMP_SUPPORT) - #pragma omp parallel for schedule(static,4) shared(status) \ + #pragma omp parallel for schedule(static,4) shared(status,initialize) \ magick_threads(image,image,image->rows,1) #endif for (y=0; y < (ssize_t) image->rows; y++) @@ -1302,39 +1445,25 @@ MagickExport MagickBooleanType GetImageKurtosis(const Image *image, if ((traits & UpdatePixelTrait) == 0) continue; #if defined(MAGICKCORE_OPENMP_SUPPORT) - #pragma omp critical (MagickCore_GetImageKurtosis) + #pragma omp critical (MagickCore_GetImageMoments) #endif { - mean+=p[i]; - sum_squares+=(double) p[i]*p[i]; - sum_cubes+=(double) p[i]*p[i]*p[i]; - sum_fourth_power+=(double) p[i]*p[i]*p[i]*p[i]; - area++; + if (initialize != MagickFalse) + { + initialize=MagickFalse; + } + else + { + } } } p+=GetPixelChannels(image); } } image_view=DestroyCacheView(image_view); - if (area != 0.0) - { - mean/=area; - sum_squares/=area; - sum_cubes/=area; - sum_fourth_power/=area; - } - standard_deviation=sqrt(sum_squares-(mean*mean)); - if (standard_deviation != 0.0) - { - *kurtosis=sum_fourth_power-4.0*mean*sum_cubes+6.0*mean*mean*sum_squares- - 3.0*mean*mean*mean*mean; - *kurtosis/=standard_deviation*standard_deviation*standard_deviation* - standard_deviation; - *kurtosis-=3.0; - *skewness=sum_cubes-3.0*mean*sum_squares+2.0*mean*mean*mean; - *skewness/=standard_deviation*standard_deviation*standard_deviation; - } - return(status); + if (status == MagickFalse) + channel_moments=(ChannelMoments *) RelinquishMagickMemory(channel_moments); + return(channel_moments); } /* diff --git a/MagickCore/statistic.h b/MagickCore/statistic.h index 6df0cbdb4..ab06b366c 100644 --- a/MagickCore/statistic.h +++ b/MagickCore/statistic.h @@ -42,6 +42,19 @@ typedef struct _ChannelStatistics skewness; } ChannelStatistics; +typedef struct _ChannelMoments +{ + double + I1, + I2, + I3, + I4, + I5, + I6, + I7, + I8; +} ChannelMoments; + typedef enum { UndefinedEvaluateOperator, @@ -103,6 +116,9 @@ typedef enum extern MagickExport ChannelStatistics *GetImageStatistics(const Image *,ExceptionInfo *); +extern MagickExport ChannelMoments + *GetImageMoments(const Image *,ExceptionInfo *); + extern MagickExport Image *EvaluateImages(const Image *,const MagickEvaluateOperator,ExceptionInfo *), *PolynomialImage(const Image *,const size_t,const double *,ExceptionInfo *), diff --git a/MagickWand/identify.c b/MagickWand/identify.c index 29797ddd5..1d53822a3 100644 --- a/MagickWand/identify.c +++ b/MagickWand/identify.c @@ -139,6 +139,7 @@ static MagickBooleanType IdentifyUsage(void) "-limit type value pixel cache resource limit", "-mask filename associate a mask with the image", "-matte store matte channel if the image has one", + "-moments report image moments", "-monitor monitor progress", "-ping efficiently determine image attributes", "-precision value maximum number of significant digits to print", diff --git a/MagickWand/mogrify.c b/MagickWand/mogrify.c index 7f984f8aa..0824eb0fa 100644 --- a/MagickWand/mogrify.c +++ b/MagickWand/mogrify.c @@ -2091,6 +2091,16 @@ WandExport MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc, (void) ModulateImage(*image,argv[i+1],exception); break; } + if (LocaleCompare("moments",option+1) == 0) + { + if (*option == '+') + { + (void) DeleteImageArtifact(*image,"identify:moments"); + break; + } + (void) SetImageArtifact(*image,"identify:moments",argv[i+1]); + break; + } if (LocaleCompare("monitor",option+1) == 0) { if (*option == '+') diff --git a/MagickWand/operation.c b/MagickWand/operation.c index 2037de631..90518de65 100644 --- a/MagickWand/operation.c +++ b/MagickWand/operation.c @@ -1112,6 +1112,14 @@ WandPrivate void CLISettingOptionInfo(MagickCLI *cli_wand, (void) SetImageOption(_image_info,option+1,ArgOption(NULL)); break; } + if (LocaleCompare("moments",option+1) == 0) + { + (void) SetImageOption(_image_info,"identify:moments", + ArgBooleanString); + if (IfSetOption) + (void) SetImageArtifact(_image,"verbose","true"); + break; + } if (LocaleCompare("monitor",option+1) == 0) { (void) SetImageInfoProgressMonitor(_image_info, IfSetOption? diff --git a/utilities/identify.1.in b/utilities/identify.1.in index 2f531fbf2..6aba2ef67 100644 --- a/utilities/identify.1.in +++ b/utilities/identify.1.in @@ -38,6 +38,7 @@ Image Settings: Resource, or Type \-mask filename associate a mask with the image \-matte store matte channel if the image has one + \-moments report image moments \-monitor monitor progress \-ping efficiently determine image attributes \-precision value maximum number of significant digits to print