43#include "magick/studio.h"
44#include "magick/accelerate-private.h"
45#include "magick/blob.h"
46#include "magick/cache-view.h"
47#include "magick/color.h"
48#include "magick/color-private.h"
49#include "magick/colorspace.h"
50#include "magick/constitute.h"
51#include "magick/decorate.h"
52#include "magick/distort.h"
53#include "magick/draw.h"
54#include "magick/enhance.h"
55#include "magick/exception.h"
56#include "magick/exception-private.h"
57#include "magick/effect.h"
59#include "magick/gem.h"
60#include "magick/geometry.h"
61#include "magick/image-private.h"
62#include "magick/list.h"
63#include "magick/log.h"
64#include "magick/matrix.h"
65#include "magick/memory_.h"
66#include "magick/memory-private.h"
67#include "magick/monitor.h"
68#include "magick/monitor-private.h"
69#include "magick/montage.h"
70#include "magick/morphology.h"
71#include "magick/morphology-private.h"
72#include "magick/opencl-private.h"
73#include "magick/paint.h"
74#include "magick/pixel-accessor.h"
75#include "magick/pixel-private.h"
76#include "magick/property.h"
77#include "magick/quantize.h"
78#include "magick/quantum.h"
79#include "magick/random_.h"
80#include "magick/random-private.h"
81#include "magick/resample.h"
82#include "magick/resample-private.h"
83#include "magick/resize.h"
84#include "magick/resource_.h"
85#include "magick/segment.h"
86#include "magick/shear.h"
87#include "magick/signature-private.h"
88#include "magick/statistic.h"
89#include "magick/string_.h"
90#include "magick/thread-private.h"
91#include "magick/transform.h"
92#include "magick/threshold.h"
93#include "magick/utility-private.h"
95#ifdef MAGICKCORE_CLPERFMARKER
96#include "CLPerfMarker.h"
139MagickExport Image *AdaptiveBlurImage(
const Image *image,
const double radius,
140 const double sigma,ExceptionInfo *exception)
145 blur_image=AdaptiveBlurImageChannel(image,DefaultChannels,radius,sigma,
150MagickExport Image *AdaptiveBlurImageChannel(
const Image *image,
151 const ChannelType channel,
const double radius,
const double sigma,
152 ExceptionInfo *exception)
154#define AdaptiveBlurImageTag "Convolve/Image"
155#define MagickSigma (fabs(sigma) < MagickEpsilon ? MagickEpsilon : sigma)
193 assert(image != (
const Image *) NULL);
194 assert(image->signature == MagickCoreSignature);
195 assert(exception != (ExceptionInfo *) NULL);
196 assert(exception->signature == MagickCoreSignature);
197 if (IsEventLogging() != MagickFalse)
198 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
199 blur_image=CloneImage(image,0,0,MagickTrue,exception);
200 if (blur_image == (Image *) NULL)
201 return((Image *) NULL);
202 if (fabs(sigma) <= MagickEpsilon)
204 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
206 InheritException(exception,&blur_image->exception);
207 blur_image=DestroyImage(blur_image);
208 return((Image *) NULL);
213 edge_image=EdgeImage(image,radius,exception);
214 if (edge_image == (Image *) NULL)
216 blur_image=DestroyImage(blur_image);
217 return((Image *) NULL);
219 (void) AutoLevelImage(edge_image);
220 gaussian_image=BlurImage(edge_image,radius,sigma,exception);
221 if (gaussian_image != (Image *) NULL)
223 edge_image=DestroyImage(edge_image);
224 edge_image=gaussian_image;
226 (void) AutoLevelImage(edge_image);
230 width=GetOptimalKernelWidth2D(radius,sigma);
231 kernel=(
double **) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
233 if (kernel == (
double **) NULL)
235 edge_image=DestroyImage(edge_image);
236 blur_image=DestroyImage(blur_image);
237 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
239 (void) memset(kernel,0,(
size_t) width*
sizeof(*kernel));
240 for (i=0; i < (ssize_t) width; i+=2)
242 kernel[i]=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t)
243 (width-i),(width-i)*
sizeof(**kernel)));
244 if (kernel[i] == (
double *) NULL)
247 j=(ssize_t) (width-i-1)/2;
249 for (v=(-j); v <= j; v++)
251 for (u=(-j); u <= j; u++)
253 kernel[i][k]=(double) (exp(-((
double) u*u+v*v)/(2.0*MagickSigma*
254 MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
255 normalize+=kernel[i][k];
259 kernel[i][(k-1)/2]+=(1.0-normalize);
260 if (sigma < MagickEpsilon)
261 kernel[i][(k-1)/2]=1.0;
263 if (i < (ssize_t) width)
265 for (i-=2; i >= 0; i-=2)
266 kernel[i]=(
double *) RelinquishAlignedMemory(kernel[i]);
267 kernel=(
double **) RelinquishAlignedMemory(kernel);
268 edge_image=DestroyImage(edge_image);
269 blur_image=DestroyImage(blur_image);
270 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
277 GetMagickPixelPacket(image,&bias);
278 SetMagickPixelPacketBias(image,&bias);
279 image_view=AcquireVirtualCacheView(image,exception);
280 edge_view=AcquireVirtualCacheView(edge_image,exception);
281 blur_view=AcquireAuthenticCacheView(blur_image,exception);
282#if defined(MAGICKCORE_OPENMP_SUPPORT)
283 #pragma omp parallel for schedule(static) shared(progress,status) \
284 magick_number_threads(image,blur_image,blur_image->rows,1)
286 for (y=0; y < (ssize_t) blur_image->rows; y++)
289 *magick_restrict indexes;
296 *magick_restrict blur_indexes;
304 if (status == MagickFalse)
306 r=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns,1,exception);
307 q=QueueCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
309 if ((r == (
const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
314 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
315 for (x=0; x < (ssize_t) blur_image->columns; x++)
333 i=CastDoubleToLong(ceil((
double) width*QuantumScale*
334 GetPixelIntensity(edge_image,r)-0.5));
338 if (i > (ssize_t) width)
342 p=GetCacheViewVirtualPixels(image_view,x-((ssize_t) (width-i)/2L),y-
343 (ssize_t) ((width-i)/2L),width-i,width-i,exception);
344 if (p == (
const PixelPacket *) NULL)
346 indexes=GetCacheViewVirtualIndexQueue(image_view);
348 pixel.green=bias.green;
349 pixel.blue=bias.blue;
350 pixel.opacity=bias.opacity;
351 pixel.index=bias.index;
353 for (v=0; v < (ssize_t) (width-i); v++)
355 for (u=0; u < (ssize_t) (width-i); u++)
358 if (((channel & OpacityChannel) != 0) &&
359 (image->matte != MagickFalse))
360 alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(p));
361 if ((channel & RedChannel) != 0)
362 pixel.red+=(*k)*alpha*(double) GetPixelRed(p);
363 if ((channel & GreenChannel) != 0)
364 pixel.green+=(*k)*alpha*(double) GetPixelGreen(p);
365 if ((channel & BlueChannel) != 0)
366 pixel.blue+=(*k)*alpha*(double) GetPixelBlue(p);
367 if ((channel & OpacityChannel) != 0)
368 pixel.opacity+=(*k)*(double) GetPixelOpacity(p);
369 if (((channel & IndexChannel) != 0) &&
370 (image->colorspace == CMYKColorspace))
371 pixel.index+=(*k)*alpha*(double) GetPixelIndex(indexes+x+(width-i)*
378 gamma=MagickSafeReciprocal(gamma);
379 if ((channel & RedChannel) != 0)
380 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) pixel.red));
381 if ((channel & GreenChannel) != 0)
382 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType) pixel.green));
383 if ((channel & BlueChannel) != 0)
384 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType) pixel.blue));
385 if ((channel & OpacityChannel) != 0)
386 SetPixelOpacity(q,ClampToQuantum((MagickRealType) pixel.opacity));
387 if (((channel & IndexChannel) != 0) &&
388 (image->colorspace == CMYKColorspace))
389 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*(MagickRealType)
394 if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
396 if (image->progress_monitor != (MagickProgressMonitor) NULL)
401#if defined(MAGICKCORE_OPENMP_SUPPORT)
405 proceed=SetImageProgress(image,AdaptiveBlurImageTag,progress,
407 if (proceed == MagickFalse)
411 blur_image->type=image->type;
412 blur_view=DestroyCacheView(blur_view);
413 edge_view=DestroyCacheView(edge_view);
414 image_view=DestroyCacheView(image_view);
415 edge_image=DestroyImage(edge_image);
416 for (i=0; i < (ssize_t) width; i+=2)
417 kernel[i]=(
double *) RelinquishAlignedMemory(kernel[i]);
418 kernel=(
double **) RelinquishAlignedMemory(kernel);
419 if (status == MagickFalse)
420 blur_image=DestroyImage(blur_image);
464MagickExport Image *AdaptiveSharpenImage(
const Image *image,
const double radius,
465 const double sigma,ExceptionInfo *exception)
470 sharp_image=AdaptiveSharpenImageChannel(image,DefaultChannels,radius,sigma,
475MagickExport Image *AdaptiveSharpenImageChannel(
const Image *image,
476 const ChannelType channel,
const double radius,
const double sigma,
477 ExceptionInfo *exception)
479#define AdaptiveSharpenImageTag "Convolve/Image"
480#define MagickSigma (fabs(sigma) < MagickEpsilon ? MagickEpsilon : sigma)
518 assert(image != (
const Image *) NULL);
519 assert(image->signature == MagickCoreSignature);
520 assert(exception != (ExceptionInfo *) NULL);
521 assert(exception->signature == MagickCoreSignature);
522 if (IsEventLogging() != MagickFalse)
523 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
524 sharp_image=CloneImage(image,0,0,MagickTrue,exception);
525 if (sharp_image == (Image *) NULL)
526 return((Image *) NULL);
527 if (fabs(sigma) <= MagickEpsilon)
529 if (SetImageStorageClass(sharp_image,DirectClass) == MagickFalse)
531 InheritException(exception,&sharp_image->exception);
532 sharp_image=DestroyImage(sharp_image);
533 return((Image *) NULL);
538 edge_image=EdgeImage(image,radius,exception);
539 if (edge_image == (Image *) NULL)
541 sharp_image=DestroyImage(sharp_image);
542 return((Image *) NULL);
544 (void) AutoLevelImage(edge_image);
545 gaussian_image=BlurImage(edge_image,radius,sigma,exception);
546 if (gaussian_image != (Image *) NULL)
548 edge_image=DestroyImage(edge_image);
549 edge_image=gaussian_image;
551 (void) AutoLevelImage(edge_image);
555 width=GetOptimalKernelWidth2D(radius,sigma);
556 kernel=(
double **) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
558 if (kernel == (
double **) NULL)
560 edge_image=DestroyImage(edge_image);
561 sharp_image=DestroyImage(sharp_image);
562 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
564 (void) memset(kernel,0,(
size_t) width*
sizeof(*kernel));
565 for (i=0; i < (ssize_t) width; i+=2)
567 kernel[i]=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t)
568 (width-i),(width-i)*
sizeof(**kernel)));
569 if (kernel[i] == (
double *) NULL)
572 j=(ssize_t) (width-i-1)/2;
574 for (v=(-j); v <= j; v++)
576 for (u=(-j); u <= j; u++)
578 kernel[i][k]=(double) (-exp(-((
double) u*u+v*v)/(2.0*MagickSigma*
579 MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
580 normalize+=kernel[i][k];
584 kernel[i][(k-1)/2]=(
double) ((-2.0)*normalize);
585 if (sigma < MagickEpsilon)
586 kernel[i][(k-1)/2]=1.0;
588 if (i < (ssize_t) width)
590 for (i-=2; i >= 0; i-=2)
591 kernel[i]=(
double *) RelinquishAlignedMemory(kernel[i]);
592 kernel=(
double **) RelinquishAlignedMemory(kernel);
593 edge_image=DestroyImage(edge_image);
594 sharp_image=DestroyImage(sharp_image);
595 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
602 GetMagickPixelPacket(image,&bias);
603 SetMagickPixelPacketBias(image,&bias);
604 image_view=AcquireVirtualCacheView(image,exception);
605 edge_view=AcquireVirtualCacheView(edge_image,exception);
606 sharp_view=AcquireAuthenticCacheView(sharp_image,exception);
607#if defined(MAGICKCORE_OPENMP_SUPPORT)
608 #pragma omp parallel for schedule(static) shared(progress,status) \
609 magick_number_threads(image,sharp_image,sharp_image->rows,1)
611 for (y=0; y < (ssize_t) sharp_image->rows; y++)
614 *magick_restrict indexes;
621 *magick_restrict sharp_indexes;
629 if (status == MagickFalse)
631 r=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns,1,exception);
632 q=QueueCacheViewAuthenticPixels(sharp_view,0,y,sharp_image->columns,1,
634 if ((r == (
const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
639 sharp_indexes=GetCacheViewAuthenticIndexQueue(sharp_view);
640 for (x=0; x < (ssize_t) sharp_image->columns; x++)
658 i=CastDoubleToLong(ceil((
double) width*(1.0-QuantumScale*
659 GetPixelIntensity(edge_image,r))-0.5));
663 if (i > (ssize_t) width)
667 p=GetCacheViewVirtualPixels(image_view,x-((ssize_t) (width-i)/2L),y-
668 (ssize_t) ((width-i)/2L),width-i,width-i,exception);
669 if (p == (
const PixelPacket *) NULL)
671 indexes=GetCacheViewVirtualIndexQueue(image_view);
674 pixel.green=bias.green;
675 pixel.blue=bias.blue;
676 pixel.opacity=bias.opacity;
677 pixel.index=bias.index;
678 for (v=0; v < (ssize_t) (width-i); v++)
680 for (u=0; u < (ssize_t) (width-i); u++)
683 if (((channel & OpacityChannel) != 0) &&
684 (image->matte != MagickFalse))
685 alpha=(MagickRealType) (QuantumScale*(MagickRealType)
687 if ((channel & RedChannel) != 0)
688 pixel.red+=(*k)*alpha*(MagickRealType) GetPixelRed(p);
689 if ((channel & GreenChannel) != 0)
690 pixel.green+=(*k)*alpha*(MagickRealType) GetPixelGreen(p);
691 if ((channel & BlueChannel) != 0)
692 pixel.blue+=(*k)*alpha*(MagickRealType) GetPixelBlue(p);
693 if ((channel & OpacityChannel) != 0)
694 pixel.opacity+=(*k)*(MagickRealType) GetPixelOpacity(p);
695 if (((channel & IndexChannel) != 0) &&
696 (image->colorspace == CMYKColorspace))
697 pixel.index+=(*k)*alpha*(MagickRealType)
698 GetPixelIndex(indexes+x+(width-i)*v+u);
704 gamma=MagickSafeReciprocal(gamma);
705 if ((channel & RedChannel) != 0)
706 SetPixelRed(q,ClampToQuantum(gamma*pixel.red));
707 if ((channel & GreenChannel) != 0)
708 SetPixelGreen(q,ClampToQuantum(gamma*pixel.green));
709 if ((channel & BlueChannel) != 0)
710 SetPixelBlue(q,ClampToQuantum(gamma*pixel.blue));
711 if ((channel & OpacityChannel) != 0)
712 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
713 if (((channel & IndexChannel) != 0) &&
714 (image->colorspace == CMYKColorspace))
715 SetPixelIndex(sharp_indexes+x,ClampToQuantum(gamma*pixel.index));
719 if (SyncCacheViewAuthenticPixels(sharp_view,exception) == MagickFalse)
721 if (image->progress_monitor != (MagickProgressMonitor) NULL)
726#if defined(MAGICKCORE_OPENMP_SUPPORT)
730 proceed=SetImageProgress(image,AdaptiveSharpenImageTag,progress,
732 if (proceed == MagickFalse)
736 sharp_image->type=image->type;
737 sharp_view=DestroyCacheView(sharp_view);
738 edge_view=DestroyCacheView(edge_view);
739 image_view=DestroyCacheView(image_view);
740 edge_image=DestroyImage(edge_image);
741 for (i=0; i < (ssize_t) width; i+=2)
742 kernel[i]=(
double *) RelinquishAlignedMemory(kernel[i]);
743 kernel=(
double **) RelinquishAlignedMemory(kernel);
744 if (status == MagickFalse)
745 sharp_image=DestroyImage(sharp_image);
787MagickExport Image *BlurImage(
const Image *image,
const double radius,
788 const double sigma,ExceptionInfo *exception)
793 blur_image=BlurImageChannel(image,DefaultChannels,radius,sigma,exception);
797MagickExport Image *BlurImageChannel(
const Image *image,
798 const ChannelType channel,
const double radius,
const double sigma,
799 ExceptionInfo *exception)
802 geometry[MaxTextExtent];
810 assert(image != (
const Image *) NULL);
811 assert(image->signature == MagickCoreSignature);
812 assert(exception != (ExceptionInfo *) NULL);
813 assert(exception->signature == MagickCoreSignature);
814 if (IsEventLogging() != MagickFalse)
815 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
816#if defined(MAGICKCORE_OPENCL_SUPPORT)
817 blur_image=AccelerateBlurImage(image,channel,radius,sigma,exception);
818 if (blur_image != (Image *) NULL)
821 (void) FormatLocaleString(geometry,MaxTextExtent,
822 "blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma);
823 kernel_info=AcquireKernelInfo(geometry);
825 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
826 blur_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
827 kernel_info,exception);
828 kernel_info=DestroyKernelInfo(kernel_info);
866MagickExport Image *ConvolveImage(
const Image *image,
const size_t order,
867 const double *kernel,ExceptionInfo *exception)
872#ifdef MAGICKCORE_CLPERFMARKER
873 clBeginPerfMarkerAMD(__FUNCTION__,
"");
876 convolve_image=ConvolveImageChannel(image,DefaultChannels,order,kernel,
879#ifdef MAGICKCORE_CLPERFMARKER
880 clEndPerfMarkerAMD();
882 return(convolve_image);
885MagickExport Image *ConvolveImageChannel(
const Image *image,
886 const ChannelType channel,
const size_t order,
const double *kernel,
887 ExceptionInfo *exception)
898 kernel_info=AcquireKernelInfo((
const char *) NULL);
900 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
901 kernel_info->width=order;
902 kernel_info->height=order;
903 kernel_info->x=(ssize_t) (order-1)/2;
904 kernel_info->y=(ssize_t) (order-1)/2;
905 kernel_info->signature=MagickCoreSignature;
906 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
907 kernel_info->width,kernel_info->width*
sizeof(*kernel_info->values)));
908 if (kernel_info->values == (
double *) NULL)
910 kernel_info=DestroyKernelInfo(kernel_info);
911 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
913 for (i=0; i < (ssize_t) (order*order); i++)
914 kernel_info->values[i]=kernel[i];
915 convolve_image=(Image *) NULL;
916#if defined(MAGICKCORE_OPENCL_SUPPORT)
917 convolve_image=AccelerateConvolveImageChannel(image,channel,kernel_info,
920 if (convolve_image == (Image *) NULL)
921 convolve_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
922 kernel_info,exception);
923 kernel_info=DestroyKernelInfo(kernel_info);
924 return(convolve_image);
957static void Hull(
const Image *image,
const ssize_t x_offset,
958 const ssize_t y_offset,
const size_t columns,
const size_t rows,
959 const int polarity,Quantum *magick_restrict f,Quantum *magick_restrict g)
970 assert(image != (
const Image *) NULL);
971 assert(image->signature == MagickCoreSignature);
972 assert(f != (Quantum *) NULL);
973 assert(g != (Quantum *) NULL);
974 assert(columns <= (MAGICK_SSIZE_MAX-2));
975 p=f+(ptrdiff_t) (columns+2);
976 q=g+(ptrdiff_t) (columns+2);
977 r=p+(ptrdiff_t) (y_offset*((ssize_t) columns+2)+x_offset);
978#if defined(MAGICKCORE_OPENMP_SUPPORT)
979 #pragma omp parallel for schedule(static) \
980 magick_number_threads(image,image,rows,2)
982 for (y=0; y < (ssize_t) rows; y++)
993 for (x=0; x < (ssize_t) columns; x++)
995 v=(SignedQuantum) p[i];
996 if ((SignedQuantum) r[i] >= (v+ScaleCharToQuantum(2)))
997 v+=ScaleCharToQuantum(1);
1002 for (x=0; x < (ssize_t) columns; x++)
1004 v=(SignedQuantum) p[i];
1005 if ((SignedQuantum) r[i] <= (v-ScaleCharToQuantum(2)))
1006 v-=ScaleCharToQuantum(1);
1012 p=f+(ptrdiff_t) (columns+2);
1013 q=g+(ptrdiff_t) (columns+2);
1014 r=q+(ptrdiff_t) (y_offset*((ssize_t) columns+2)+x_offset);
1015 s=q-(ptrdiff_t) (y_offset*((ssize_t) columns+2)+x_offset);
1016#if defined(MAGICKCORE_OPENMP_SUPPORT)
1017 #pragma omp parallel for schedule(static) \
1018 magick_number_threads(image,image,rows,2)
1020 for (y=0; y < (ssize_t) rows; y++)
1029 i=(2*y+1)+y*columns;
1031 for (x=0; x < (ssize_t) columns; x++)
1033 v=(SignedQuantum) q[i];
1034 if (((SignedQuantum) s[i] >= (v+ScaleCharToQuantum(2))) &&
1035 ((SignedQuantum) r[i] > v))
1036 v+=ScaleCharToQuantum(1);
1041 for (x=0; x < (ssize_t) columns; x++)
1043 v=(SignedQuantum) q[i];
1044 if (((SignedQuantum) s[i] <= (v-ScaleCharToQuantum(2))) &&
1045 ((SignedQuantum) r[i] < v))
1046 v-=ScaleCharToQuantum(1);
1053MagickExport Image *DespeckleImage(
const Image *image,ExceptionInfo *exception)
1055#define DespeckleImageTag "Despeckle/Image"
1075 *magick_restrict buffer,
1076 *magick_restrict pixels;
1082 static const ssize_t
1083 X[4] = {0, 1, 1,-1},
1084 Y[4] = {1, 0, 1, 1};
1089 assert(image != (
const Image *) NULL);
1090 assert(image->signature == MagickCoreSignature);
1091 assert(exception != (ExceptionInfo *) NULL);
1092 assert(exception->signature == MagickCoreSignature);
1093 if (IsEventLogging() != MagickFalse)
1094 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1095#if defined(MAGICKCORE_OPENCL_SUPPORT)
1096 despeckle_image=AccelerateDespeckleImage(image, exception);
1097 if (despeckle_image != (Image *) NULL)
1098 return(despeckle_image);
1100 despeckle_image=CloneImage(image,0,0,MagickTrue,exception);
1101 if (despeckle_image == (Image *) NULL)
1102 return((Image *) NULL);
1103 if (SetImageStorageClass(despeckle_image,DirectClass) == MagickFalse)
1105 InheritException(exception,&despeckle_image->exception);
1106 despeckle_image=DestroyImage(despeckle_image);
1107 return((Image *) NULL);
1112 if ((image->columns > (MAGICK_SIZE_MAX-2)) ||
1113 (image->rows > (MAGICK_SIZE_MAX-2)))
1115 despeckle_image=DestroyImage(despeckle_image);
1116 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1118 length=(image->columns+2)*(image->rows+2);
1119 pixel_info=AcquireVirtualMemory(length,
sizeof(*pixels));
1120 buffer_info=AcquireVirtualMemory(length,
sizeof(*buffer));
1121 if ((pixel_info == (MemoryInfo *) NULL) ||
1122 (buffer_info == (MemoryInfo *) NULL))
1124 if (buffer_info != (MemoryInfo *) NULL)
1125 buffer_info=RelinquishVirtualMemory(buffer_info);
1126 if (pixel_info != (MemoryInfo *) NULL)
1127 pixel_info=RelinquishVirtualMemory(pixel_info);
1128 despeckle_image=DestroyImage(despeckle_image);
1129 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1131 pixels=(Quantum *) GetVirtualMemoryBlob(pixel_info);
1132 buffer=(Quantum *) GetVirtualMemoryBlob(buffer_info);
1137 number_channels=(size_t) (image->colorspace == CMYKColorspace ? 5 : 4);
1138 image_view=AcquireVirtualCacheView(image,exception);
1139 despeckle_view=AcquireAuthenticCacheView(despeckle_image,exception);
1140 for (i=0; i < (ssize_t) number_channels; i++)
1150 if (status == MagickFalse)
1152 if ((image->matte == MagickFalse) && (i == 3))
1154 (void) memset(pixels,0,length*
sizeof(*pixels));
1155 j=(ssize_t) image->columns+2;
1156 for (y=0; y < (ssize_t) image->rows; y++)
1159 *magick_restrict indexes;
1164 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1165 if (p == (
const PixelPacket *) NULL)
1167 indexes=GetCacheViewVirtualIndexQueue(image_view);
1169 for (x=0; x < (ssize_t) image->columns; x++)
1173 case 0: pixels[j]=GetPixelRed(p);
break;
1174 case 1: pixels[j]=GetPixelGreen(p);
break;
1175 case 2: pixels[j]=GetPixelBlue(p);
break;
1176 case 3: pixels[j]=GetPixelOpacity(p);
break;
1177 case 4: pixels[j]=GetPixelBlack(indexes+x);
break;
1185 (void) memset(buffer,0,length*
sizeof(*buffer));
1186 for (k=0; k < 4; k++)
1188 Hull(image,X[k],Y[k],image->columns,image->rows,1,pixels,buffer);
1189 Hull(image,-X[k],-Y[k],image->columns,image->rows,1,pixels,buffer);
1190 Hull(image,-X[k],-Y[k],image->columns,image->rows,-1,pixels,buffer);
1191 Hull(image,X[k],Y[k],image->columns,image->rows,-1,pixels,buffer);
1193 j=(ssize_t) image->columns+2;
1194 for (y=0; y < (ssize_t) image->rows; y++)
1200 *magick_restrict indexes;
1205 q=GetCacheViewAuthenticPixels(despeckle_view,0,y,despeckle_image->columns,
1207 if (q == (PixelPacket *) NULL)
1209 indexes=GetCacheViewAuthenticIndexQueue(despeckle_view);
1211 for (x=0; x < (ssize_t) image->columns; x++)
1215 case 0: SetPixelRed(q,pixels[j]);
break;
1216 case 1: SetPixelGreen(q,pixels[j]);
break;
1217 case 2: SetPixelBlue(q,pixels[j]);
break;
1218 case 3: SetPixelOpacity(q,pixels[j]);
break;
1219 case 4: SetPixelIndex(indexes+x,pixels[j]);
break;
1225 sync=SyncCacheViewAuthenticPixels(despeckle_view,exception);
1226 if (sync == MagickFalse)
1233 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1238 proceed=SetImageProgress(image,DespeckleImageTag,(MagickOffsetType) i,
1240 if (proceed == MagickFalse)
1244 despeckle_view=DestroyCacheView(despeckle_view);
1245 image_view=DestroyCacheView(image_view);
1246 buffer_info=RelinquishVirtualMemory(buffer_info);
1247 pixel_info=RelinquishVirtualMemory(pixel_info);
1248 despeckle_image->type=image->type;
1249 if (status == MagickFalse)
1250 despeckle_image=DestroyImage(despeckle_image);
1251 return(despeckle_image);
1283MagickExport Image *EdgeImage(
const Image *image,
const double radius,
1284 ExceptionInfo *exception)
1298 assert(image != (
const Image *) NULL);
1299 assert(image->signature == MagickCoreSignature);
1300 assert(exception != (ExceptionInfo *) NULL);
1301 assert(exception->signature == MagickCoreSignature);
1302 if (IsEventLogging() != MagickFalse)
1303 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1304 width=GetOptimalKernelWidth1D(radius,0.5);
1305 kernel_info=AcquireKernelInfo((
const char *) NULL);
1307 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1308 (void) memset(kernel_info,0,
sizeof(*kernel_info));
1309 kernel_info->width=width;
1310 kernel_info->height=width;
1311 kernel_info->x=(ssize_t) (kernel_info->width-1)/2;
1312 kernel_info->y=(ssize_t) (kernel_info->height-1)/2;
1313 kernel_info->signature=MagickCoreSignature;
1314 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
1315 kernel_info->width,kernel_info->height*
sizeof(*kernel_info->values)));
1316 if (kernel_info->values == (
double *) NULL)
1318 kernel_info=DestroyKernelInfo(kernel_info);
1319 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1321 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1322 kernel_info->values[i]=(-1.0);
1323 kernel_info->values[i/2]=(double) kernel_info->width*kernel_info->height-1.0;
1324 edge_image=(Image *) NULL;
1325#if defined(MAGICKCORE_OPENCL_SUPPORT)
1326 edge_image=AccelerateConvolveImageChannel(image,DefaultChannels,kernel_info,
1329 if (edge_image == (Image *) NULL)
1330 edge_image=MorphologyImageChannel(image,DefaultChannels,ConvolveMorphology,
1331 1,kernel_info,exception);
1332 kernel_info=DestroyKernelInfo(kernel_info);
1369MagickExport Image *EmbossImage(
const Image *image,
const double radius,
1370 const double sigma,ExceptionInfo *exception)
1394 assert(image != (
const Image *) NULL);
1395 assert(image->signature == MagickCoreSignature);
1396 assert(exception != (ExceptionInfo *) NULL);
1397 assert(exception->signature == MagickCoreSignature);
1398 if (IsEventLogging() != MagickFalse)
1399 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1400 width=GetOptimalKernelWidth1D(radius,sigma);
1401 kernel_info=AcquireKernelInfo((
const char *) NULL);
1403 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1404 kernel_info->width=width;
1405 kernel_info->height=width;
1406 kernel_info->x=(ssize_t) (width-1)/2;
1407 kernel_info->y=(ssize_t) (width-1)/2;
1408 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
1409 kernel_info->width,kernel_info->width*
sizeof(*kernel_info->values)));
1410 if (kernel_info->values == (
double *) NULL)
1412 kernel_info=DestroyKernelInfo(kernel_info);
1413 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1415 j=(ssize_t) (kernel_info->width-1)/2;
1418 for (v=(-j); v <= j; v++)
1420 for (u=(-j); u <= j; u++)
1422 kernel_info->values[i]=(double) (((u < 0) || (v < 0) ? -8.0 :
1423 8.0)*exp(-((
double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
1424 (2.0*MagickPI*MagickSigma*MagickSigma));
1426 kernel_info->values[i]=0.0;
1432 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1433 normalize+=kernel_info->values[i];
1434 gamma=MagickSafeReciprocal(normalize);
1435 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1436 kernel_info->values[i]*=gamma;
1437 emboss_image=(Image *) NULL;
1438#if defined(MAGICKCORE_OPENCL_SUPPORT)
1439 emboss_image=AccelerateConvolveImageChannel(image,DefaultChannels,kernel_info,
1442 if (emboss_image == (Image *) NULL)
1443 emboss_image=MorphologyImageChannel(image,DefaultChannels,
1444 ConvolveMorphology,1,kernel_info,exception);
1445 kernel_info=DestroyKernelInfo(kernel_info);
1446 if (emboss_image != (Image *) NULL)
1447 (void) EqualizeImageChannel(emboss_image,(ChannelType)
1448 (AllChannels &~ SyncChannels));
1449 return(emboss_image);
1484MagickExport Image *FilterImage(
const Image *image,
const KernelInfo *kernel,
1485 ExceptionInfo *exception)
1490 filter_image=FilterImageChannel(image,DefaultChannels,kernel,exception);
1491 return(filter_image);
1494MagickExport Image *FilterImageChannel(
const Image *image,
1495 const ChannelType channel,
const KernelInfo *kernel,ExceptionInfo *exception)
1497#define FilterImageTag "Filter/Image"
1524#ifdef MAGICKCORE_CLPERFMARKER
1525 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1531 assert(image != (Image *) NULL);
1532 assert(image->signature == MagickCoreSignature);
1533 assert(exception != (ExceptionInfo *) NULL);
1534 assert(exception->signature == MagickCoreSignature);
1535 if (IsEventLogging() != MagickFalse)
1536 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1537 if ((kernel->width % 2) == 0)
1538 ThrowImageException(OptionError,
"KernelWidthMustBeAnOddNumber");
1539 if (image->debug != MagickFalse)
1542 format[MaxTextExtent],
1552 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
1553 " FilterImage with %.20gx%.20g kernel:",(
double) kernel->width,(
double)
1555 message=AcquireString(
"");
1557 for (v=0; v < (ssize_t) kernel->height; v++)
1560 (void) FormatLocaleString(format,MaxTextExtent,
"%.20g: ",(
double) v);
1561 (void) ConcatenateString(&message,format);
1562 for (u=0; u < (ssize_t) kernel->width; u++)
1564 (void) FormatLocaleString(format,MaxTextExtent,
"%g ",*k++);
1565 (void) ConcatenateString(&message,format);
1567 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"%s",message);
1569 message=DestroyString(message);
1571#if defined(MAGICKCORE_OPENCL_SUPPORT)
1572 filter_image=AccelerateConvolveImageChannel(image,channel,kernel,exception);
1573 if (filter_image != (Image *) NULL)
1575#ifdef MAGICKCORE_CLPERFMARKER
1576 clEndPerfMarkerAMD();
1578 return(filter_image);
1581 filter_image=CloneImage(image,0,0,MagickTrue,exception);
1582 if (filter_image == (Image *) NULL)
1583 return((Image *) NULL);
1584 if (SetImageStorageClass(filter_image,DirectClass) == MagickFalse)
1586 InheritException(exception,&filter_image->exception);
1587 filter_image=DestroyImage(filter_image);
1588 return((Image *) NULL);
1593 filter_kernel=(MagickRealType *) MagickAssumeAligned(AcquireAlignedMemory(
1594 kernel->width,kernel->height*
sizeof(*filter_kernel)));
1595 if (filter_kernel == (MagickRealType *) NULL)
1597 filter_image=DestroyImage(filter_image);
1598 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1600 for (i=0; i < (ssize_t) (kernel->width*kernel->height); i++)
1601 filter_kernel[i]=(MagickRealType) kernel->values[i];
1607 GetMagickPixelPacket(image,&bias);
1608 SetMagickPixelPacketBias(image,&bias);
1609 image_view=AcquireVirtualCacheView(image,exception);
1610 filter_view=AcquireAuthenticCacheView(filter_image,exception);
1611#if defined(MAGICKCORE_OPENMP_SUPPORT)
1612 #pragma omp parallel for schedule(static) shared(progress,status) \
1613 magick_number_threads(image,filter_image,image->rows,1)
1615 for (y=0; y < (ssize_t) image->rows; y++)
1621 *magick_restrict indexes;
1627 *magick_restrict filter_indexes;
1635 if (status == MagickFalse)
1637 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) (kernel->width-1)/2L),y-
1638 (ssize_t) ((kernel->height-1)/2L),image->columns+kernel->width,
1639 kernel->height,exception);
1640 q=GetCacheViewAuthenticPixels(filter_view,0,y,filter_image->columns,1,
1642 if ((p == (
const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
1647 indexes=GetCacheViewVirtualIndexQueue(image_view);
1648 filter_indexes=GetCacheViewAuthenticIndexQueue(filter_view);
1649 for (x=0; x < (ssize_t) image->columns; x++)
1654 const MagickRealType
1658 *magick_restrict kernel_pixels;
1667 pixel.green=bias.green;
1668 pixel.blue=bias.blue;
1669 pixel.opacity=bias.opacity;
1670 pixel.index=bias.index;
1673 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
1675 for (v=0; v < (ssize_t) kernel->width; v++)
1677 for (u=0; u < (ssize_t) kernel->height; u++)
1679 pixel.red+=(*k)*(double) kernel_pixels[u].red;
1680 pixel.green+=(*k)*(double) kernel_pixels[u].green;
1681 pixel.blue+=(*k)*(double) kernel_pixels[u].blue;
1684 kernel_pixels+=image->columns+kernel->width;
1686 if ((channel & RedChannel) != 0)
1687 SetPixelRed(q,ClampToQuantum(pixel.red));
1688 if ((channel & GreenChannel) != 0)
1689 SetPixelGreen(q,ClampToQuantum(pixel.green));
1690 if ((channel & BlueChannel) != 0)
1691 SetPixelBlue(q,ClampToQuantum(pixel.blue));
1692 if ((channel & OpacityChannel) != 0)
1696 for (v=0; v < (ssize_t) kernel->width; v++)
1698 for (u=0; u < (ssize_t) kernel->height; u++)
1700 pixel.opacity+=(*k)*(MagickRealType) kernel_pixels[u].opacity;
1703 kernel_pixels+=image->columns+kernel->width;
1705 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
1707 if (((channel & IndexChannel) != 0) &&
1708 (image->colorspace == CMYKColorspace))
1711 *magick_restrict kernel_indexes;
1714 kernel_indexes=indexes;
1715 for (v=0; v < (ssize_t) kernel->width; v++)
1717 for (u=0; u < (ssize_t) kernel->height; u++)
1719 pixel.index+=(*k)*(double) GetPixelIndex(kernel_indexes+u);
1722 kernel_indexes+=image->columns+kernel->width;
1724 SetPixelIndex(filter_indexes+x,ClampToQuantum(pixel.index));
1734 for (v=0; v < (ssize_t) kernel->width; v++)
1736 for (u=0; u < (ssize_t) kernel->height; u++)
1738 alpha=(MagickRealType) QuantumScale*((MagickRealType)
1739 QuantumRange-(MagickRealType) GetPixelOpacity(kernel_pixels+u));
1740 pixel.red+=(*k)*alpha*(double) GetPixelRed(kernel_pixels+u);
1741 pixel.green+=(*k)*alpha*(double) GetPixelGreen(kernel_pixels+u);
1742 pixel.blue+=(*k)*alpha*(double) GetPixelBlue(kernel_pixels+u);
1746 kernel_pixels+=image->columns+kernel->width;
1748 gamma=MagickSafeReciprocal(gamma);
1749 if ((channel & RedChannel) != 0)
1750 SetPixelRed(q,ClampToQuantum(gamma*(
double) pixel.red));
1751 if ((channel & GreenChannel) != 0)
1752 SetPixelGreen(q,ClampToQuantum(gamma*(
double) pixel.green));
1753 if ((channel & BlueChannel) != 0)
1754 SetPixelBlue(q,ClampToQuantum(gamma*(
double) pixel.blue));
1755 if ((channel & OpacityChannel) != 0)
1759 for (v=0; v < (ssize_t) kernel->width; v++)
1761 for (u=0; u < (ssize_t) kernel->height; u++)
1763 pixel.opacity+=(*k)*(double) GetPixelOpacity(kernel_pixels+u);
1766 kernel_pixels+=image->columns+kernel->width;
1768 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
1770 if (((channel & IndexChannel) != 0) &&
1771 (image->colorspace == CMYKColorspace))
1774 *magick_restrict kernel_indexes;
1778 kernel_indexes=indexes;
1779 for (v=0; v < (ssize_t) kernel->width; v++)
1781 for (u=0; u < (ssize_t) kernel->height; u++)
1783 alpha=(MagickRealType) (QuantumScale*((
double) QuantumRange-
1784 (
double) kernel_pixels[u].opacity));
1785 pixel.index+=(*k)*alpha*(MagickRealType)
1786 GetPixelIndex(kernel_indexes+u);
1789 kernel_pixels+=image->columns+kernel->width;
1790 kernel_indexes+=image->columns+kernel->width;
1792 SetPixelIndex(filter_indexes+x,ClampToQuantum(gamma*(
double)
1800 sync=SyncCacheViewAuthenticPixels(filter_view,exception);
1801 if (sync == MagickFalse)
1803 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1808#if defined(MAGICKCORE_OPENMP_SUPPORT)
1812 proceed=SetImageProgress(image,FilterImageTag,progress,image->rows);
1813 if (proceed == MagickFalse)
1817 filter_image->type=image->type;
1818 filter_view=DestroyCacheView(filter_view);
1819 image_view=DestroyCacheView(image_view);
1820 filter_kernel=(MagickRealType *) RelinquishAlignedMemory(filter_kernel);
1821 if (status == MagickFalse)
1822 filter_image=DestroyImage(filter_image);
1823#ifdef MAGICKCORE_CLPERFMARKER
1824 clEndPerfMarkerAMD();
1826 return(filter_image);
1868MagickExport Image *GaussianBlurImage(
const Image *image,
const double radius,
1869 const double sigma,ExceptionInfo *exception)
1874 blur_image=GaussianBlurImageChannel(image,DefaultChannels,radius,sigma,
1879MagickExport Image *GaussianBlurImageChannel(
const Image *image,
1880 const ChannelType channel,
const double radius,
const double sigma,
1881 ExceptionInfo *exception)
1884 geometry[MaxTextExtent];
1892 assert(image != (
const Image *) NULL);
1893 assert(image->signature == MagickCoreSignature);
1894 assert(exception != (ExceptionInfo *) NULL);
1895 assert(exception->signature == MagickCoreSignature);
1896 if (IsEventLogging() != MagickFalse)
1897 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1898 (void) FormatLocaleString(geometry,MaxTextExtent,
"gaussian:%.20gx%.20g",
1900 kernel_info=AcquireKernelInfo(geometry);
1902 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1903 blur_image=(Image *) NULL;
1904#if defined(MAGICKCORE_OPENCL_SUPPORT)
1905 blur_image=AccelerateConvolveImageChannel(image,channel,kernel_info,
1908 if (blur_image == (Image *) NULL)
1909 blur_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
1910 kernel_info,exception);
1911 kernel_info=DestroyKernelInfo(kernel_info);
1959static double *GetMotionBlurKernel(
const size_t width,
const double sigma)
1971 if (IsEventLogging() != MagickFalse)
1972 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1973 kernel=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
1975 if (kernel == (
double *) NULL)
1978 for (i=0; i < (ssize_t) width; i++)
1980 kernel[i]=(double) (exp((-((
double) i*i)/(
double) (2.0*MagickSigma*
1981 MagickSigma)))/(MagickSQ2PI*MagickSigma));
1982 normalize+=kernel[i];
1984 for (i=0; i < (ssize_t) width; i++)
1985 kernel[i]/=normalize;
1989MagickExport Image *MotionBlurImage(
const Image *image,
const double radius,
1990 const double sigma,
const double angle,ExceptionInfo *exception)
1995 motion_blur=MotionBlurImageChannel(image,DefaultChannels,radius,sigma,angle,
1997 return(motion_blur);
2000MagickExport Image *MotionBlurImageChannel(
const Image *image,
2001 const ChannelType channel,
const double radius,
const double sigma,
2002 const double angle,ExceptionInfo *exception)
2004#define BlurImageTag "Blur/Image"
2040 assert(image != (Image *) NULL);
2041 assert(image->signature == MagickCoreSignature);
2042 assert(exception != (ExceptionInfo *) NULL);
2043 assert(exception->signature == MagickCoreSignature);
2044 if (IsEventLogging() != MagickFalse)
2045 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2046 width=GetOptimalKernelWidth1D(radius,sigma);
2047 kernel=GetMotionBlurKernel(width,sigma);
2048 if (kernel == (
double *) NULL)
2049 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2050 offset=(OffsetInfo *) AcquireQuantumMemory(width,
sizeof(*offset));
2051 if (offset == (OffsetInfo *) NULL)
2053 kernel=(
double *) RelinquishAlignedMemory(kernel);
2054 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2057 point.x=(double) width*sin(DegreesToRadians(angle));
2058 point.y=(double) width*cos(DegreesToRadians(angle));
2059 for (i=0; i < (ssize_t) width; i++)
2061 offset[i].x=CastDoubleToLong(ceil((
double) (i*point.y)/
2062 hypot(point.x,point.y)-0.5));
2063 offset[i].y=CastDoubleToLong(ceil((
double) (i*point.x)/
2064 hypot(point.x,point.y)-0.5));
2070#if defined(MAGICKCORE_OPENCL_SUPPORT)
2071 blur_image=AccelerateMotionBlurImage(image,channel,kernel,width,offset,
2073 if (blur_image != (Image *) NULL)
2076 blur_image=CloneImage(image,0,0,MagickTrue,exception);
2077 if (blur_image == (Image *) NULL)
2079 kernel=(
double *) RelinquishAlignedMemory(kernel);
2080 offset=(OffsetInfo *) RelinquishMagickMemory(offset);
2081 return((Image *) NULL);
2083 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
2085 kernel=(
double *) RelinquishAlignedMemory(kernel);
2086 offset=(OffsetInfo *) RelinquishMagickMemory(offset);
2087 InheritException(exception,&blur_image->exception);
2088 blur_image=DestroyImage(blur_image);
2089 return((Image *) NULL);
2094 GetMagickPixelPacket(image,&bias);
2095 image_view=AcquireVirtualCacheView(image,exception);
2096 blur_view=AcquireAuthenticCacheView(blur_image,exception);
2097#if defined(MAGICKCORE_OPENMP_SUPPORT)
2098 #pragma omp parallel for schedule(static) shared(progress,status) \
2099 magick_number_threads(image,blur_image,image->rows,1)
2101 for (y=0; y < (ssize_t) image->rows; y++)
2104 *magick_restrict blur_indexes;
2112 if (status == MagickFalse)
2114 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
2116 if (q == (PixelPacket *) NULL)
2121 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
2122 for (x=0; x < (ssize_t) image->columns; x++)
2131 *magick_restrict indexes;
2141 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
2143 for (i=0; i < (ssize_t) width; i++)
2145 (void) GetOneCacheViewVirtualPixel(image_view,x+offset[i].x,y+
2146 offset[i].y,&pixel,exception);
2147 qixel.red+=(*k)*(double) pixel.red;
2148 qixel.green+=(*k)*(double) pixel.green;
2149 qixel.blue+=(*k)*(double) pixel.blue;
2150 qixel.opacity+=(*k)*(double) pixel.opacity;
2151 if (image->colorspace == CMYKColorspace)
2153 indexes=GetCacheViewVirtualIndexQueue(image_view);
2154 qixel.index+=(*k)*(double) (*indexes);
2158 if ((channel & RedChannel) != 0)
2159 SetPixelRed(q,ClampToQuantum(qixel.red));
2160 if ((channel & GreenChannel) != 0)
2161 SetPixelGreen(q,ClampToQuantum(qixel.green));
2162 if ((channel & BlueChannel) != 0)
2163 SetPixelBlue(q,ClampToQuantum(qixel.blue));
2164 if ((channel & OpacityChannel) != 0)
2165 SetPixelOpacity(q,ClampToQuantum(qixel.opacity));
2166 if (((channel & IndexChannel) != 0) &&
2167 (image->colorspace == CMYKColorspace))
2168 SetPixelIndex(blur_indexes+x,ClampToQuantum(qixel.index));
2176 for (i=0; i < (ssize_t) width; i++)
2178 (void) GetOneCacheViewVirtualPixel(image_view,x+offset[i].x,y+
2179 offset[i].y,&pixel,exception);
2180 alpha=(MagickRealType) (QuantumScale*(
double)
2181 GetPixelAlpha(&pixel));
2182 qixel.red+=(*k)*alpha*(double) pixel.red;
2183 qixel.green+=(*k)*alpha*(double) pixel.green;
2184 qixel.blue+=(*k)*alpha*(double) pixel.blue;
2185 qixel.opacity+=(*k)*(double) pixel.opacity;
2186 if (image->colorspace == CMYKColorspace)
2188 indexes=GetCacheViewVirtualIndexQueue(image_view);
2189 qixel.index+=(*k)*alpha*(double) GetPixelIndex(indexes);
2194 gamma=MagickSafeReciprocal(gamma);
2195 if ((channel & RedChannel) != 0)
2196 SetPixelRed(q,ClampToQuantum(gamma*qixel.red));
2197 if ((channel & GreenChannel) != 0)
2198 SetPixelGreen(q,ClampToQuantum(gamma*qixel.green));
2199 if ((channel & BlueChannel) != 0)
2200 SetPixelBlue(q,ClampToQuantum(gamma*qixel.blue));
2201 if ((channel & OpacityChannel) != 0)
2202 SetPixelOpacity(q,ClampToQuantum(qixel.opacity));
2203 if (((channel & IndexChannel) != 0) &&
2204 (image->colorspace == CMYKColorspace))
2205 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*qixel.index));
2209 if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
2211 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2216#if defined(MAGICKCORE_OPENMP_SUPPORT)
2220 proceed=SetImageProgress(image,BlurImageTag,progress,image->rows);
2221 if (proceed == MagickFalse)
2225 blur_view=DestroyCacheView(blur_view);
2226 image_view=DestroyCacheView(image_view);
2227 kernel=(
double *) RelinquishAlignedMemory(kernel);
2228 offset=(OffsetInfo *) RelinquishMagickMemory(offset);
2229 if (status == MagickFalse)
2230 blur_image=DestroyImage(blur_image);
2268MagickExport Image *KuwaharaImage(
const Image *image,
const double radius,
2269 const double sigma,ExceptionInfo *exception)
2274 kuwahara_image=KuwaharaImageChannel(image,DefaultChannels,radius,sigma,
2276 return(kuwahara_image);
2279MagickExport Image *KuwaharaImageChannel(
const Image *image,
2280 const ChannelType channel,
const double radius,
const double sigma,
2281 ExceptionInfo *exception)
2283#define KuwaharaImageTag "Kiwahara/Image"
2308 assert(image != (Image *) NULL);
2309 assert(image->signature == MagickCoreSignature);
2310 assert(exception != (ExceptionInfo *) NULL);
2311 assert(exception->signature == MagickCoreSignature);
2312 if (IsEventLogging() != MagickFalse)
2313 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2315 width=(size_t) radius+1;
2316 gaussian_image=BlurImage(image,radius,sigma,exception);
2317 if (gaussian_image == (Image *) NULL)
2318 return((Image *) NULL);
2319 kuwahara_image=CloneImage(image,0,0,MagickTrue,exception);
2320 if (kuwahara_image == (Image *) NULL)
2322 gaussian_image=DestroyImage(gaussian_image);
2323 return((Image *) NULL);
2325 if (SetImageStorageClass(kuwahara_image,DirectClass) == MagickFalse)
2327 InheritException(exception,&kuwahara_image->exception);
2328 gaussian_image=DestroyImage(gaussian_image);
2329 kuwahara_image=DestroyImage(kuwahara_image);
2330 return((Image *) NULL);
2337 image_view=AcquireVirtualCacheView(gaussian_image,exception);
2338 kuwahara_view=AcquireAuthenticCacheView(kuwahara_image,exception);
2339#if defined(MAGICKCORE_OPENMP_SUPPORT)
2340 #pragma omp parallel for schedule(static) shared(progress,status) \
2341 magick_number_threads(image,kuwahara_image,kuwahara_image->rows,1)
2343 for (y=0; y < (ssize_t) kuwahara_image->rows; y++)
2346 *magick_restrict kuwahara_indexes;
2354 if (status == MagickFalse)
2356 q=QueueCacheViewAuthenticPixels(kuwahara_view,0,y,kuwahara_image->columns,1,
2358 if (q == (PixelPacket *) NULL)
2363 kuwahara_indexes=GetCacheViewAuthenticIndexQueue(kuwahara_view);
2364 for (x=0; x < (ssize_t) kuwahara_image->columns; x++)
2379 min_variance=MagickMaximumValue;
2380 SetGeometry(gaussian_image,&target);
2381 quadrant.width=width;
2382 quadrant.height=width;
2383 for (i=0; i < 4; i++)
2406 quadrant.x=x-(ssize_t) (width-1);
2407 quadrant.y=y-(ssize_t) (width-1);
2412 quadrant.y=y-(ssize_t) (width-1);
2417 quadrant.x=x-(ssize_t) (width-1);
2423 p=GetCacheViewVirtualPixels(image_view,quadrant.x,quadrant.y,
2424 quadrant.width,quadrant.height,exception);
2425 if (p == (
const PixelPacket *) NULL)
2427 GetMagickPixelPacket(image,&mean);
2429 for (n=0; n < (ssize_t) (width*width); n++)
2431 mean.red+=(double) k->red;
2432 mean.green+=(double) k->green;
2433 mean.blue+=(double) k->blue;
2436 mean.red/=(double) (width*width);
2437 mean.green/=(double) (width*width);
2438 mean.blue/=(double) (width*width);
2441 for (n=0; n < (ssize_t) (width*width); n++)
2446 luma=GetPixelLuma(image,k);
2447 variance+=(luma-MagickPixelLuma(&mean))*(luma-MagickPixelLuma(&mean));
2450 if (variance < min_variance)
2452 min_variance=variance;
2461 status=InterpolateMagickPixelPacket(gaussian_image,image_view,
2462 UndefinedInterpolatePixel,(
double) target.x+target.width/2.0,
2463 (
double) target.y+target.height/2.0,&pixel,exception);
2464 if (status == MagickFalse)
2466 SetPixelPacket(kuwahara_image,&pixel,q,kuwahara_indexes+x);
2469 if (SyncCacheViewAuthenticPixels(kuwahara_view,exception) == MagickFalse)
2471 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2476#if defined(MAGICKCORE_OPENMP_SUPPORT)
2480 proceed=SetImageProgress(image,KuwaharaImageTag,progress,image->rows);
2481 if (proceed == MagickFalse)
2485 kuwahara_view=DestroyCacheView(kuwahara_view);
2486 image_view=DestroyCacheView(image_view);
2487 gaussian_image=DestroyImage(gaussian_image);
2488 if (status == MagickFalse)
2489 kuwahara_image=DestroyImage(kuwahara_image);
2490 return(kuwahara_image);
2526MagickExport Image *LocalContrastImage(
const Image *image,
const double radius,
2527 const double strength,ExceptionInfo *exception)
2529#define LocalContrastImageTag "LocalContrast/Image"
2557 assert(image != (
const Image *) NULL);
2558 assert(image->signature == MagickCoreSignature);
2559 assert(exception != (ExceptionInfo *) NULL);
2560 assert(exception->signature == MagickCoreSignature);
2561 if (IsEventLogging() != MagickFalse)
2562 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2563#if defined(MAGICKCORE_OPENCL_SUPPORT)
2564 contrast_image=AccelerateLocalContrastImage(image,radius,strength,exception);
2565 if (contrast_image != (Image *) NULL)
2566 return(contrast_image);
2568 contrast_image=CloneImage(image,0,0,MagickTrue,exception);
2569 if (contrast_image == (Image *) NULL)
2570 return((Image *) NULL);
2571 if (SetImageStorageClass(contrast_image,DirectClass) == MagickFalse)
2573 InheritException(exception,&contrast_image->exception);
2574 contrast_image=DestroyImage(contrast_image);
2575 return((Image *) NULL);
2577 image_view=AcquireVirtualCacheView(image,exception);
2578 contrast_view=AcquireAuthenticCacheView(contrast_image,exception);
2579 scanLineSize=(ssize_t) MagickMax(image->columns,image->rows);
2580 width=(ssize_t) scanLineSize*0.002*fabs(radius);
2581 scanLineSize+=(2*width);
2582 scanline_info=AcquireVirtualMemory(GetOpenMPMaximumThreads()*
2583 scanLineSize,
sizeof(*scanline));
2584 if (scanline_info == (MemoryInfo *) NULL)
2586 contrast_view=DestroyCacheView(contrast_view);
2587 image_view=DestroyCacheView(image_view);
2588 contrast_image=DestroyImage(contrast_image);
2589 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2591 scanline=(
float *) GetVirtualMemoryBlob(scanline_info);
2595 interImage_info=AcquireVirtualMemory(image->rows*(image->columns+(2*width)),
2596 sizeof(*interImage));
2597 if (interImage_info == (MemoryInfo *) NULL)
2599 scanline_info=RelinquishVirtualMemory(scanline_info);
2600 contrast_view=DestroyCacheView(contrast_view);
2601 image_view=DestroyCacheView(image_view);
2602 contrast_image=DestroyImage(contrast_image);
2603 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2605 interImage=(
float *) GetVirtualMemoryBlob(interImage_info);
2606 totalWeight=(width+1)*(width+1);
2615#if defined(MAGICKCORE_OPENMP_SUPPORT)
2616 #pragma omp parallel for schedule(static) \
2617 magick_number_threads(image,image,image->columns,1)
2619 for (x=0; x < (ssize_t) image->columns; x++)
2622 id = GetOpenMPThreadId();
2638 if (status == MagickFalse)
2641 pixels+=
id*scanLineSize;
2643 p=GetCacheViewVirtualPixels(image_view,x,-width,1,image->rows+(2*width),
2645 if (p == (
const PixelPacket *) NULL)
2650 for (y=0; y < (ssize_t) image->rows+(2*width); y++)
2652 *pix++=(float)GetPixelLuma(image,p);
2655 out=interImage+x+width;
2656 for (y=0; y < (ssize_t) image->rows; y++)
2665 for (i=0; i < width; i++)
2667 sum+=weight*(*pix++);
2670 for (i=width+1; i < (2*width); i++)
2672 sum+=weight*(*pix++);
2676 *out=sum/totalWeight;
2678 if (x <= width && x != 0)
2680 if ((x > (ssize_t) image->columns-width-2) &&
2681 (x != (ssize_t) image->columns-1))
2682 *(out+((image->columns-x-1)*2))=*out;
2683 out+=image->columns+(width*2);
2694#if defined(MAGICKCORE_OPENMP_SUPPORT)
2695#pragma omp parallel for schedule(static) \
2696 magick_number_threads(image,image,image->rows,1)
2698 for (y=0; y < (ssize_t) image->rows; y++)
2701 id = GetOpenMPThreadId();
2719 if (status == MagickFalse)
2722 pixels+=
id*scanLineSize;
2723 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,
2725 q=GetCacheViewAuthenticPixels(contrast_view,0,y,image->columns,1,
2727 if ((p == (
const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
2732 memcpy(pixels,interImage+(y*(image->columns+(2*width))),(image->columns+
2733 (2*width))*
sizeof(
float));
2734 for (x=0; x < (ssize_t) image->columns; x++)
2745 for (i=0; i < width; i++)
2747 sum+=weight*(*pix++);
2750 for (i=width+1; i < (2*width); i++)
2752 sum+=weight*(*pix++);
2756 srcVal=(float) GetPixelLuma(image,p);
2757 mult=(srcVal-(sum/totalWeight))*(
float) (0.01*strength);
2758 mult=(srcVal+mult)/srcVal;
2759 SetPixelRed(q,ClampToQuantum((MagickRealType) GetPixelRed(p)*
2760 (MagickRealType) mult));
2761 SetPixelGreen(q,ClampToQuantum((MagickRealType) GetPixelGreen(p)*
2762 (MagickRealType) mult));
2763 SetPixelBlue(q,ClampToQuantum((MagickRealType) GetPixelBlue(p)*
2764 (MagickRealType) mult));
2768 if (SyncCacheViewAuthenticPixels(contrast_view,exception) == MagickFalse)
2772 scanline_info=RelinquishVirtualMemory(scanline_info);
2773 interImage_info=RelinquishVirtualMemory(interImage_info);
2774 contrast_view=DestroyCacheView(contrast_view);
2775 image_view=DestroyCacheView(image_view);
2776 if (status == MagickFalse)
2777 contrast_image=DestroyImage(contrast_image);
2778 return(contrast_image);
2811MagickExport Image *PreviewImage(
const Image *image,
const PreviewType preview,
2812 ExceptionInfo *exception)
2814#define NumberTiles 9
2815#define PreviewImageTag "Preview/Image"
2816#define DefaultPreviewGeometry "204x204+10+10"
2819 factor[MaxTextExtent],
2820 label[MaxTextExtent];
2862 assert(image != (Image *) NULL);
2863 assert(image->signature == MagickCoreSignature);
2864 if (IsEventLogging() != MagickFalse)
2865 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2869 preview_info=AcquireImageInfo();
2870 SetGeometry(image,&geometry);
2871 (void) ParseMetaGeometry(DefaultPreviewGeometry,&geometry.x,&geometry.y,
2872 &geometry.width,&geometry.height);
2873 images=NewImageList();
2875 GetQuantizeInfo(&quantize_info);
2881 for (i=0; i < NumberTiles; i++)
2883 thumbnail=ThumbnailImage(image,geometry.width,geometry.height,exception);
2884 if (thumbnail == (Image *) NULL)
2886 (void) SetImageProgressMonitor(thumbnail,(MagickProgressMonitor) NULL,
2888 (void) SetImageProperty(thumbnail,
"label",DefaultTileLabel);
2889 if (i == (NumberTiles/2))
2891 (void) QueryColorDatabase(
"#dfdfdf",&thumbnail->matte_color,exception);
2892 AppendImageToList(&images,thumbnail);
2900 preview_image=RotateImage(thumbnail,degrees,exception);
2901 (void) FormatLocaleString(label,MaxTextExtent,
"rotate %g",degrees);
2907 preview_image=ShearImage(thumbnail,degrees,degrees,exception);
2908 (void) FormatLocaleString(label,MaxTextExtent,
"shear %gx%g",
2909 degrees,2.0*degrees);
2914 x=(ssize_t) ((i+1)*thumbnail->columns)/NumberTiles;
2915 y=(ssize_t) ((i+1)*thumbnail->rows)/NumberTiles;
2916 preview_image=RollImage(thumbnail,x,y,exception);
2917 (void) FormatLocaleString(label,MaxTextExtent,
"roll %+.20gx%+.20g",
2918 (
double) x,(
double) y);
2923 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2924 if (preview_image == (Image *) NULL)
2926 (void) FormatLocaleString(factor,MaxTextExtent,
"100,100,%g",
2928 (void) ModulateImage(preview_image,factor);
2929 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2932 case SaturationPreview:
2934 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2935 if (preview_image == (Image *) NULL)
2937 (void) FormatLocaleString(factor,MaxTextExtent,
"100,%g",2.0*percentage);
2938 (void) ModulateImage(preview_image,factor);
2939 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2942 case BrightnessPreview:
2944 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2945 if (preview_image == (Image *) NULL)
2947 (void) FormatLocaleString(factor,MaxTextExtent,
"%g",2.0*percentage);
2948 (void) ModulateImage(preview_image,factor);
2949 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2955 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2956 if (preview_image == (Image *) NULL)
2959 (void) GammaImageChannel(preview_image,DefaultChannels,gamma);
2960 (void) FormatLocaleString(label,MaxTextExtent,
"gamma %g",gamma);
2965 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2966 if (preview_image != (Image *) NULL)
2967 for (x=0; x < i; x++)
2968 (
void) ContrastImage(preview_image,MagickTrue);
2969 (void) FormatLocaleString(label,MaxTextExtent,
"contrast (%.20g)",
2975 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2976 if (preview_image == (Image *) NULL)
2978 for (x=0; x < i; x++)
2979 (
void) ContrastImage(preview_image,MagickFalse);
2980 (void) FormatLocaleString(label,MaxTextExtent,
"+contrast (%.20g)",
2984 case GrayscalePreview:
2986 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2987 if (preview_image == (Image *) NULL)
2990 quantize_info.number_colors=colors;
2991 quantize_info.colorspace=GRAYColorspace;
2992 (void) QuantizeImage(&quantize_info,preview_image);
2993 (void) FormatLocaleString(label,MaxTextExtent,
2994 "-colorspace gray -colors %.20g",(
double) colors);
2997 case QuantizePreview:
2999 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3000 if (preview_image == (Image *) NULL)
3003 quantize_info.number_colors=colors;
3004 (void) QuantizeImage(&quantize_info,preview_image);
3005 (void) FormatLocaleString(label,MaxTextExtent,
"colors %.20g",(
double)
3009 case DespecklePreview:
3011 for (x=0; x < (i-1); x++)
3013 preview_image=DespeckleImage(thumbnail,exception);
3014 if (preview_image == (Image *) NULL)
3016 thumbnail=DestroyImage(thumbnail);
3017 thumbnail=preview_image;
3019 preview_image=DespeckleImage(thumbnail,exception);
3020 if (preview_image == (Image *) NULL)
3022 (void) FormatLocaleString(label,MaxTextExtent,
"despeckle (%.20g)",
3026 case ReduceNoisePreview:
3028 preview_image=StatisticImage(thumbnail,NonpeakStatistic,(
size_t) radius,
3029 (
size_t) radius,exception);
3030 (void) FormatLocaleString(label,MaxTextExtent,
"noise %g",radius);
3033 case AddNoisePreview:
3039 (void) CopyMagickString(factor,
"uniform",MaxTextExtent);
3044 (void) CopyMagickString(factor,
"gaussian",MaxTextExtent);
3049 (void) CopyMagickString(factor,
"multiplicative",MaxTextExtent);
3054 (void) CopyMagickString(factor,
"impulse",MaxTextExtent);
3059 (void) CopyMagickString(factor,
"laplacian",MaxTextExtent);
3064 (void) CopyMagickString(factor,
"poisson",MaxTextExtent);
3069 (void) CopyMagickString(thumbnail->magick,
"NULL",MaxTextExtent);
3073 preview_image=StatisticImage(thumbnail,NonpeakStatistic,(
size_t) i,
3074 (
size_t) i,exception);
3075 (void) FormatLocaleString(label,MaxTextExtent,
"+noise %s",factor);
3078 case SharpenPreview:
3080 preview_image=SharpenImage(thumbnail,radius,sigma,exception);
3081 (void) FormatLocaleString(label,MaxTextExtent,
"sharpen %gx%g",
3087 preview_image=BlurImage(thumbnail,radius,sigma,exception);
3088 (void) FormatLocaleString(label,MaxTextExtent,
"blur %gx%g",radius,
3092 case ThresholdPreview:
3094 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3095 if (preview_image == (Image *) NULL)
3097 (void) BilevelImage(thumbnail,
3098 (
double) (percentage*((MagickRealType) QuantumRange+1.0))/100.0);
3099 (void) FormatLocaleString(label,MaxTextExtent,
"threshold %g",
3100 (
double) (percentage*((MagickRealType) QuantumRange+1.0))/100.0);
3103 case EdgeDetectPreview:
3105 preview_image=EdgeImage(thumbnail,radius,exception);
3106 (void) FormatLocaleString(label,MaxTextExtent,
"edge %g",radius);
3111 preview_image=SpreadImage(thumbnail,radius,exception);
3112 (void) FormatLocaleString(label,MaxTextExtent,
"spread %g",
3116 case SolarizePreview:
3118 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3119 if (preview_image == (Image *) NULL)
3121 (void) SolarizeImage(preview_image,(
double) QuantumRange*
3123 (void) FormatLocaleString(label,MaxTextExtent,
"solarize %g",
3124 ((
double) QuantumRange*percentage)/100.0);
3130 preview_image=ShadeImage(thumbnail,MagickTrue,degrees,degrees,
3132 (void) FormatLocaleString(label,MaxTextExtent,
"shade %gx%g",
3141 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3142 if (preview_image == (Image *) NULL)
3144 raise.width=(size_t) (2*i+2);
3145 raise.height=(size_t) (2*i+2);
3148 (void) RaiseImage(preview_image,&raise,MagickTrue);
3149 (void) FormatLocaleString(label,MaxTextExtent,
3150 "raise %.20gx%.20g%+.20g%+.20g",(
double) raise.width,(
double)
3151 raise.height,(
double) raise.x,(
double) raise.y);
3154 case SegmentPreview:
3156 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3157 if (preview_image == (Image *) NULL)
3160 (void) SegmentImage(preview_image,sRGBColorspace,MagickFalse,threshold,
3162 (void) FormatLocaleString(label,MaxTextExtent,
"segment %gx%g",
3163 threshold,threshold);
3168 preview_image=SwirlImage(thumbnail,degrees,exception);
3169 (void) FormatLocaleString(label,MaxTextExtent,
"swirl %g",degrees);
3173 case ImplodePreview:
3176 preview_image=ImplodeImage(thumbnail,degrees,exception);
3177 (void) FormatLocaleString(label,MaxTextExtent,
"implode %g",degrees);
3183 preview_image=WaveImage(thumbnail,0.5*degrees,2.0*degrees,exception);
3184 (void) FormatLocaleString(label,MaxTextExtent,
"wave %gx%g",
3185 0.5*degrees,2.0*degrees);
3188 case OilPaintPreview:
3190 preview_image=OilPaintImage(thumbnail,(
double) radius,exception);
3191 (void) FormatLocaleString(label,MaxTextExtent,
"paint %g",radius);
3194 case CharcoalDrawingPreview:
3196 preview_image=CharcoalImage(thumbnail,(
double) radius,(
double) sigma,
3198 (void) FormatLocaleString(label,MaxTextExtent,
"charcoal %gx%g",
3205 filename[MaxTextExtent];
3213 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3214 if (preview_image == (Image *) NULL)
3216 preview_info->quality=(size_t) percentage;
3217 (void) FormatLocaleString(factor,MaxTextExtent,
"%.20g",(
double)
3218 preview_info->quality);
3219 file=AcquireUniqueFileResource(filename);
3221 file=close_utf8(file)-1;
3222 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,
3223 "jpeg:%s",filename);
3224 status=WriteImage(preview_info,preview_image);
3225 if (status != MagickFalse)
3230 (void) CopyMagickString(preview_info->filename,
3231 preview_image->filename,MaxTextExtent);
3232 quality_image=ReadImage(preview_info,exception);
3233 if (quality_image != (Image *) NULL)
3235 preview_image=DestroyImage(preview_image);
3236 preview_image=quality_image;
3239 (void) RelinquishUniqueFileResource(preview_image->filename);
3240 if ((GetBlobSize(preview_image)/1024) >= 1024)
3241 (void) FormatLocaleString(label,MaxTextExtent,
"quality %s\n%gmb ",
3242 factor,(
double) ((MagickOffsetType) GetBlobSize(preview_image))/
3245 if (GetBlobSize(preview_image) >= 1024)
3246 (void) FormatLocaleString(label,MaxTextExtent,
3247 "quality %s\n%gkb ",factor,(
double) ((MagickOffsetType)
3248 GetBlobSize(preview_image))/1024.0);
3250 (
void) FormatLocaleString(label,MaxTextExtent,
"quality %s\n%.20gb ",
3251 factor,(
double) ((MagickOffsetType) GetBlobSize(thumbnail)));
3255 thumbnail=DestroyImage(thumbnail);
3259 if (preview_image == (Image *) NULL)
3261 (void) DeleteImageProperty(preview_image,
"label");
3262 (void) SetImageProperty(preview_image,
"label",label);
3263 AppendImageToList(&images,preview_image);
3264 proceed=SetImageProgress(image,PreviewImageTag,(MagickOffsetType) i,
3266 if (proceed == MagickFalse)
3269 if (images == (Image *) NULL)
3271 preview_info=DestroyImageInfo(preview_info);
3272 return((Image *) NULL);
3277 montage_info=CloneMontageInfo(preview_info,(MontageInfo *) NULL);
3278 (void) CopyMagickString(montage_info->filename,image->filename,MaxTextExtent);
3279 montage_info->shadow=MagickTrue;
3280 (void) CloneString(&montage_info->tile,
"3x3");
3281 (void) CloneString(&montage_info->geometry,DefaultPreviewGeometry);
3282 (void) CloneString(&montage_info->frame,DefaultTileFrame);
3283 montage_image=MontageImages(images,montage_info,exception);
3284 montage_info=DestroyMontageInfo(montage_info);
3285 images=DestroyImageList(images);
3286 if (montage_image == (Image *) NULL)
3287 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3288 if (montage_image->montage != (
char *) NULL)
3293 montage_image->montage=(
char *) RelinquishMagickMemory(
3294 montage_image->montage);
3295 if (image->directory != (
char *) NULL)
3296 montage_image->directory=(
char *) RelinquishMagickMemory(
3297 montage_image->directory);
3299 preview_info=DestroyImageInfo(preview_info);
3300 return(montage_image);
3337MagickExport Image *RotationalBlurImage(
const Image *image,
const double angle,
3338 ExceptionInfo *exception)
3343 blur_image=RotationalBlurImageChannel(image,DefaultChannels,angle,exception);
3347MagickExport Image *RotationalBlurImageChannel(
const Image *image,
3348 const ChannelType channel,
const double angle,ExceptionInfo *exception)
3388 assert(image != (Image *) NULL);
3389 assert(image->signature == MagickCoreSignature);
3390 assert(exception != (ExceptionInfo *) NULL);
3391 assert(exception->signature == MagickCoreSignature);
3392 if (IsEventLogging() != MagickFalse)
3393 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3394#if defined(MAGICKCORE_OPENCL_SUPPORT)
3395 blur_image=AccelerateRadialBlurImage(image,channel,angle,exception);
3396 if (blur_image != (Image *) NULL)
3399 blur_image=CloneImage(image,0,0,MagickTrue,exception);
3400 if (blur_image == (Image *) NULL)
3401 return((Image *) NULL);
3402 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
3404 InheritException(exception,&blur_image->exception);
3405 blur_image=DestroyImage(blur_image);
3406 return((Image *) NULL);
3408 blur_center.x=(double) (image->columns-1)/2.0;
3409 blur_center.y=(double) (image->rows-1)/2.0;
3410 blur_radius=hypot(blur_center.x,blur_center.y);
3411 n=(size_t) fabs(4.0*DegreesToRadians(angle)*sqrt((
double) blur_radius)+2UL);
3412 theta=DegreesToRadians(angle)/(MagickRealType) (n-1);
3413 cos_theta=(MagickRealType *) AcquireQuantumMemory((
size_t) n,
3414 sizeof(*cos_theta));
3415 sin_theta=(MagickRealType *) AcquireQuantumMemory((
size_t) n,
3416 sizeof(*sin_theta));
3417 if ((cos_theta == (MagickRealType *) NULL) ||
3418 (sin_theta == (MagickRealType *) NULL))
3420 if (cos_theta != (MagickRealType *) NULL)
3421 cos_theta=(MagickRealType *) RelinquishMagickMemory(cos_theta);
3422 if (sin_theta != (MagickRealType *) NULL)
3423 sin_theta=(MagickRealType *) RelinquishMagickMemory(sin_theta);
3424 blur_image=DestroyImage(blur_image);
3425 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3427 offset=theta*(MagickRealType) (n-1)/2.0;
3428 for (i=0; i < (ssize_t) n; i++)
3430 cos_theta[i]=cos((
double) (theta*i-offset));
3431 sin_theta[i]=sin((
double) (theta*i-offset));
3438 GetMagickPixelPacket(image,&bias);
3439 image_view=AcquireVirtualCacheView(image,exception);
3440 blur_view=AcquireAuthenticCacheView(blur_image,exception);
3441#if defined(MAGICKCORE_OPENMP_SUPPORT)
3442 #pragma omp parallel for schedule(static) shared(progress,status) \
3443 magick_number_threads(image,blur_image,blur_image->rows,1)
3445 for (y=0; y < (ssize_t) blur_image->rows; y++)
3448 *magick_restrict indexes;
3451 *magick_restrict blur_indexes;
3459 if (status == MagickFalse)
3461 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
3463 if (q == (PixelPacket *) NULL)
3468 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
3469 for (x=0; x < (ssize_t) blur_image->columns; x++)
3490 center.x=(double) x-blur_center.x;
3491 center.y=(double) y-blur_center.y;
3492 radius=hypot((
double) center.x,center.y);
3497 step=(size_t) (blur_radius/radius);
3506 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
3508 for (i=0; i < (ssize_t) n; i+=(ssize_t) step)
3510 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t)
3511 (blur_center.x+center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),
3512 (ssize_t) (blur_center.y+center.x*sin_theta[i]+center.y*
3513 cos_theta[i]+0.5),&pixel,exception);
3514 qixel.red+=(MagickRealType) pixel.red;
3515 qixel.green+=(MagickRealType) pixel.green;
3516 qixel.blue+=(MagickRealType) pixel.blue;
3517 qixel.opacity+=(MagickRealType) pixel.opacity;
3518 if (image->colorspace == CMYKColorspace)
3520 indexes=GetCacheViewVirtualIndexQueue(image_view);
3521 qixel.index+=(MagickRealType) (*indexes);
3525 normalize=MagickSafeReciprocal(normalize);
3526 if ((channel & RedChannel) != 0)
3527 SetPixelRed(q,ClampToQuantum(normalize*qixel.red));
3528 if ((channel & GreenChannel) != 0)
3529 SetPixelGreen(q,ClampToQuantum(normalize*qixel.green));
3530 if ((channel & BlueChannel) != 0)
3531 SetPixelBlue(q,ClampToQuantum(normalize*qixel.blue));
3532 if ((channel & OpacityChannel) != 0)
3533 SetPixelOpacity(q,ClampToQuantum(normalize*qixel.opacity));
3534 if (((channel & IndexChannel) != 0) &&
3535 (image->colorspace == CMYKColorspace))
3536 SetPixelIndex(blur_indexes+x,ClampToQuantum(normalize*qixel.index));
3546 for (i=0; i < (ssize_t) n; i+=(ssize_t) step)
3548 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t)
3549 (blur_center.x+center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),
3550 (ssize_t) (blur_center.y+center.x*sin_theta[i]+center.y*
3551 cos_theta[i]+0.5),&pixel,exception);
3552 alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(&pixel));
3553 qixel.red+=alpha*(MagickRealType) pixel.red;
3554 qixel.green+=alpha*(MagickRealType) pixel.green;
3555 qixel.blue+=alpha*(MagickRealType) pixel.blue;
3556 qixel.opacity+=(MagickRealType) pixel.opacity;
3557 if (image->colorspace == CMYKColorspace)
3559 indexes=GetCacheViewVirtualIndexQueue(image_view);
3560 qixel.index+=alpha*(MagickRealType) (*indexes);
3565 gamma=MagickSafeReciprocal(gamma);
3566 normalize=MagickSafeReciprocal(normalize);
3567 if ((channel & RedChannel) != 0)
3568 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) qixel.red));
3569 if ((channel & GreenChannel) != 0)
3570 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType) qixel.green));
3571 if ((channel & BlueChannel) != 0)
3572 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType) qixel.blue));
3573 if ((channel & OpacityChannel) != 0)
3574 SetPixelOpacity(q,ClampToQuantum(normalize*(MagickRealType)
3576 if (((channel & IndexChannel) != 0) &&
3577 (image->colorspace == CMYKColorspace))
3578 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*(MagickRealType)
3583 if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
3585 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3590#if defined(MAGICKCORE_OPENMP_SUPPORT)
3594 proceed=SetImageProgress(image,BlurImageTag,progress,image->rows);
3595 if (proceed == MagickFalse)
3599 blur_view=DestroyCacheView(blur_view);
3600 image_view=DestroyCacheView(image_view);
3601 cos_theta=(MagickRealType *) RelinquishMagickMemory(cos_theta);
3602 sin_theta=(MagickRealType *) RelinquishMagickMemory(sin_theta);
3603 if (status == MagickFalse)
3604 blur_image=DestroyImage(blur_image);
3649MagickExport Image *SelectiveBlurImage(
const Image *image,
const double radius,
3650 const double sigma,
const double threshold,ExceptionInfo *exception)
3655 blur_image=SelectiveBlurImageChannel(image,DefaultChannels,radius,sigma,
3656 threshold,exception);
3660MagickExport Image *SelectiveBlurImageChannel(
const Image *image,
3661 const ChannelType channel,
const double radius,
const double sigma,
3662 const double threshold,ExceptionInfo *exception)
3664#define SelectiveBlurImageTag "SelectiveBlur/Image"
3703 assert(image != (Image *) NULL);
3704 assert(image->signature == MagickCoreSignature);
3705 assert(exception != (ExceptionInfo *) NULL);
3706 assert(exception->signature == MagickCoreSignature);
3707 if (IsEventLogging() != MagickFalse)
3708 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3709 width=GetOptimalKernelWidth1D(radius,sigma);
3710 kernel=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
3711 width*
sizeof(*kernel)));
3712 if (kernel == (
double *) NULL)
3713 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3714 j=(ssize_t) (width-1)/2;
3716 for (v=(-j); v <= j; v++)
3718 for (u=(-j); u <= j; u++)
3719 kernel[i++]=(
double) (exp(-((
double) u*u+v*v)/(2.0*MagickSigma*
3720 MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
3722 if (image->debug != MagickFalse)
3725 format[MaxTextExtent],
3735 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
3736 " SelectiveBlurImage with %.20gx%.20g kernel:",(
double) width,(
double)
3738 message=AcquireString(
"");
3740 for (v=0; v < (ssize_t) width; v++)
3743 (void) FormatLocaleString(format,MaxTextExtent,
"%.20g: ",(
double) v);
3744 (void) ConcatenateString(&message,format);
3745 for (u=0; u < (ssize_t) width; u++)
3747 (void) FormatLocaleString(format,MaxTextExtent,
"%+f ",*k++);
3748 (void) ConcatenateString(&message,format);
3750 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"%s",message);
3752 message=DestroyString(message);
3754 blur_image=CloneImage(image,0,0,MagickTrue,exception);
3755 if (blur_image == (Image *) NULL)
3757 kernel=(
double *) RelinquishAlignedMemory(kernel);
3758 return((Image *) NULL);
3760 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
3762 kernel=(
double *) RelinquishAlignedMemory(kernel);
3763 InheritException(exception,&blur_image->exception);
3764 blur_image=DestroyImage(blur_image);
3765 return((Image *) NULL);
3767 luminance_image=CloneImage(image,0,0,MagickTrue,exception);
3768 if (luminance_image == (Image *) NULL)
3770 kernel=(
double *) RelinquishAlignedMemory(kernel);
3771 blur_image=DestroyImage(blur_image);
3772 return((Image *) NULL);
3774 status=TransformImageColorspace(luminance_image,GRAYColorspace);
3775 if (status == MagickFalse)
3777 InheritException(exception,&luminance_image->exception);
3778 kernel=(
double *) RelinquishAlignedMemory(kernel);
3779 blur_image=DestroyImage(blur_image);
3780 luminance_image=DestroyImage(luminance_image);
3781 return((Image *) NULL);
3788 center=(ssize_t) ((image->columns+width)*((width-1)/2L)+((width-1)/2L));
3789 GetMagickPixelPacket(image,&bias);
3790 SetMagickPixelPacketBias(image,&bias);
3791 image_view=AcquireVirtualCacheView(image,exception);
3792 luminance_view=AcquireVirtualCacheView(luminance_image,exception);
3793 blur_view=AcquireAuthenticCacheView(blur_image,exception);
3794#if defined(MAGICKCORE_OPENMP_SUPPORT)
3795 #pragma omp parallel for schedule(static) shared(progress,status) \
3796 magick_number_threads(image,blur_image,image->rows,1)
3798 for (y=0; y < (ssize_t) image->rows; y++)
3807 *magick_restrict indexes;
3814 *magick_restrict blur_indexes;
3822 if (status == MagickFalse)
3824 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) (width-1)/2L),y-(ssize_t)
3825 ((width-1)/2L),image->columns+width,width,exception);
3826 l=GetCacheViewVirtualPixels(luminance_view,-((ssize_t) (width-1)/2L),y-
3827 (ssize_t) ((width-1)/2L),luminance_image->columns+width,width,exception);
3828 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
3830 if ((p == (
const PixelPacket *) NULL) ||
3831 (l == (
const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
3836 indexes=GetCacheViewVirtualIndexQueue(image_view);
3837 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
3838 for (x=0; x < (ssize_t) image->columns; x++)
3860 pixel.green=bias.green;
3861 pixel.blue=bias.blue;
3862 pixel.opacity=bias.opacity;
3863 pixel.index=bias.index;
3865 intensity=GetPixelIntensity(image,p+center);
3868 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
3870 for (v=0; v < (ssize_t) width; v++)
3872 for (u=0; u < (ssize_t) width; u++)
3874 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3875 if (fabs(contrast) < threshold)
3877 pixel.red+=(*k)*(MagickRealType) GetPixelRed(p+u+j);
3878 pixel.green+=(*k)*(MagickRealType) GetPixelGreen(p+u+j);
3879 pixel.blue+=(*k)*(MagickRealType) GetPixelBlue(p+u+j);
3884 j+=(ssize_t) (image->columns+width);
3888 gamma=MagickSafeReciprocal(gamma);
3889 if ((channel & RedChannel) != 0)
3890 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType)
3892 if ((channel & GreenChannel) != 0)
3893 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType)
3895 if ((channel & BlueChannel) != 0)
3896 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType)
3899 if ((channel & OpacityChannel) != 0)
3903 for (v=0; v < (ssize_t) width; v++)
3905 for (u=0; u < (ssize_t) width; u++)
3907 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3908 if (fabs(contrast) < threshold)
3910 pixel.opacity+=(*k)*(MagickRealType) (p+u+j)->opacity;
3915 j+=(ssize_t) (image->columns+width);
3917 gamma=MagickSafeReciprocal(gamma);
3918 SetPixelOpacity(q,ClampToQuantum(gamma*pixel.opacity));
3920 if (((channel & IndexChannel) != 0) &&
3921 (image->colorspace == CMYKColorspace))
3925 for (v=0; v < (ssize_t) width; v++)
3927 for (u=0; u < (ssize_t) width; u++)
3929 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3930 if (fabs(contrast) < threshold)
3932 pixel.index+=(*k)*(MagickRealType)
3933 GetPixelIndex(indexes+x+u+j);
3938 j+=(ssize_t) (image->columns+width);
3940 gamma=MagickSafeReciprocal(gamma);
3941 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*pixel.index));
3949 for (v=0; v < (ssize_t) width; v++)
3951 for (u=0; u < (ssize_t) width; u++)
3953 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3954 if (fabs(contrast) < threshold)
3956 alpha=(MagickRealType) (QuantumScale*(MagickRealType)
3957 GetPixelAlpha(p+u+j));
3958 pixel.red+=(*k)*alpha*(MagickRealType) GetPixelRed(p+u+j);
3959 pixel.green+=(*k)*alpha*(MagickRealType) GetPixelGreen(p+u+j);
3960 pixel.blue+=(*k)*alpha*(MagickRealType) GetPixelBlue(p+u+j);
3961 pixel.opacity+=(*k)*(MagickRealType) GetPixelOpacity(p+u+j);
3966 j+=(ssize_t) (image->columns+width);
3970 gamma=MagickSafeReciprocal(gamma);
3971 if ((channel & RedChannel) != 0)
3972 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) pixel.red));
3973 if ((channel & GreenChannel) != 0)
3974 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType)
3976 if ((channel & BlueChannel) != 0)
3977 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType)
3980 if ((channel & OpacityChannel) != 0)
3983 for (v=0; v < (ssize_t) width; v++)
3985 for (u=0; u < (ssize_t) width; u++)
3987 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3988 if (fabs(contrast) < threshold)
3989 pixel.opacity+=(*k)*(MagickRealType) GetPixelOpacity(p+u+j);
3992 j+=(ssize_t) (image->columns+width);
3994 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
3996 if (((channel & IndexChannel) != 0) &&
3997 (image->colorspace == CMYKColorspace))
4001 for (v=0; v < (ssize_t) width; v++)
4003 for (u=0; u < (ssize_t) width; u++)
4005 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
4006 if (fabs(contrast) < threshold)
4008 alpha=(MagickRealType) (QuantumScale*(MagickRealType)
4009 GetPixelAlpha(p+u+j));
4010 pixel.index+=(*k)*alpha*(MagickRealType)
4011 GetPixelIndex(indexes+x+u+j);
4016 j+=(ssize_t) (image->columns+width);
4018 gamma=MagickSafeReciprocal(gamma);
4019 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*pixel.index));
4026 sync=SyncCacheViewAuthenticPixels(blur_view,exception);
4027 if (sync == MagickFalse)
4029 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4034#if defined(MAGICKCORE_OPENMP_SUPPORT)
4038 proceed=SetImageProgress(image,SelectiveBlurImageTag,progress,
4040 if (proceed == MagickFalse)
4044 blur_image->type=image->type;
4045 blur_view=DestroyCacheView(blur_view);
4046 luminance_view=DestroyCacheView(luminance_view);
4047 image_view=DestroyCacheView(image_view);
4048 luminance_image=DestroyImage(luminance_image);
4049 kernel=(
double *) RelinquishAlignedMemory(kernel);
4050 if (status == MagickFalse)
4051 blur_image=DestroyImage(blur_image);
4087MagickExport Image *ShadeImage(
const Image *image,
const MagickBooleanType gray,
4088 const double azimuth,
const double elevation,ExceptionInfo *exception)
4090#define GetShadeIntensity(image,pixel) \
4091 ClampPixel(GetPixelIntensity((image),(pixel)))
4092#define ShadeImageTag "Shade/Image"
4117 assert(image != (
const Image *) NULL);
4118 assert(image->signature == MagickCoreSignature);
4119 assert(exception != (ExceptionInfo *) NULL);
4120 assert(exception->signature == MagickCoreSignature);
4121 if (IsEventLogging() != MagickFalse)
4122 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4123 linear_image=CloneImage(image,0,0,MagickTrue,exception);
4124 shade_image=CloneImage(image,0,0,MagickTrue,exception);
4125 if ((linear_image == (Image *) NULL) || (shade_image == (Image *) NULL))
4127 if (linear_image != (Image *) NULL)
4128 linear_image=DestroyImage(linear_image);
4129 if (shade_image != (Image *) NULL)
4130 shade_image=DestroyImage(shade_image);
4131 return((Image *) NULL);
4133 if (SetImageStorageClass(shade_image,DirectClass) == MagickFalse)
4135 InheritException(exception,&shade_image->exception);
4136 linear_image=DestroyImage(linear_image);
4137 shade_image=DestroyImage(shade_image);
4138 return((Image *) NULL);
4143 light.x=(double) QuantumRange*cos(DegreesToRadians(azimuth))*
4144 cos(DegreesToRadians(elevation));
4145 light.y=(double) QuantumRange*sin(DegreesToRadians(azimuth))*
4146 cos(DegreesToRadians(elevation));
4147 light.z=(double) QuantumRange*sin(DegreesToRadians(elevation));
4153 image_view=AcquireVirtualCacheView(linear_image,exception);
4154 shade_view=AcquireAuthenticCacheView(shade_image,exception);
4155#if defined(MAGICKCORE_OPENMP_SUPPORT)
4156 #pragma omp parallel for schedule(static) shared(progress,status) \
4157 magick_number_threads(linear_image,shade_image,linear_image->rows,1)
4159 for (y=0; y < (ssize_t) linear_image->rows; y++)
4171 *magick_restrict s0,
4172 *magick_restrict s1,
4173 *magick_restrict s2;
4181 if (status == MagickFalse)
4183 p=GetCacheViewVirtualPixels(image_view,-1,y-1,linear_image->columns+2,3,
4185 q=QueueCacheViewAuthenticPixels(shade_view,0,y,shade_image->columns,1,
4187 if ((p == (PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
4195 normal.z=2.0*(double) QuantumRange;
4196 for (x=0; x < (ssize_t) linear_image->columns; x++)
4202 s1=s0+image->columns+2;
4203 s2=s1+image->columns+2;
4204 normal.x=(double) (GetShadeIntensity(linear_image,s0-1)+
4205 GetShadeIntensity(linear_image,s1-1)+
4206 GetShadeIntensity(linear_image,s2-1)-
4207 GetShadeIntensity(linear_image,s0+1)-
4208 GetShadeIntensity(linear_image,s1+1)-
4209 GetShadeIntensity(linear_image,s2+1));
4210 normal.y=(double) (GetShadeIntensity(linear_image,s2-1)+
4211 GetShadeIntensity(linear_image,s2)+
4212 GetShadeIntensity(linear_image,s2+1)-
4213 GetShadeIntensity(linear_image,s0-1)-
4214 GetShadeIntensity(linear_image,s0)-
4215 GetShadeIntensity(linear_image,s0+1));
4216 if ((fabs(normal.x) <= MagickEpsilon) &&
4217 (fabs(normal.y) <= MagickEpsilon))
4222 distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
4223 if (distance > MagickEpsilon)
4225 normal_distance=normal.x*normal.x+normal.y*normal.y+normal.z*
4227 if (normal_distance > (MagickEpsilon*MagickEpsilon))
4228 shade=distance/sqrt((
double) normal_distance);
4231 if (gray != MagickFalse)
4233 SetPixelRed(q,shade);
4234 SetPixelGreen(q,shade);
4235 SetPixelBlue(q,shade);
4239 SetPixelRed(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4241 SetPixelGreen(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4242 GetPixelGreen(s1)));
4243 SetPixelBlue(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4246 q->opacity=s1->opacity;
4250 if (SyncCacheViewAuthenticPixels(shade_view,exception) == MagickFalse)
4252 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4257#if defined(MAGICKCORE_OPENMP_SUPPORT)
4261 proceed=SetImageProgress(image,ShadeImageTag,progress,image->rows);
4262 if (proceed == MagickFalse)
4266 shade_view=DestroyCacheView(shade_view);
4267 image_view=DestroyCacheView(image_view);
4268 linear_image=DestroyImage(linear_image);
4269 if (status == MagickFalse)
4270 shade_image=DestroyImage(shade_image);
4271 return(shade_image);
4317MagickExport Image *SharpenImage(
const Image *image,
const double radius,
4318 const double sigma,ExceptionInfo *exception)
4323 sharp_image=SharpenImageChannel(image,DefaultChannels,radius,sigma,exception);
4324 return(sharp_image);
4327MagickExport Image *SharpenImageChannel(
const Image *image,
4328 const ChannelType channel,
const double radius,
const double sigma,
4329 ExceptionInfo *exception)
4352 assert(image != (
const Image *) NULL);
4353 assert(image->signature == MagickCoreSignature);
4354 assert(exception != (ExceptionInfo *) NULL);
4355 assert(exception->signature == MagickCoreSignature);
4356 if (IsEventLogging() != MagickFalse)
4357 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4358 width=GetOptimalKernelWidth2D(radius,sigma);
4359 kernel_info=AcquireKernelInfo((
const char *) NULL);
4361 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
4362 (void) memset(kernel_info,0,
sizeof(*kernel_info));
4363 kernel_info->width=width;
4364 kernel_info->height=width;
4365 kernel_info->x=(ssize_t) (width-1)/2;
4366 kernel_info->y=(ssize_t) (width-1)/2;
4367 kernel_info->signature=MagickCoreSignature;
4368 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
4369 kernel_info->width,kernel_info->height*
sizeof(*kernel_info->values)));
4370 if (kernel_info->values == (
double *) NULL)
4372 kernel_info=DestroyKernelInfo(kernel_info);
4373 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
4376 j=(ssize_t) (kernel_info->width-1)/2;
4378 for (v=(-j); v <= j; v++)
4380 for (u=(-j); u <= j; u++)
4382 kernel_info->values[i]=(double) (-exp(-((
double) u*u+v*v)/(2.0*
4383 MagickSigma*MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
4384 normalize+=kernel_info->values[i];
4388 kernel_info->values[i/2]=(double) ((-2.0)*normalize);
4390 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
4391 normalize+=kernel_info->values[i];
4392 gamma=MagickSafeReciprocal(normalize);
4393 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
4394 kernel_info->values[i]*=gamma;
4395 sharp_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
4396 kernel_info,exception);
4397 kernel_info=DestroyKernelInfo(kernel_info);
4398 return(sharp_image);
4429MagickExport Image *SpreadImage(
const Image *image,
const double radius,
4430 ExceptionInfo *exception)
4432#define SpreadImageTag "Spread/Image"
4451 **magick_restrict random_info;
4459#if defined(MAGICKCORE_OPENMP_SUPPORT)
4467 assert(image != (Image *) NULL);
4468 assert(image->signature == MagickCoreSignature);
4469 assert(exception != (ExceptionInfo *) NULL);
4470 assert(exception->signature == MagickCoreSignature);
4471 if (IsEventLogging() != MagickFalse)
4472 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4473 spread_image=CloneImage(image,0,0,MagickTrue,exception);
4474 if (spread_image == (Image *) NULL)
4475 return((Image *) NULL);
4476 if (SetImageStorageClass(spread_image,DirectClass) == MagickFalse)
4478 InheritException(exception,&spread_image->exception);
4479 spread_image=DestroyImage(spread_image);
4480 return((Image *) NULL);
4487 GetMagickPixelPacket(spread_image,&bias);
4488 width=GetOptimalKernelWidth1D(radius,0.5);
4489 random_info=AcquireRandomInfoTLS();
4490 image_view=AcquireVirtualCacheView(image,exception);
4491 spread_view=AcquireAuthenticCacheView(spread_image,exception);
4492#if defined(MAGICKCORE_OPENMP_SUPPORT)
4493 key=GetRandomSecretKey(random_info[0]);
4494 #pragma omp parallel for schedule(static) shared(progress,status) \
4495 magick_number_threads(image,spread_image,spread_image->rows,key == ~0UL)
4497 for (y=0; y < (ssize_t) spread_image->rows; y++)
4500 id = GetOpenMPThreadId();
4506 *magick_restrict indexes;
4514 if (status == MagickFalse)
4516 q=QueueCacheViewAuthenticPixels(spread_view,0,y,spread_image->columns,1,
4518 if (q == (PixelPacket *) NULL)
4523 indexes=GetCacheViewAuthenticIndexQueue(spread_view);
4525 for (x=0; x < (ssize_t) spread_image->columns; x++)
4530 point.x=GetPseudoRandomValue(random_info[
id]);
4531 point.y=GetPseudoRandomValue(random_info[
id]);
4532 status=InterpolateMagickPixelPacket(image,image_view,image->interpolate,
4533 (
double) x+width*(point.x-0.5),(
double) y+width*(point.y-0.5),&pixel,
4535 if (status == MagickFalse)
4537 SetPixelPacket(spread_image,&pixel,q,indexes+x);
4540 if (SyncCacheViewAuthenticPixels(spread_view,exception) == MagickFalse)
4542 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4547#if defined(MAGICKCORE_OPENMP_SUPPORT)
4551 proceed=SetImageProgress(image,SpreadImageTag,progress,image->rows);
4552 if (proceed == MagickFalse)
4556 spread_view=DestroyCacheView(spread_view);
4557 image_view=DestroyCacheView(image_view);
4558 random_info=DestroyRandomInfoTLS(random_info);
4559 if (status == MagickFalse)
4560 spread_image=DestroyImage(spread_image);
4561 return(spread_image);
4609MagickExport Image *UnsharpMaskImage(
const Image *image,
const double radius,
4610 const double sigma,
const double gain,
const double threshold,
4611 ExceptionInfo *exception)
4617 sharp_image=UnsharpMaskImageChannel(image,DefaultChannels,radius,sigma,gain,
4618 threshold,exception);
4620 return(sharp_image);
4623MagickExport Image *UnsharpMaskImageChannel(
const Image *image,
4624 const ChannelType channel,
const double radius,
const double sigma,
4625 const double gain,
const double threshold,ExceptionInfo *exception)
4627#define SharpenImageTag "Sharpen/Image"
4651 assert(image != (
const Image *) NULL);
4652 assert(image->signature == MagickCoreSignature);
4653 assert(exception != (ExceptionInfo *) NULL);
4654 assert(exception->signature == MagickCoreSignature);
4655 if (IsEventLogging() != MagickFalse)
4656 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4665 unsharp_image=BlurImageChannel(image,(ChannelType) (channel &~ SyncChannels),
4666 radius,sigma,exception);
4667 if (unsharp_image == (Image *) NULL)
4668 return((Image *) NULL);
4669 quantum_threshold=(MagickRealType) QuantumRange*threshold;
4675 GetMagickPixelPacket(image,&bias);
4676 image_view=AcquireVirtualCacheView(image,exception);
4677 unsharp_view=AcquireAuthenticCacheView(unsharp_image,exception);
4678#if defined(MAGICKCORE_OPENMP_SUPPORT)
4679 #pragma omp parallel for schedule(static) shared(progress,status) \
4680 magick_number_threads(image,unsharp_image,image->rows,1)
4682 for (y=0; y < (ssize_t) image->rows; y++)
4688 *magick_restrict indexes;
4694 *magick_restrict unsharp_indexes;
4702 if (status == MagickFalse)
4704 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
4705 q=GetCacheViewAuthenticPixels(unsharp_view,0,y,unsharp_image->columns,1,
4707 if ((p == (
const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
4712 indexes=GetCacheViewVirtualIndexQueue(image_view);
4713 unsharp_indexes=GetCacheViewAuthenticIndexQueue(unsharp_view);
4715 pixel.green=bias.green;
4716 pixel.blue=bias.blue;
4717 pixel.opacity=bias.opacity;
4718 pixel.index=bias.index;
4719 for (x=0; x < (ssize_t) image->columns; x++)
4721 if ((channel & RedChannel) != 0)
4723 pixel.red=(MagickRealType) GetPixelRed(p)-(MagickRealType)
4725 if (fabs(2.0*pixel.red) < quantum_threshold)
4726 pixel.red=(MagickRealType) GetPixelRed(p);
4728 pixel.red=(MagickRealType) GetPixelRed(p)+(pixel.red*gain);
4729 SetPixelRed(q,ClampToQuantum(pixel.red));
4731 if ((channel & GreenChannel) != 0)
4733 pixel.green=(MagickRealType) GetPixelGreen(p)-(MagickRealType)
4735 if (fabs(2.0*pixel.green) < quantum_threshold)
4736 pixel.green=(MagickRealType) GetPixelGreen(p);
4738 pixel.green=(MagickRealType) GetPixelGreen(p)+(pixel.green*gain);
4739 SetPixelGreen(q,ClampToQuantum(pixel.green));
4741 if ((channel & BlueChannel) != 0)
4743 pixel.blue=(MagickRealType) GetPixelBlue(p)-(MagickRealType) q->blue;
4744 if (fabs(2.0*pixel.blue) < quantum_threshold)
4745 pixel.blue=(MagickRealType) GetPixelBlue(p);
4747 pixel.blue=(MagickRealType) GetPixelBlue(p)+(pixel.blue*gain);
4748 SetPixelBlue(q,ClampToQuantum(pixel.blue));
4750 if ((channel & OpacityChannel) != 0)
4752 pixel.opacity=(MagickRealType) GetPixelOpacity(p)-(MagickRealType)
4754 if (fabs(2.0*pixel.opacity) < quantum_threshold)
4755 pixel.opacity=(MagickRealType) GetPixelOpacity(p);
4757 pixel.opacity=(MagickRealType) GetPixelOpacity(p)+
4758 (pixel.opacity*gain);
4759 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
4761 if (((channel & IndexChannel) != 0) &&
4762 (image->colorspace == CMYKColorspace))
4764 pixel.index=(MagickRealType) GetPixelIndex(indexes+x)-
4765 (MagickRealType) GetPixelIndex(unsharp_indexes+x);
4766 if (fabs(2.0*pixel.index) < quantum_threshold)
4767 pixel.index=(MagickRealType) GetPixelIndex(indexes+x);
4769 pixel.index=(MagickRealType) GetPixelIndex(indexes+x)+
4771 SetPixelIndex(unsharp_indexes+x,ClampToQuantum(pixel.index));
4776 if (SyncCacheViewAuthenticPixels(unsharp_view,exception) == MagickFalse)
4778 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4783#if defined(MAGICKCORE_OPENMP_SUPPORT)
4787 proceed=SetImageProgress(image,SharpenImageTag,progress,image->rows);
4788 if (proceed == MagickFalse)
4792 unsharp_image->type=image->type;
4793 unsharp_view=DestroyCacheView(unsharp_view);
4794 image_view=DestroyCacheView(image_view);
4795 if (status == MagickFalse)
4796 unsharp_image=DestroyImage(unsharp_image);
4797 return(unsharp_image);