From: cristy Date: Fri, 18 Mar 2011 18:26:08 +0000 (+0000) Subject: (no commit message) X-Git-Tag: 7.0.1-0~7954 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0834d64fb1a6ccbff0f10cc57a647d7793381805;p=imagemagick --- diff --git a/magick/effect.c b/magick/effect.c index 92334cbfb..7fbcd8c1c 100644 --- a/magick/effect.c +++ b/magick/effect.c @@ -5453,6 +5453,211 @@ MagickExport Image *SpreadImage(const Image *image,const double radius, % % % % % % +% S t a t i s t i c I m a g e % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% StatisticImage() makes each pixel the min / max / median / mode / etc. of +% the neighborhood of the specified radius. +% +% The format of the StatisticImage method is: +% +% Image *StatisticImage(const Image *image,const StatisticType type, +% const double radius,ExceptionInfo *exception) +% Image *StatisticImageChannel(const Image *image, +% const ChannelType channel,const StatisticType type, +% const double radius,ExceptionInfo *exception) +% +% A description of each parameter follows: +% +% o image: the image. +% +% o channel: the image channel. +% +% o type: the statistic type (median, mode, etc.). +% +% o radius: the radius of the pixel neighborhood. +% +% o exception: return any errors or warnings in this structure. +% +*/ + +MagickExport Image *StatisticImage(const Image *image,const StatisticType type, + const double radius,ExceptionInfo *exception) +{ + return(StatisticImageChannel(image,DefaultChannels,type,radius,exception)); +} + +MagickExport Image *StatisticImageChannel(const Image *image, + const ChannelType channel,const StatisticType type,const double radius, + ExceptionInfo *exception) +{ +#define StatisticImageTag "Statistic/Image" + + CacheView + *image_view, + *statistic_view; + + Image + *statistic_image; + + MagickBooleanType + status; + + MagickOffsetType + progress; + + PixelList + **restrict pixel_list; + + size_t + width; + + ssize_t + y; + + /* + Initialize statistics image attributes. + */ + assert(image != (Image *) NULL); + assert(image->signature == MagickSignature); + if (image->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickSignature); + width=GetOptimalKernelWidth2D(radius,0.5); + statistic_image=CloneImage(image,image->columns,image->rows,MagickTrue, + exception); + if (statistic_image == (Image *) NULL) + return((Image *) NULL); + if (SetImageStorageClass(statistic_image,DirectClass) == MagickFalse) + { + InheritException(exception,&statistic_image->exception); + statistic_image=DestroyImage(statistic_image); + return((Image *) NULL); + } + pixel_list=AcquirePixelListThreadSet(width); + if (pixel_list == (PixelList **) NULL) + { + statistic_image=DestroyImage(statistic_image); + ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); + } + /* + Reduce statistics image. + */ + status=MagickTrue; + progress=0; + image_view=AcquireCacheView(image); + statistic_view=AcquireCacheView(statistic_image); +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp parallel for schedule(dynamic,4) shared(progress,status) +#endif + for (y=0; y < (ssize_t) statistic_image->rows; y++) + { + const int + id = GetOpenMPThreadId(); + + register const IndexPacket + *restrict indexes; + + register const PixelPacket + *restrict p; + + register IndexPacket + *restrict statistic_indexes; + + register PixelPacket + *restrict q; + + register ssize_t + x; + + if (status == MagickFalse) + continue; + p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t) + (width/2L),image->columns+width,width,exception); + q=QueueCacheViewAuthenticPixels(statistic_view,0,y, + statistic_image->columns,1,exception); + if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL)) + { + status=MagickFalse; + continue; + } + indexes=GetCacheViewVirtualIndexQueue(image_view); + statistic_indexes=GetCacheViewAuthenticIndexQueue(statistic_view); + for (x=0; x < (ssize_t) statistic_image->columns; x++) + { + MagickPixelPacket + pixel; + + register const PixelPacket + *restrict r; + + register const IndexPacket + *restrict s; + + register ssize_t + u, + v; + + r=p; + s=indexes+x; + ResetPixelList(pixel_list[id]); + for (v=0; v < (ssize_t) width; v++) + { + for (u=0; u < (ssize_t) width; u++) + InsertPixelList(image,r+u,s+u,pixel_list[id]); + r+=image->columns+width; + s+=image->columns+width; + } + switch (type) + { + case ModeStatistic: pixel=GetModePixelList(pixel_list[id]); + default: break; + } + if ((channel & RedChannel) != 0) + q->red=ClampToQuantum(pixel.red); + if ((channel & GreenChannel) != 0) + q->green=ClampToQuantum(pixel.green); + if ((channel & BlueChannel) != 0) + q->blue=ClampToQuantum(pixel.blue); + if ((image->matte != MagickFalse) && ((channel & OpacityChannel) != 0)) + q->opacity=ClampToQuantum(pixel.opacity); + if (((channel & IndexChannel) != 0) && + (image->colorspace == CMYKColorspace)) + statistic_indexes[x]=(IndexPacket) ClampToQuantum(pixel.index); + p++; + q++; + } + if (SyncCacheViewAuthenticPixels(statistic_view,exception) == MagickFalse) + status=MagickFalse; + if (image->progress_monitor != (MagickProgressMonitor) NULL) + { + MagickBooleanType + proceed; + +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp critical (MagickCore_StatisticImage) +#endif + proceed=SetImageProgress(image,StatisticImageTag,progress++, + image->rows); + if (proceed == MagickFalse) + status=MagickFalse; + } + } + statistic_view=DestroyCacheView(statistic_view); + image_view=DestroyCacheView(image_view); + pixel_list=DestroyPixelListThreadSet(pixel_list); + return(statistic_image); +} + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % % U n s h a r p M a s k I m a g e % % % % % diff --git a/magick/effect.h b/magick/effect.h index 0bd50e3f9..9643d588e 100644 --- a/magick/effect.h +++ b/magick/effect.h @@ -58,6 +58,16 @@ typedef enum JPEGPreview } PreviewType; +typedef enum +{ + UndefinedStatistic, + MaximumStatistic, + MedianStatistic, + MinimumStatistic, + ModeStatistic, + ReduceNoiseStatistic +} StatisticType; + extern MagickExport Image *AdaptiveBlurImage(const Image *,const double,const double,ExceptionInfo *), *AdaptiveBlurImageChannel(const Image *,const ChannelType,const double, @@ -102,6 +112,9 @@ extern MagickExport Image *SharpenImageChannel(const Image *,const ChannelType,const double, const double,ExceptionInfo *), *SpreadImage(const Image *,const double,ExceptionInfo *), + *StatisticImage(const Image *,const StatisticType,const double,ExceptionInfo *), + *StatisticImageChannel(const Image *,const ChannelType,const StatisticType, + const double,ExceptionInfo *), *UnsharpMaskImage(const Image *,const double,const double,const double, const double,ExceptionInfo *), *UnsharpMaskImageChannel(const Image *,const ChannelType,const double, diff --git a/magick/option.c b/magick/option.c index 81ef7cd86..cd96dff26 100644 --- a/magick/option.c +++ b/magick/option.c @@ -597,6 +597,8 @@ static const OptionInfo { "-sparse-color", 2L, MagickFalse }, { "+spread", 0L, MagickFalse }, { "-spread", 1L, MagickFalse }, + { "+statistic", 2L, MagickFalse }, + { "-statistic", 2L, MagickFalse }, { "+stegano", 0L, MagickFalse }, { "-stegano", 1L, MagickFalse }, { "+stereo", 0L, MagickFalse }, @@ -1442,6 +1444,15 @@ static const OptionInfo { "Voronoi", (ssize_t) VoronoiColorInterpolate, MagickFalse }, { (char *) NULL, (ssize_t) UndefinedResource, MagickFalse } }, + StatisticOptions[] = + { + { "Undefined", (ssize_t) UndefinedStatistic, MagickTrue }, + { "Maximum", (ssize_t) MaximumStatistic, MagickFalse }, + { "Median", (ssize_t) MedianStatistic, MagickFalse }, + { "Minimum", (ssize_t) MinimumStatistic, MagickFalse }, + { "Mode", (ssize_t) ModeStatistic, MagickFalse }, + { (char *) NULL, (ssize_t) UndefinedMethod, MagickFalse } + }, StorageOptions[] = { { "Undefined", (ssize_t) UndefinedPixel, MagickTrue }, @@ -1809,6 +1820,7 @@ static const OptionInfo *GetOptionInfo(const MagickOption option) case MagickResolutionOptions: return(ResolutionOptions); case MagickResourceOptions: return(ResourceOptions); case MagickSparseColorOptions: return(SparseColorOptions); + case MagickStatisticOptions: return(StatisticOptions); case MagickStorageOptions: return(StorageOptions); case MagickStretchOptions: return(StretchOptions); case MagickStyleOptions: return(StyleOptions); diff --git a/magick/option.h b/magick/option.h index 3e05183f5..d9dff4962 100644 --- a/magick/option.h +++ b/magick/option.h @@ -85,6 +85,7 @@ typedef enum MagickResolutionOptions, MagickResourceOptions, MagickSparseColorOptions, + MagickStatisticOptions, MagickStorageOptions, MagickStretchOptions, MagickStyleOptions, diff --git a/utilities/convert.1.in b/utilities/convert.1.in index 42dfeed57..045b8c304 100644 --- a/utilities/convert.1.in +++ b/utilities/convert.1.in @@ -76,6 +76,8 @@ Image Settings: \-scene value image scene number \-seed value seed a new sequence of pseudo-random numbers \-size geometry width and height of image + \-statistic type radius + replace each pixel with corresponding statistic from the neighborhood \-stretch type render text with this font stretch \-stroke color graphic primitive stroke color \-strokewidth value graphic primitive stroke width diff --git a/utilities/mogrify.1.in b/utilities/mogrify.1.in index 571267c01..cbdba4d08 100644 --- a/utilities/mogrify.1.in +++ b/utilities/mogrify.1.in @@ -206,6 +206,8 @@ Image Operators: \-solarize threshold negate all pixels above the threshold level \-splice geometry splice the background color into the image \-spread amount displace image pixels by a random amount + \-statistic type radius + replace each pixel with corresponding statistic from the neighborhood \-strip strip image of all profiles and comments \-swirl degrees swirl image pixels about the center \-threshold value threshold the image diff --git a/wand/convert.c b/wand/convert.c index df3ad1ad7..32f68152e 100644 --- a/wand/convert.c +++ b/wand/convert.c @@ -269,6 +269,8 @@ static MagickBooleanType ConvertUsage(void) " fill in a image based on a few color points", "-splice geometry splice the background color into the image", "-spread radius displace image pixels by a random amount", + "-statistic type radius", + " replace each pixel with corresponding statistic from the neighborhood", "-strip strip image of all profiles and comments", "-swirl degrees swirl image pixels about the center", "-threshold value threshold the image", @@ -2605,6 +2607,27 @@ WandExport MagickBooleanType ConvertImageCommand(ImageInfo *image_info, ThrowConvertException(OptionError,"MissingArgument",option); break; } + if (LocaleCompare("statistic",option+1) == 0) + { + ssize_t + op; + + if (*option == '+') + break; + i++; + if (i == (ssize_t) argc) + ThrowConvertException(OptionError,"MissingArgument",option); + op=ParseMagickOption(MagickStatisticOptions,MagickFalse,argv[i]); + if (op < 0) + ThrowConvertException(OptionError,"UnrecognizedStatisticType", + argv[i]); + i++; + if (i == (ssize_t) (argc-1)) + ThrowConvertException(OptionError,"MissingArgument",option); + if (IsGeometry(argv[i]) == MagickFalse) + ThrowConvertInvalidArgumentException(option,argv[i]); + break; + } if (LocaleCompare("stretch",option+1) == 0) { ssize_t diff --git a/wand/mogrify.c b/wand/mogrify.c index 8d592d103..40d037d68 100644 --- a/wand/mogrify.c +++ b/wand/mogrify.c @@ -3156,6 +3156,26 @@ WandExport MagickBooleanType MogrifyImage(ImageInfo *image_info,const int argc, *image=spread_image; break; } + if (LocaleCompare("statistic",option+1) == 0) + { + Image + *statistic_image; + + StatisticType + type; + + (void) SyncImageSettings(mogrify_info,*image); + type=(StatisticType) ParseMagickOption(MagickStatisticOptions, + MagickFalse,argv[i+1]); + (void) ParseGeometry(argv[i+2],&geometry_info); + statistic_image=StatisticImageChannel(*image,channel,type, + geometry_info.rho,exception); + if (statistic_image == (Image *) NULL) + break; + *image=DestroyImage(*image); + *image=statistic_image; + break; + } if (LocaleCompare("stretch",option+1) == 0) { if (*option == '+') @@ -3765,6 +3785,8 @@ static MagickBooleanType MogrifyUsage(void) " fill in a image based on a few color points", "-splice geometry splice the background color into the image", "-spread radius displace image pixels by a random amount", + "-statistic type radius", + " replace each pixel with corresponding statistic from the neighborhood", "-strip strip image of all profiles and comments", "-swirl degrees swirl image pixels about the center", "-threshold value threshold the image", @@ -6046,6 +6068,27 @@ WandExport MagickBooleanType MogrifyImageCommand(ImageInfo *image_info, ThrowMogrifyInvalidArgumentException(option,argv[i]); break; } + if (LocaleCompare("statistic",option+1) == 0) + { + ssize_t + op; + + if (*option == '+') + break; + i++; + if (i == (ssize_t) argc) + ThrowMogrifyException(OptionError,"MissingArgument",option); + op=ParseMagickOption(MagickStatisticOptions,MagickFalse,argv[i]); + if (op < 0) + ThrowMogrifyException(OptionError,"UnrecognizedStatisticType", + argv[i]); + i++; + if (i == (ssize_t) (argc-1)) + ThrowMogrifyException(OptionError,"MissingArgument",option); + if (IsGeometry(argv[i]) == MagickFalse) + ThrowMogrifyInvalidArgumentException(option,argv[i]); + break; + } if (LocaleCompare("stretch",option+1) == 0) { ssize_t