CacheView
*evaluate_view;
- const Image
- *next;
-
Image
*image;
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)
%
% 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).
%
*/
-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);
}
\f
/*