- if (fabs(sigma) < MagickEpsilon)
- return(blur_image);
- if (SetImageStorageClass(blur_image,DirectClass,exception) == MagickFalse)
- {
- blur_image=DestroyImage(blur_image);
- return((Image *) NULL);
- }
- width=GetOptimalKernelWidth1D(radius,sigma);
- kernel=GetBlurKernel(width,sigma);
- if (kernel == (MagickRealType *) NULL)
- {
- blur_image=DestroyImage(blur_image);
- ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
- }
- if (image->debug != MagickFalse)
- {
- char
- format[MaxTextExtent],
- *message;
-
- register const MagickRealType
- *k;
-
- (void) LogMagickEvent(TransformEvent,GetMagickModule(),
- " blur image with kernel width %.20g:",(double) width);
- message=AcquireString("");
- k=kernel;
- for (i=0; i < (ssize_t) width; i++)
- {
- *message='\0';
- (void) FormatLocaleString(format,MaxTextExtent,"%.20g: ",(double) i);
- (void) ConcatenateString(&message,format);
- (void) FormatLocaleString(format,MaxTextExtent,"%g ",(double) *k++);
- (void) ConcatenateString(&message,format);
- (void) LogMagickEvent(TransformEvent,GetMagickModule(),"%s",message);
- }
- message=DestroyString(message);
- }
- /*
- Blur rows.
- */
- status=MagickTrue;
- progress=0;
- center=(ssize_t) GetPixelChannels(image)*(width/2L);
- image_view=AcquireVirtualCacheView(image,exception);
- blur_view=AcquireAuthenticCacheView(blur_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++)
- {
- register const Quantum
- *restrict p;
-
- register Quantum
- *restrict q;
-
- register ssize_t
- x;
-
- if (status == MagickFalse)
- continue;
- p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y,
- image->columns+width,1,exception);
- q=QueueCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
- exception);
- if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
- {
- status=MagickFalse;
- continue;
- }
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- register ssize_t
- i;
-
- for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
- {
- double
- alpha,
- gamma,
- pixel;
-
- PixelChannel
- channel;
-
- PixelTrait
- blur_traits,
- traits;
-
- register const MagickRealType
- *restrict k;
-
- register const Quantum
- *restrict pixels;
-
- register ssize_t
- u;
-
- channel=GetPixelChannelChannel(image,i);
- traits=GetPixelChannelTraits(image,channel);
- blur_traits=GetPixelChannelTraits(blur_image,channel);
- if ((traits == UndefinedPixelTrait) ||
- (blur_traits == UndefinedPixelTrait))
- continue;
- if (((blur_traits & CopyPixelTrait) != 0) ||
- (GetPixelMask(image,p) != 0))
- {
- SetPixelChannel(blur_image,channel,p[center+i],q);
- continue;
- }
- k=kernel;
- pixels=p;
- pixel=0.0;
- if ((blur_traits & BlendPixelTrait) == 0)
- {
- /*
- No alpha blending.
- */
- for (u=0; u < (ssize_t) width; u++)
- {
- pixel+=(*k)*pixels[i];
- k++;
- pixels+=GetPixelChannels(image);
- }
- SetPixelChannel(blur_image,channel,ClampToQuantum(pixel),q);
- continue;
- }
- /*
- Alpha blending.
- */
- gamma=0.0;
- for (u=0; u < (ssize_t) width; u++)
- {
- alpha=(double) (QuantumScale*GetPixelAlpha(image,pixels));
- pixel+=(*k)*alpha*pixels[i];
- gamma+=(*k)*alpha;
- k++;
- pixels+=GetPixelChannels(image);
- }
- gamma=MagickEpsilonReciprocal(gamma);
- SetPixelChannel(blur_image,channel,ClampToQuantum(gamma*pixel),q);
- }
- p+=GetPixelChannels(image);
- q+=GetPixelChannels(blur_image);
- }
- if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
- status=MagickFalse;
- if (image->progress_monitor != (MagickProgressMonitor) NULL)
- {
- MagickBooleanType
- proceed;
-
-#if defined(MAGICKCORE_OPENMP_SUPPORT)
- #pragma omp critical (MagickCore_BlurImage)
-#endif
- proceed=SetImageProgress(image,BlurImageTag,progress++,blur_image->rows+
- blur_image->columns);
- if (proceed == MagickFalse)
- status=MagickFalse;
- }
- }
- blur_view=DestroyCacheView(blur_view);
- image_view=DestroyCacheView(image_view);
- /*
- Blur columns.
- */
- center=(ssize_t) GetPixelChannels(blur_image)*(width/2L);
- image_view=AcquireVirtualCacheView(blur_image,exception);
- blur_view=AcquireAuthenticCacheView(blur_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 (x=0; x < (ssize_t) blur_image->columns; x++)
- {
- register const Quantum
- *restrict p;
-
- register Quantum
- *restrict q;
-
- register ssize_t
- y;
-
- if (status == MagickFalse)
- continue;
- p=GetCacheViewVirtualPixels(image_view,x,-((ssize_t) width/2L),1,
- blur_image->rows+width,exception);
- q=GetCacheViewAuthenticPixels(blur_view,x,0,1,blur_image->rows,exception);
- if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
- {
- status=MagickFalse;
- continue;
- }
- for (y=0; y < (ssize_t) blur_image->rows; y++)