From 41f5fe9f39b5f0d7d8be74eaed6e5358888c6f1b Mon Sep 17 00:00:00 2001 From: cristy Date: Sun, 11 Nov 2012 23:21:51 +0000 Subject: [PATCH] --- MagickCore/statistic.c | 230 +++++++++++++++++++++++++++++++++++------ 1 file changed, 199 insertions(+), 31 deletions(-) diff --git a/MagickCore/statistic.c b/MagickCore/statistic.c index 6ff118d24..d0ecc256e 100644 --- a/MagickCore/statistic.c +++ b/MagickCore/statistic.c @@ -428,9 +428,6 @@ MagickExport Image *EvaluateImages(const Image *images, CacheView *evaluate_view; - const Image - *next; - Image *image; @@ -457,25 +454,12 @@ MagickExport Image *EvaluateImages(const Image *images, key; #endif - /* - Ensure the image are the same size. - */ assert(images != (Image *) NULL); assert(images->signature == MagickSignature); if (images->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); - for (next=images; next != (Image *) NULL; next=GetNextImageInList(next)) - if ((next->columns != images->columns) || (next->rows != images->rows)) - { - (void) ThrowMagickException(exception,GetMagickModule(),OptionError, - "ImageWidthsOrHeightsDiffer","'%s'",images->filename); - return((Image *) NULL); - } - /* - Initialize evaluate next attributes. - */ image=CloneImage(images,images->columns,images->rows,MagickTrue, exception); if (image == (Image *) NULL) @@ -1764,12 +1748,12 @@ MagickExport ChannelStatistics *GetImageStatistics(const Image *image, % % The format of the PolynomialImage method is: % -% Image *PolynomialImage(const Image *image,const size_t number_terms, +% Image *PolynomialImage(const Image *images,const size_t number_terms, % const double *terms,ExceptionInfo *exception) % % A description of each parameter follows: % -% o image: the image. +% o images: the image sequence. % % o number_terms: the number of terms in the list. The actual list length % is 2 x number_terms + 1 (the constant). @@ -1781,33 +1765,217 @@ MagickExport ChannelStatistics *GetImageStatistics(const Image *image, % */ -MagickExport Image *PolynomialImage(const Image *image, +MagickExport Image *PolynomialImage(const Image *images, const size_t number_terms,const double *terms,ExceptionInfo *exception) { +#define PolynomialImageTag "Polynomial/Image" + + CacheView + *polynomial_view; + Image - *polynomial_image; + *image; MagickBooleanType status; - assert(image != (Image *) NULL); - assert(image->signature == MagickSignature); - if (image->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - assert(terms != (double *) NULL); + MagickOffsetType + progress; + + PixelChannels + **restrict polynomial_pixels; + + size_t + number_images; + + ssize_t + y; + + assert(images != (Image *) NULL); + assert(images->signature == MagickSignature); + if (images->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); - polynomial_image=CloneImage(image,image->columns,image->rows,MagickTrue, + image=CloneImage(images,images->columns,images->rows,MagickTrue, exception); - if (polynomial_image == (Image *) NULL) + if (image == (Image *) NULL) return((Image *) NULL); - status=SetImageStorageClass(polynomial_image,DirectClass,exception); - if (status == MagickFalse) + if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) + { + image=DestroyImage(image); + return((Image *) NULL); + } + number_images=GetImageListLength(images); + polynomial_pixels=AcquirePixelThreadSet(images,number_images); + if (polynomial_pixels == (PixelChannels **) NULL) { - polynomial_image=DestroyImage(polynomial_image); + image=DestroyImage(image); + (void) ThrowMagickException(exception,GetMagickModule(), + ResourceLimitError,"MemoryAllocationFailed","'%s'",images->filename); return((Image *) NULL); } - return(polynomial_image); + /* + Polynomial image pixels. + */ + status=MagickTrue; + progress=0; + polynomial_view=AcquireAuthenticCacheView(image,exception); +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp parallel for schedule(static,4) shared(progress,status) \ + dynamic_number_threads(image,image->columns,image->rows,1) +#endif + for (y=0; y < (ssize_t) image->rows; y++) + { + CacheView + *image_view; + + const Image + *next; + + const int + id = GetOpenMPThreadId(); + + register ssize_t + i, + x; + + register PixelChannels + *polynomial_pixel; + + register Quantum + *restrict q; + + ssize_t + j; + + if (status == MagickFalse) + continue; + q=QueueCacheViewAuthenticPixels(polynomial_view,0,y, + image->columns,1,exception); + if (q == (Quantum *) NULL) + { + status=MagickFalse; + continue; + } + polynomial_pixel=polynomial_pixels[id]; + for (j=0; j < (ssize_t) image->columns; j++) + for (i=0; i < MaxPixelChannels; i++) + polynomial_pixel[j].channel[i]=0.0; + next=images; + for (j=0; j < (ssize_t) number_images; j++) + { + register const Quantum + *p; + + image_view=AcquireVirtualCacheView(next,exception); + p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception); + if (p == (const Quantum *) NULL) + { + image_view=DestroyCacheView(image_view); + break; + } + for (x=0; x < (ssize_t) next->columns; x++) + { + register ssize_t + i; + + if (GetPixelMask(next,p) != 0) + { + p+=GetPixelChannels(next); + continue; + } + for (i=0; i < (ssize_t) GetPixelChannels(next); i++) + { + MagickRealType + coefficient, + degree; + + PixelChannel + channel; + + PixelTrait + polynomial_traits, + traits; + + if ((i << 1) >= (ssize_t) number_terms) + continue; + channel=GetPixelChannelChannel(image,i); + traits=GetPixelChannelTraits(next,channel); + polynomial_traits=GetPixelChannelTraits(image,channel); + if ((traits == UndefinedPixelTrait) || + (polynomial_traits == UndefinedPixelTrait)) + continue; + if ((traits & UpdatePixelTrait) == 0) + continue; + coefficient=(MagickRealType) terms[2*i]; + degree=(MagickRealType) terms[2*i+1]; + polynomial_pixel[x].channel[i]+=coefficient* + pow(GetPixelChannel(image,channel,p),degree); + } + p+=GetPixelChannels(next); + } + image_view=DestroyCacheView(image_view); + next=GetNextImageInList(next); + } + for (x=0; x < (ssize_t) image->columns; x++) + { + MagickRealType + constant; + + constant=(MagickRealType) terms[number_terms << 1]; + for (i=0; i < (ssize_t) GetPixelChannels(image); i++) + polynomial_pixel[x].channel[i]+=constant; + } + for (x=0; x < (ssize_t) image->columns; x++) + { + register ssize_t + i; + + if (GetPixelMask(image,q) != 0) + { + q+=GetPixelChannels(image); + continue; + } + for (i=0; i < (ssize_t) GetPixelChannels(image); i++) + { + PixelChannel + channel; + + PixelTrait + traits; + + channel=GetPixelChannelChannel(image,i); + traits=GetPixelChannelTraits(image,channel); + if (traits == UndefinedPixelTrait) + continue; + if ((traits & UpdatePixelTrait) == 0) + continue; + q[i]=ClampToQuantum(polynomial_pixel[x].channel[i]); + } + q+=GetPixelChannels(image); + } + if (SyncCacheViewAuthenticPixels(polynomial_view,exception) == MagickFalse) + status=MagickFalse; + if (images->progress_monitor != (MagickProgressMonitor) NULL) + { + MagickBooleanType + proceed; + +#if defined(MAGICKCORE_OPENMP_SUPPORT) + #pragma omp critical (MagickCore_PolynomialImages) +#endif + proceed=SetImageProgress(images,PolynomialImageTag,progress++, + image->rows); + if (proceed == MagickFalse) + status=MagickFalse; + } + } + polynomial_view=DestroyCacheView(polynomial_view); + polynomial_pixels=DestroyPixelThreadSet(polynomial_pixels); + if (status == MagickFalse) + image=DestroyImage(image); + return(image); } /* -- 2.50.1