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 length=(size_t) ((image->columns+2)*(image->rows+2));
1113 pixel_info=AcquireVirtualMemory(length,
sizeof(*pixels));
1114 buffer_info=AcquireVirtualMemory(length,
sizeof(*buffer));
1115 if ((pixel_info == (MemoryInfo *) NULL) ||
1116 (buffer_info == (MemoryInfo *) NULL))
1118 if (buffer_info != (MemoryInfo *) NULL)
1119 buffer_info=RelinquishVirtualMemory(buffer_info);
1120 if (pixel_info != (MemoryInfo *) NULL)
1121 pixel_info=RelinquishVirtualMemory(pixel_info);
1122 despeckle_image=DestroyImage(despeckle_image);
1123 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1125 pixels=(Quantum *) GetVirtualMemoryBlob(pixel_info);
1126 buffer=(Quantum *) GetVirtualMemoryBlob(buffer_info);
1131 number_channels=(size_t) (image->colorspace == CMYKColorspace ? 5 : 4);
1132 image_view=AcquireVirtualCacheView(image,exception);
1133 despeckle_view=AcquireAuthenticCacheView(despeckle_image,exception);
1134 for (i=0; i < (ssize_t) number_channels; i++)
1144 if (status == MagickFalse)
1146 if ((image->matte == MagickFalse) && (i == 3))
1148 (void) memset(pixels,0,length*
sizeof(*pixels));
1149 j=(ssize_t) image->columns+2;
1150 for (y=0; y < (ssize_t) image->rows; y++)
1153 *magick_restrict indexes;
1158 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1159 if (p == (
const PixelPacket *) NULL)
1161 indexes=GetCacheViewVirtualIndexQueue(image_view);
1163 for (x=0; x < (ssize_t) image->columns; x++)
1167 case 0: pixels[j]=GetPixelRed(p);
break;
1168 case 1: pixels[j]=GetPixelGreen(p);
break;
1169 case 2: pixels[j]=GetPixelBlue(p);
break;
1170 case 3: pixels[j]=GetPixelOpacity(p);
break;
1171 case 4: pixels[j]=GetPixelBlack(indexes+x);
break;
1179 (void) memset(buffer,0,length*
sizeof(*buffer));
1180 for (k=0; k < 4; k++)
1182 Hull(image,X[k],Y[k],image->columns,image->rows,1,pixels,buffer);
1183 Hull(image,-X[k],-Y[k],image->columns,image->rows,1,pixels,buffer);
1184 Hull(image,-X[k],-Y[k],image->columns,image->rows,-1,pixels,buffer);
1185 Hull(image,X[k],Y[k],image->columns,image->rows,-1,pixels,buffer);
1187 j=(ssize_t) image->columns+2;
1188 for (y=0; y < (ssize_t) image->rows; y++)
1194 *magick_restrict indexes;
1199 q=GetCacheViewAuthenticPixels(despeckle_view,0,y,despeckle_image->columns,
1201 if (q == (PixelPacket *) NULL)
1203 indexes=GetCacheViewAuthenticIndexQueue(despeckle_view);
1205 for (x=0; x < (ssize_t) image->columns; x++)
1209 case 0: SetPixelRed(q,pixels[j]);
break;
1210 case 1: SetPixelGreen(q,pixels[j]);
break;
1211 case 2: SetPixelBlue(q,pixels[j]);
break;
1212 case 3: SetPixelOpacity(q,pixels[j]);
break;
1213 case 4: SetPixelIndex(indexes+x,pixels[j]);
break;
1219 sync=SyncCacheViewAuthenticPixels(despeckle_view,exception);
1220 if (sync == MagickFalse)
1227 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1232 proceed=SetImageProgress(image,DespeckleImageTag,(MagickOffsetType) i,
1234 if (proceed == MagickFalse)
1238 despeckle_view=DestroyCacheView(despeckle_view);
1239 image_view=DestroyCacheView(image_view);
1240 buffer_info=RelinquishVirtualMemory(buffer_info);
1241 pixel_info=RelinquishVirtualMemory(pixel_info);
1242 despeckle_image->type=image->type;
1243 if (status == MagickFalse)
1244 despeckle_image=DestroyImage(despeckle_image);
1245 return(despeckle_image);
1277MagickExport Image *EdgeImage(
const Image *image,
const double radius,
1278 ExceptionInfo *exception)
1292 assert(image != (
const Image *) NULL);
1293 assert(image->signature == MagickCoreSignature);
1294 assert(exception != (ExceptionInfo *) NULL);
1295 assert(exception->signature == MagickCoreSignature);
1296 if (IsEventLogging() != MagickFalse)
1297 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1298 width=GetOptimalKernelWidth1D(radius,0.5);
1299 kernel_info=AcquireKernelInfo((
const char *) NULL);
1301 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1302 (void) memset(kernel_info,0,
sizeof(*kernel_info));
1303 kernel_info->width=width;
1304 kernel_info->height=width;
1305 kernel_info->x=(ssize_t) (kernel_info->width-1)/2;
1306 kernel_info->y=(ssize_t) (kernel_info->height-1)/2;
1307 kernel_info->signature=MagickCoreSignature;
1308 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
1309 kernel_info->width,kernel_info->height*
sizeof(*kernel_info->values)));
1310 if (kernel_info->values == (
double *) NULL)
1312 kernel_info=DestroyKernelInfo(kernel_info);
1313 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1315 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1316 kernel_info->values[i]=(-1.0);
1317 kernel_info->values[i/2]=(double) kernel_info->width*kernel_info->height-1.0;
1318 edge_image=(Image *) NULL;
1319#if defined(MAGICKCORE_OPENCL_SUPPORT)
1320 edge_image=AccelerateConvolveImageChannel(image,DefaultChannels,kernel_info,
1323 if (edge_image == (Image *) NULL)
1324 edge_image=MorphologyImageChannel(image,DefaultChannels,ConvolveMorphology,
1325 1,kernel_info,exception);
1326 kernel_info=DestroyKernelInfo(kernel_info);
1363MagickExport Image *EmbossImage(
const Image *image,
const double radius,
1364 const double sigma,ExceptionInfo *exception)
1388 assert(image != (
const Image *) NULL);
1389 assert(image->signature == MagickCoreSignature);
1390 assert(exception != (ExceptionInfo *) NULL);
1391 assert(exception->signature == MagickCoreSignature);
1392 if (IsEventLogging() != MagickFalse)
1393 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1394 width=GetOptimalKernelWidth1D(radius,sigma);
1395 kernel_info=AcquireKernelInfo((
const char *) NULL);
1397 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1398 kernel_info->width=width;
1399 kernel_info->height=width;
1400 kernel_info->x=(ssize_t) (width-1)/2;
1401 kernel_info->y=(ssize_t) (width-1)/2;
1402 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
1403 kernel_info->width,kernel_info->width*
sizeof(*kernel_info->values)));
1404 if (kernel_info->values == (
double *) NULL)
1406 kernel_info=DestroyKernelInfo(kernel_info);
1407 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1409 j=(ssize_t) (kernel_info->width-1)/2;
1412 for (v=(-j); v <= j; v++)
1414 for (u=(-j); u <= j; u++)
1416 kernel_info->values[i]=(double) (((u < 0) || (v < 0) ? -8.0 :
1417 8.0)*exp(-((
double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
1418 (2.0*MagickPI*MagickSigma*MagickSigma));
1420 kernel_info->values[i]=0.0;
1426 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1427 normalize+=kernel_info->values[i];
1428 gamma=MagickSafeReciprocal(normalize);
1429 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1430 kernel_info->values[i]*=gamma;
1431 emboss_image=(Image *) NULL;
1432#if defined(MAGICKCORE_OPENCL_SUPPORT)
1433 emboss_image=AccelerateConvolveImageChannel(image,DefaultChannels,kernel_info,
1436 if (emboss_image == (Image *) NULL)
1437 emboss_image=MorphologyImageChannel(image,DefaultChannels,
1438 ConvolveMorphology,1,kernel_info,exception);
1439 kernel_info=DestroyKernelInfo(kernel_info);
1440 if (emboss_image != (Image *) NULL)
1441 (void) EqualizeImageChannel(emboss_image,(ChannelType)
1442 (AllChannels &~ SyncChannels));
1443 return(emboss_image);
1478MagickExport Image *FilterImage(
const Image *image,
const KernelInfo *kernel,
1479 ExceptionInfo *exception)
1484 filter_image=FilterImageChannel(image,DefaultChannels,kernel,exception);
1485 return(filter_image);
1488MagickExport Image *FilterImageChannel(
const Image *image,
1489 const ChannelType channel,
const KernelInfo *kernel,ExceptionInfo *exception)
1491#define FilterImageTag "Filter/Image"
1518#ifdef MAGICKCORE_CLPERFMARKER
1519 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1525 assert(image != (Image *) NULL);
1526 assert(image->signature == MagickCoreSignature);
1527 assert(exception != (ExceptionInfo *) NULL);
1528 assert(exception->signature == MagickCoreSignature);
1529 if (IsEventLogging() != MagickFalse)
1530 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1531 if ((kernel->width % 2) == 0)
1532 ThrowImageException(OptionError,
"KernelWidthMustBeAnOddNumber");
1533 if (image->debug != MagickFalse)
1536 format[MaxTextExtent],
1546 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
1547 " FilterImage with %.20gx%.20g kernel:",(
double) kernel->width,(
double)
1549 message=AcquireString(
"");
1551 for (v=0; v < (ssize_t) kernel->height; v++)
1554 (void) FormatLocaleString(format,MaxTextExtent,
"%.20g: ",(
double) v);
1555 (void) ConcatenateString(&message,format);
1556 for (u=0; u < (ssize_t) kernel->width; u++)
1558 (void) FormatLocaleString(format,MaxTextExtent,
"%g ",*k++);
1559 (void) ConcatenateString(&message,format);
1561 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"%s",message);
1563 message=DestroyString(message);
1565#if defined(MAGICKCORE_OPENCL_SUPPORT)
1566 filter_image=AccelerateConvolveImageChannel(image,channel,kernel,exception);
1567 if (filter_image != (Image *) NULL)
1569#ifdef MAGICKCORE_CLPERFMARKER
1570 clEndPerfMarkerAMD();
1572 return(filter_image);
1575 filter_image=CloneImage(image,0,0,MagickTrue,exception);
1576 if (filter_image == (Image *) NULL)
1577 return((Image *) NULL);
1578 if (SetImageStorageClass(filter_image,DirectClass) == MagickFalse)
1580 InheritException(exception,&filter_image->exception);
1581 filter_image=DestroyImage(filter_image);
1582 return((Image *) NULL);
1587 filter_kernel=(MagickRealType *) MagickAssumeAligned(AcquireAlignedMemory(
1588 kernel->width,kernel->height*
sizeof(*filter_kernel)));
1589 if (filter_kernel == (MagickRealType *) NULL)
1591 filter_image=DestroyImage(filter_image);
1592 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1594 for (i=0; i < (ssize_t) (kernel->width*kernel->height); i++)
1595 filter_kernel[i]=(MagickRealType) kernel->values[i];
1601 GetMagickPixelPacket(image,&bias);
1602 SetMagickPixelPacketBias(image,&bias);
1603 image_view=AcquireVirtualCacheView(image,exception);
1604 filter_view=AcquireAuthenticCacheView(filter_image,exception);
1605#if defined(MAGICKCORE_OPENMP_SUPPORT)
1606 #pragma omp parallel for schedule(static) shared(progress,status) \
1607 magick_number_threads(image,filter_image,image->rows,1)
1609 for (y=0; y < (ssize_t) image->rows; y++)
1615 *magick_restrict indexes;
1621 *magick_restrict filter_indexes;
1629 if (status == MagickFalse)
1631 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) (kernel->width-1)/2L),y-
1632 (ssize_t) ((kernel->height-1)/2L),image->columns+kernel->width,
1633 kernel->height,exception);
1634 q=GetCacheViewAuthenticPixels(filter_view,0,y,filter_image->columns,1,
1636 if ((p == (
const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
1641 indexes=GetCacheViewVirtualIndexQueue(image_view);
1642 filter_indexes=GetCacheViewAuthenticIndexQueue(filter_view);
1643 for (x=0; x < (ssize_t) image->columns; x++)
1648 const MagickRealType
1652 *magick_restrict kernel_pixels;
1661 pixel.green=bias.green;
1662 pixel.blue=bias.blue;
1663 pixel.opacity=bias.opacity;
1664 pixel.index=bias.index;
1667 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
1669 for (v=0; v < (ssize_t) kernel->width; v++)
1671 for (u=0; u < (ssize_t) kernel->height; u++)
1673 pixel.red+=(*k)*(double) kernel_pixels[u].red;
1674 pixel.green+=(*k)*(double) kernel_pixels[u].green;
1675 pixel.blue+=(*k)*(double) kernel_pixels[u].blue;
1678 kernel_pixels+=image->columns+kernel->width;
1680 if ((channel & RedChannel) != 0)
1681 SetPixelRed(q,ClampToQuantum(pixel.red));
1682 if ((channel & GreenChannel) != 0)
1683 SetPixelGreen(q,ClampToQuantum(pixel.green));
1684 if ((channel & BlueChannel) != 0)
1685 SetPixelBlue(q,ClampToQuantum(pixel.blue));
1686 if ((channel & OpacityChannel) != 0)
1690 for (v=0; v < (ssize_t) kernel->width; v++)
1692 for (u=0; u < (ssize_t) kernel->height; u++)
1694 pixel.opacity+=(*k)*(MagickRealType) kernel_pixels[u].opacity;
1697 kernel_pixels+=image->columns+kernel->width;
1699 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
1701 if (((channel & IndexChannel) != 0) &&
1702 (image->colorspace == CMYKColorspace))
1705 *magick_restrict kernel_indexes;
1708 kernel_indexes=indexes;
1709 for (v=0; v < (ssize_t) kernel->width; v++)
1711 for (u=0; u < (ssize_t) kernel->height; u++)
1713 pixel.index+=(*k)*(double) GetPixelIndex(kernel_indexes+u);
1716 kernel_indexes+=image->columns+kernel->width;
1718 SetPixelIndex(filter_indexes+x,ClampToQuantum(pixel.index));
1728 for (v=0; v < (ssize_t) kernel->width; v++)
1730 for (u=0; u < (ssize_t) kernel->height; u++)
1732 alpha=(MagickRealType) QuantumScale*((MagickRealType)
1733 QuantumRange-(MagickRealType) GetPixelOpacity(kernel_pixels+u));
1734 pixel.red+=(*k)*alpha*(double) GetPixelRed(kernel_pixels+u);
1735 pixel.green+=(*k)*alpha*(double) GetPixelGreen(kernel_pixels+u);
1736 pixel.blue+=(*k)*alpha*(double) GetPixelBlue(kernel_pixels+u);
1740 kernel_pixels+=image->columns+kernel->width;
1742 gamma=MagickSafeReciprocal(gamma);
1743 if ((channel & RedChannel) != 0)
1744 SetPixelRed(q,ClampToQuantum(gamma*(
double) pixel.red));
1745 if ((channel & GreenChannel) != 0)
1746 SetPixelGreen(q,ClampToQuantum(gamma*(
double) pixel.green));
1747 if ((channel & BlueChannel) != 0)
1748 SetPixelBlue(q,ClampToQuantum(gamma*(
double) pixel.blue));
1749 if ((channel & OpacityChannel) != 0)
1753 for (v=0; v < (ssize_t) kernel->width; v++)
1755 for (u=0; u < (ssize_t) kernel->height; u++)
1757 pixel.opacity+=(*k)*(double) GetPixelOpacity(kernel_pixels+u);
1760 kernel_pixels+=image->columns+kernel->width;
1762 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
1764 if (((channel & IndexChannel) != 0) &&
1765 (image->colorspace == CMYKColorspace))
1768 *magick_restrict kernel_indexes;
1772 kernel_indexes=indexes;
1773 for (v=0; v < (ssize_t) kernel->width; v++)
1775 for (u=0; u < (ssize_t) kernel->height; u++)
1777 alpha=(MagickRealType) (QuantumScale*((
double) QuantumRange-
1778 (
double) kernel_pixels[u].opacity));
1779 pixel.index+=(*k)*alpha*(MagickRealType)
1780 GetPixelIndex(kernel_indexes+u);
1783 kernel_pixels+=image->columns+kernel->width;
1784 kernel_indexes+=image->columns+kernel->width;
1786 SetPixelIndex(filter_indexes+x,ClampToQuantum(gamma*(
double)
1794 sync=SyncCacheViewAuthenticPixels(filter_view,exception);
1795 if (sync == MagickFalse)
1797 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1802#if defined(MAGICKCORE_OPENMP_SUPPORT)
1806 proceed=SetImageProgress(image,FilterImageTag,progress,image->rows);
1807 if (proceed == MagickFalse)
1811 filter_image->type=image->type;
1812 filter_view=DestroyCacheView(filter_view);
1813 image_view=DestroyCacheView(image_view);
1814 filter_kernel=(MagickRealType *) RelinquishAlignedMemory(filter_kernel);
1815 if (status == MagickFalse)
1816 filter_image=DestroyImage(filter_image);
1817#ifdef MAGICKCORE_CLPERFMARKER
1818 clEndPerfMarkerAMD();
1820 return(filter_image);
1862MagickExport Image *GaussianBlurImage(
const Image *image,
const double radius,
1863 const double sigma,ExceptionInfo *exception)
1868 blur_image=GaussianBlurImageChannel(image,DefaultChannels,radius,sigma,
1873MagickExport Image *GaussianBlurImageChannel(
const Image *image,
1874 const ChannelType channel,
const double radius,
const double sigma,
1875 ExceptionInfo *exception)
1878 geometry[MaxTextExtent];
1886 assert(image != (
const Image *) NULL);
1887 assert(image->signature == MagickCoreSignature);
1888 assert(exception != (ExceptionInfo *) NULL);
1889 assert(exception->signature == MagickCoreSignature);
1890 if (IsEventLogging() != MagickFalse)
1891 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1892 (void) FormatLocaleString(geometry,MaxTextExtent,
"gaussian:%.20gx%.20g",
1894 kernel_info=AcquireKernelInfo(geometry);
1896 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1897 blur_image=(Image *) NULL;
1898#if defined(MAGICKCORE_OPENCL_SUPPORT)
1899 blur_image=AccelerateConvolveImageChannel(image,channel,kernel_info,
1902 if (blur_image == (Image *) NULL)
1903 blur_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
1904 kernel_info,exception);
1905 kernel_info=DestroyKernelInfo(kernel_info);
1953static double *GetMotionBlurKernel(
const size_t width,
const double sigma)
1965 if (IsEventLogging() != MagickFalse)
1966 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1967 kernel=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
1969 if (kernel == (
double *) NULL)
1972 for (i=0; i < (ssize_t) width; i++)
1974 kernel[i]=(double) (exp((-((
double) i*i)/(
double) (2.0*MagickSigma*
1975 MagickSigma)))/(MagickSQ2PI*MagickSigma));
1976 normalize+=kernel[i];
1978 for (i=0; i < (ssize_t) width; i++)
1979 kernel[i]/=normalize;
1983MagickExport Image *MotionBlurImage(
const Image *image,
const double radius,
1984 const double sigma,
const double angle,ExceptionInfo *exception)
1989 motion_blur=MotionBlurImageChannel(image,DefaultChannels,radius,sigma,angle,
1991 return(motion_blur);
1994MagickExport Image *MotionBlurImageChannel(
const Image *image,
1995 const ChannelType channel,
const double radius,
const double sigma,
1996 const double angle,ExceptionInfo *exception)
1998#define BlurImageTag "Blur/Image"
2034 assert(image != (Image *) NULL);
2035 assert(image->signature == MagickCoreSignature);
2036 assert(exception != (ExceptionInfo *) NULL);
2037 assert(exception->signature == MagickCoreSignature);
2038 if (IsEventLogging() != MagickFalse)
2039 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2040 width=GetOptimalKernelWidth1D(radius,sigma);
2041 kernel=GetMotionBlurKernel(width,sigma);
2042 if (kernel == (
double *) NULL)
2043 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2044 offset=(OffsetInfo *) AcquireQuantumMemory(width,
sizeof(*offset));
2045 if (offset == (OffsetInfo *) NULL)
2047 kernel=(
double *) RelinquishAlignedMemory(kernel);
2048 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2051 point.x=(double) width*sin(DegreesToRadians(angle));
2052 point.y=(double) width*cos(DegreesToRadians(angle));
2053 for (i=0; i < (ssize_t) width; i++)
2055 offset[i].x=CastDoubleToLong(ceil((
double) (i*point.y)/
2056 hypot(point.x,point.y)-0.5));
2057 offset[i].y=CastDoubleToLong(ceil((
double) (i*point.x)/
2058 hypot(point.x,point.y)-0.5));
2064#if defined(MAGICKCORE_OPENCL_SUPPORT)
2065 blur_image=AccelerateMotionBlurImage(image,channel,kernel,width,offset,
2067 if (blur_image != (Image *) NULL)
2070 blur_image=CloneImage(image,0,0,MagickTrue,exception);
2071 if (blur_image == (Image *) NULL)
2073 kernel=(
double *) RelinquishAlignedMemory(kernel);
2074 offset=(OffsetInfo *) RelinquishMagickMemory(offset);
2075 return((Image *) NULL);
2077 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
2079 kernel=(
double *) RelinquishAlignedMemory(kernel);
2080 offset=(OffsetInfo *) RelinquishMagickMemory(offset);
2081 InheritException(exception,&blur_image->exception);
2082 blur_image=DestroyImage(blur_image);
2083 return((Image *) NULL);
2088 GetMagickPixelPacket(image,&bias);
2089 image_view=AcquireVirtualCacheView(image,exception);
2090 blur_view=AcquireAuthenticCacheView(blur_image,exception);
2091#if defined(MAGICKCORE_OPENMP_SUPPORT)
2092 #pragma omp parallel for schedule(static) shared(progress,status) \
2093 magick_number_threads(image,blur_image,image->rows,1)
2095 for (y=0; y < (ssize_t) image->rows; y++)
2098 *magick_restrict blur_indexes;
2106 if (status == MagickFalse)
2108 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
2110 if (q == (PixelPacket *) NULL)
2115 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
2116 for (x=0; x < (ssize_t) image->columns; x++)
2125 *magick_restrict indexes;
2135 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
2137 for (i=0; i < (ssize_t) width; i++)
2139 (void) GetOneCacheViewVirtualPixel(image_view,x+offset[i].x,y+
2140 offset[i].y,&pixel,exception);
2141 qixel.red+=(*k)*(double) pixel.red;
2142 qixel.green+=(*k)*(double) pixel.green;
2143 qixel.blue+=(*k)*(double) pixel.blue;
2144 qixel.opacity+=(*k)*(double) pixel.opacity;
2145 if (image->colorspace == CMYKColorspace)
2147 indexes=GetCacheViewVirtualIndexQueue(image_view);
2148 qixel.index+=(*k)*(double) (*indexes);
2152 if ((channel & RedChannel) != 0)
2153 SetPixelRed(q,ClampToQuantum(qixel.red));
2154 if ((channel & GreenChannel) != 0)
2155 SetPixelGreen(q,ClampToQuantum(qixel.green));
2156 if ((channel & BlueChannel) != 0)
2157 SetPixelBlue(q,ClampToQuantum(qixel.blue));
2158 if ((channel & OpacityChannel) != 0)
2159 SetPixelOpacity(q,ClampToQuantum(qixel.opacity));
2160 if (((channel & IndexChannel) != 0) &&
2161 (image->colorspace == CMYKColorspace))
2162 SetPixelIndex(blur_indexes+x,ClampToQuantum(qixel.index));
2170 for (i=0; i < (ssize_t) width; i++)
2172 (void) GetOneCacheViewVirtualPixel(image_view,x+offset[i].x,y+
2173 offset[i].y,&pixel,exception);
2174 alpha=(MagickRealType) (QuantumScale*(
double)
2175 GetPixelAlpha(&pixel));
2176 qixel.red+=(*k)*alpha*(double) pixel.red;
2177 qixel.green+=(*k)*alpha*(double) pixel.green;
2178 qixel.blue+=(*k)*alpha*(double) pixel.blue;
2179 qixel.opacity+=(*k)*(double) pixel.opacity;
2180 if (image->colorspace == CMYKColorspace)
2182 indexes=GetCacheViewVirtualIndexQueue(image_view);
2183 qixel.index+=(*k)*alpha*(double) GetPixelIndex(indexes);
2188 gamma=MagickSafeReciprocal(gamma);
2189 if ((channel & RedChannel) != 0)
2190 SetPixelRed(q,ClampToQuantum(gamma*qixel.red));
2191 if ((channel & GreenChannel) != 0)
2192 SetPixelGreen(q,ClampToQuantum(gamma*qixel.green));
2193 if ((channel & BlueChannel) != 0)
2194 SetPixelBlue(q,ClampToQuantum(gamma*qixel.blue));
2195 if ((channel & OpacityChannel) != 0)
2196 SetPixelOpacity(q,ClampToQuantum(qixel.opacity));
2197 if (((channel & IndexChannel) != 0) &&
2198 (image->colorspace == CMYKColorspace))
2199 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*qixel.index));
2203 if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
2205 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2210#if defined(MAGICKCORE_OPENMP_SUPPORT)
2214 proceed=SetImageProgress(image,BlurImageTag,progress,image->rows);
2215 if (proceed == MagickFalse)
2219 blur_view=DestroyCacheView(blur_view);
2220 image_view=DestroyCacheView(image_view);
2221 kernel=(
double *) RelinquishAlignedMemory(kernel);
2222 offset=(OffsetInfo *) RelinquishMagickMemory(offset);
2223 if (status == MagickFalse)
2224 blur_image=DestroyImage(blur_image);
2262MagickExport Image *KuwaharaImage(
const Image *image,
const double radius,
2263 const double sigma,ExceptionInfo *exception)
2268 kuwahara_image=KuwaharaImageChannel(image,DefaultChannels,radius,sigma,
2270 return(kuwahara_image);
2273MagickExport Image *KuwaharaImageChannel(
const Image *image,
2274 const ChannelType channel,
const double radius,
const double sigma,
2275 ExceptionInfo *exception)
2277#define KuwaharaImageTag "Kiwahara/Image"
2302 assert(image != (Image *) NULL);
2303 assert(image->signature == MagickCoreSignature);
2304 assert(exception != (ExceptionInfo *) NULL);
2305 assert(exception->signature == MagickCoreSignature);
2306 if (IsEventLogging() != MagickFalse)
2307 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2309 width=(size_t) radius+1;
2310 gaussian_image=BlurImage(image,radius,sigma,exception);
2311 if (gaussian_image == (Image *) NULL)
2312 return((Image *) NULL);
2313 kuwahara_image=CloneImage(image,0,0,MagickTrue,exception);
2314 if (kuwahara_image == (Image *) NULL)
2316 gaussian_image=DestroyImage(gaussian_image);
2317 return((Image *) NULL);
2319 if (SetImageStorageClass(kuwahara_image,DirectClass) == MagickFalse)
2321 InheritException(exception,&kuwahara_image->exception);
2322 gaussian_image=DestroyImage(gaussian_image);
2323 kuwahara_image=DestroyImage(kuwahara_image);
2324 return((Image *) NULL);
2331 image_view=AcquireVirtualCacheView(gaussian_image,exception);
2332 kuwahara_view=AcquireAuthenticCacheView(kuwahara_image,exception);
2333#if defined(MAGICKCORE_OPENMP_SUPPORT)
2334 #pragma omp parallel for schedule(static) shared(progress,status) \
2335 magick_number_threads(image,kuwahara_image,kuwahara_image->rows,1)
2337 for (y=0; y < (ssize_t) kuwahara_image->rows; y++)
2340 *magick_restrict kuwahara_indexes;
2348 if (status == MagickFalse)
2350 q=QueueCacheViewAuthenticPixels(kuwahara_view,0,y,kuwahara_image->columns,1,
2352 if (q == (PixelPacket *) NULL)
2357 kuwahara_indexes=GetCacheViewAuthenticIndexQueue(kuwahara_view);
2358 for (x=0; x < (ssize_t) kuwahara_image->columns; x++)
2373 min_variance=MagickMaximumValue;
2374 SetGeometry(gaussian_image,&target);
2375 quadrant.width=width;
2376 quadrant.height=width;
2377 for (i=0; i < 4; i++)
2400 quadrant.x=x-(ssize_t) (width-1);
2401 quadrant.y=y-(ssize_t) (width-1);
2406 quadrant.y=y-(ssize_t) (width-1);
2411 quadrant.x=x-(ssize_t) (width-1);
2417 p=GetCacheViewVirtualPixels(image_view,quadrant.x,quadrant.y,
2418 quadrant.width,quadrant.height,exception);
2419 if (p == (
const PixelPacket *) NULL)
2421 GetMagickPixelPacket(image,&mean);
2423 for (n=0; n < (ssize_t) (width*width); n++)
2425 mean.red+=(double) k->red;
2426 mean.green+=(double) k->green;
2427 mean.blue+=(double) k->blue;
2430 mean.red/=(double) (width*width);
2431 mean.green/=(double) (width*width);
2432 mean.blue/=(double) (width*width);
2435 for (n=0; n < (ssize_t) (width*width); n++)
2440 luma=GetPixelLuma(image,k);
2441 variance+=(luma-MagickPixelLuma(&mean))*(luma-MagickPixelLuma(&mean));
2444 if (variance < min_variance)
2446 min_variance=variance;
2455 status=InterpolateMagickPixelPacket(gaussian_image,image_view,
2456 UndefinedInterpolatePixel,(
double) target.x+target.width/2.0,
2457 (
double) target.y+target.height/2.0,&pixel,exception);
2458 if (status == MagickFalse)
2460 SetPixelPacket(kuwahara_image,&pixel,q,kuwahara_indexes+x);
2463 if (SyncCacheViewAuthenticPixels(kuwahara_view,exception) == MagickFalse)
2465 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2470#if defined(MAGICKCORE_OPENMP_SUPPORT)
2474 proceed=SetImageProgress(image,KuwaharaImageTag,progress,image->rows);
2475 if (proceed == MagickFalse)
2479 kuwahara_view=DestroyCacheView(kuwahara_view);
2480 image_view=DestroyCacheView(image_view);
2481 gaussian_image=DestroyImage(gaussian_image);
2482 if (status == MagickFalse)
2483 kuwahara_image=DestroyImage(kuwahara_image);
2484 return(kuwahara_image);
2520MagickExport Image *LocalContrastImage(
const Image *image,
const double radius,
2521 const double strength,ExceptionInfo *exception)
2523#define LocalContrastImageTag "LocalContrast/Image"
2551 assert(image != (
const Image *) NULL);
2552 assert(image->signature == MagickCoreSignature);
2553 assert(exception != (ExceptionInfo *) NULL);
2554 assert(exception->signature == MagickCoreSignature);
2555 if (IsEventLogging() != MagickFalse)
2556 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2557#if defined(MAGICKCORE_OPENCL_SUPPORT)
2558 contrast_image=AccelerateLocalContrastImage(image,radius,strength,exception);
2559 if (contrast_image != (Image *) NULL)
2560 return(contrast_image);
2562 contrast_image=CloneImage(image,0,0,MagickTrue,exception);
2563 if (contrast_image == (Image *) NULL)
2564 return((Image *) NULL);
2565 if (SetImageStorageClass(contrast_image,DirectClass) == MagickFalse)
2567 InheritException(exception,&contrast_image->exception);
2568 contrast_image=DestroyImage(contrast_image);
2569 return((Image *) NULL);
2571 image_view=AcquireVirtualCacheView(image,exception);
2572 contrast_view=AcquireAuthenticCacheView(contrast_image,exception);
2573 scanLineSize=(ssize_t) MagickMax(image->columns,image->rows);
2574 width=(ssize_t) scanLineSize*0.002*fabs(radius);
2575 scanLineSize+=(2*width);
2576 scanline_info=AcquireVirtualMemory(GetOpenMPMaximumThreads()*
2577 scanLineSize,
sizeof(*scanline));
2578 if (scanline_info == (MemoryInfo *) NULL)
2580 contrast_view=DestroyCacheView(contrast_view);
2581 image_view=DestroyCacheView(image_view);
2582 contrast_image=DestroyImage(contrast_image);
2583 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2585 scanline=(
float *) GetVirtualMemoryBlob(scanline_info);
2589 interImage_info=AcquireVirtualMemory(image->rows*(image->columns+(2*width)),
2590 sizeof(*interImage));
2591 if (interImage_info == (MemoryInfo *) NULL)
2593 scanline_info=RelinquishVirtualMemory(scanline_info);
2594 contrast_view=DestroyCacheView(contrast_view);
2595 image_view=DestroyCacheView(image_view);
2596 contrast_image=DestroyImage(contrast_image);
2597 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2599 interImage=(
float *) GetVirtualMemoryBlob(interImage_info);
2600 totalWeight=(width+1)*(width+1);
2609#if defined(MAGICKCORE_OPENMP_SUPPORT)
2610 #pragma omp parallel for schedule(static) \
2611 magick_number_threads(image,image,image->columns,1)
2613 for (x=0; x < (ssize_t) image->columns; x++)
2616 id = GetOpenMPThreadId();
2632 if (status == MagickFalse)
2635 pixels+=
id*scanLineSize;
2637 p=GetCacheViewVirtualPixels(image_view,x,-width,1,image->rows+(2*width),
2639 if (p == (
const PixelPacket *) NULL)
2644 for (y=0; y < (ssize_t) image->rows+(2*width); y++)
2646 *pix++=(float)GetPixelLuma(image,p);
2649 out=interImage+x+width;
2650 for (y=0; y < (ssize_t) image->rows; y++)
2659 for (i=0; i < width; i++)
2661 sum+=weight*(*pix++);
2664 for (i=width+1; i < (2*width); i++)
2666 sum+=weight*(*pix++);
2670 *out=sum/totalWeight;
2672 if (x <= width && x != 0)
2674 if ((x > (ssize_t) image->columns-width-2) &&
2675 (x != (ssize_t) image->columns-1))
2676 *(out+((image->columns-x-1)*2))=*out;
2677 out+=image->columns+(width*2);
2688#if defined(MAGICKCORE_OPENMP_SUPPORT)
2689#pragma omp parallel for schedule(static) \
2690 magick_number_threads(image,image,image->rows,1)
2692 for (y=0; y < (ssize_t) image->rows; y++)
2695 id = GetOpenMPThreadId();
2713 if (status == MagickFalse)
2716 pixels+=
id*scanLineSize;
2717 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,
2719 q=GetCacheViewAuthenticPixels(contrast_view,0,y,image->columns,1,
2721 if ((p == (
const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
2726 memcpy(pixels,interImage+(y*(image->columns+(2*width))),(image->columns+
2727 (2*width))*
sizeof(
float));
2728 for (x=0; x < (ssize_t) image->columns; x++)
2739 for (i=0; i < width; i++)
2741 sum+=weight*(*pix++);
2744 for (i=width+1; i < (2*width); i++)
2746 sum+=weight*(*pix++);
2750 srcVal=(float) GetPixelLuma(image,p);
2751 mult=(srcVal-(sum/totalWeight))*(
float) (0.01*strength);
2752 mult=(srcVal+mult)/srcVal;
2753 SetPixelRed(q,ClampToQuantum((MagickRealType) GetPixelRed(p)*
2754 (MagickRealType) mult));
2755 SetPixelGreen(q,ClampToQuantum((MagickRealType) GetPixelGreen(p)*
2756 (MagickRealType) mult));
2757 SetPixelBlue(q,ClampToQuantum((MagickRealType) GetPixelBlue(p)*
2758 (MagickRealType) mult));
2762 if (SyncCacheViewAuthenticPixels(contrast_view,exception) == MagickFalse)
2766 scanline_info=RelinquishVirtualMemory(scanline_info);
2767 interImage_info=RelinquishVirtualMemory(interImage_info);
2768 contrast_view=DestroyCacheView(contrast_view);
2769 image_view=DestroyCacheView(image_view);
2770 if (status == MagickFalse)
2771 contrast_image=DestroyImage(contrast_image);
2772 return(contrast_image);
2805MagickExport Image *PreviewImage(
const Image *image,
const PreviewType preview,
2806 ExceptionInfo *exception)
2808#define NumberTiles 9
2809#define PreviewImageTag "Preview/Image"
2810#define DefaultPreviewGeometry "204x204+10+10"
2813 factor[MaxTextExtent],
2814 label[MaxTextExtent];
2856 assert(image != (Image *) NULL);
2857 assert(image->signature == MagickCoreSignature);
2858 if (IsEventLogging() != MagickFalse)
2859 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2863 preview_info=AcquireImageInfo();
2864 SetGeometry(image,&geometry);
2865 (void) ParseMetaGeometry(DefaultPreviewGeometry,&geometry.x,&geometry.y,
2866 &geometry.width,&geometry.height);
2867 images=NewImageList();
2869 GetQuantizeInfo(&quantize_info);
2875 for (i=0; i < NumberTiles; i++)
2877 thumbnail=ThumbnailImage(image,geometry.width,geometry.height,exception);
2878 if (thumbnail == (Image *) NULL)
2880 (void) SetImageProgressMonitor(thumbnail,(MagickProgressMonitor) NULL,
2882 (void) SetImageProperty(thumbnail,
"label",DefaultTileLabel);
2883 if (i == (NumberTiles/2))
2885 (void) QueryColorDatabase(
"#dfdfdf",&thumbnail->matte_color,exception);
2886 AppendImageToList(&images,thumbnail);
2894 preview_image=RotateImage(thumbnail,degrees,exception);
2895 (void) FormatLocaleString(label,MaxTextExtent,
"rotate %g",degrees);
2901 preview_image=ShearImage(thumbnail,degrees,degrees,exception);
2902 (void) FormatLocaleString(label,MaxTextExtent,
"shear %gx%g",
2903 degrees,2.0*degrees);
2908 x=(ssize_t) ((i+1)*thumbnail->columns)/NumberTiles;
2909 y=(ssize_t) ((i+1)*thumbnail->rows)/NumberTiles;
2910 preview_image=RollImage(thumbnail,x,y,exception);
2911 (void) FormatLocaleString(label,MaxTextExtent,
"roll %+.20gx%+.20g",
2912 (
double) x,(
double) y);
2917 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2918 if (preview_image == (Image *) NULL)
2920 (void) FormatLocaleString(factor,MaxTextExtent,
"100,100,%g",
2922 (void) ModulateImage(preview_image,factor);
2923 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2926 case SaturationPreview:
2928 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2929 if (preview_image == (Image *) NULL)
2931 (void) FormatLocaleString(factor,MaxTextExtent,
"100,%g",2.0*percentage);
2932 (void) ModulateImage(preview_image,factor);
2933 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2936 case BrightnessPreview:
2938 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2939 if (preview_image == (Image *) NULL)
2941 (void) FormatLocaleString(factor,MaxTextExtent,
"%g",2.0*percentage);
2942 (void) ModulateImage(preview_image,factor);
2943 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2949 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2950 if (preview_image == (Image *) NULL)
2953 (void) GammaImageChannel(preview_image,DefaultChannels,gamma);
2954 (void) FormatLocaleString(label,MaxTextExtent,
"gamma %g",gamma);
2959 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2960 if (preview_image != (Image *) NULL)
2961 for (x=0; x < i; x++)
2962 (
void) ContrastImage(preview_image,MagickTrue);
2963 (void) FormatLocaleString(label,MaxTextExtent,
"contrast (%.20g)",
2969 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2970 if (preview_image == (Image *) NULL)
2972 for (x=0; x < i; x++)
2973 (
void) ContrastImage(preview_image,MagickFalse);
2974 (void) FormatLocaleString(label,MaxTextExtent,
"+contrast (%.20g)",
2978 case GrayscalePreview:
2980 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2981 if (preview_image == (Image *) NULL)
2984 quantize_info.number_colors=colors;
2985 quantize_info.colorspace=GRAYColorspace;
2986 (void) QuantizeImage(&quantize_info,preview_image);
2987 (void) FormatLocaleString(label,MaxTextExtent,
2988 "-colorspace gray -colors %.20g",(
double) colors);
2991 case QuantizePreview:
2993 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2994 if (preview_image == (Image *) NULL)
2997 quantize_info.number_colors=colors;
2998 (void) QuantizeImage(&quantize_info,preview_image);
2999 (void) FormatLocaleString(label,MaxTextExtent,
"colors %.20g",(
double)
3003 case DespecklePreview:
3005 for (x=0; x < (i-1); x++)
3007 preview_image=DespeckleImage(thumbnail,exception);
3008 if (preview_image == (Image *) NULL)
3010 thumbnail=DestroyImage(thumbnail);
3011 thumbnail=preview_image;
3013 preview_image=DespeckleImage(thumbnail,exception);
3014 if (preview_image == (Image *) NULL)
3016 (void) FormatLocaleString(label,MaxTextExtent,
"despeckle (%.20g)",
3020 case ReduceNoisePreview:
3022 preview_image=StatisticImage(thumbnail,NonpeakStatistic,(
size_t) radius,
3023 (
size_t) radius,exception);
3024 (void) FormatLocaleString(label,MaxTextExtent,
"noise %g",radius);
3027 case AddNoisePreview:
3033 (void) CopyMagickString(factor,
"uniform",MaxTextExtent);
3038 (void) CopyMagickString(factor,
"gaussian",MaxTextExtent);
3043 (void) CopyMagickString(factor,
"multiplicative",MaxTextExtent);
3048 (void) CopyMagickString(factor,
"impulse",MaxTextExtent);
3053 (void) CopyMagickString(factor,
"laplacian",MaxTextExtent);
3058 (void) CopyMagickString(factor,
"poisson",MaxTextExtent);
3063 (void) CopyMagickString(thumbnail->magick,
"NULL",MaxTextExtent);
3067 preview_image=StatisticImage(thumbnail,NonpeakStatistic,(
size_t) i,
3068 (
size_t) i,exception);
3069 (void) FormatLocaleString(label,MaxTextExtent,
"+noise %s",factor);
3072 case SharpenPreview:
3074 preview_image=SharpenImage(thumbnail,radius,sigma,exception);
3075 (void) FormatLocaleString(label,MaxTextExtent,
"sharpen %gx%g",
3081 preview_image=BlurImage(thumbnail,radius,sigma,exception);
3082 (void) FormatLocaleString(label,MaxTextExtent,
"blur %gx%g",radius,
3086 case ThresholdPreview:
3088 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3089 if (preview_image == (Image *) NULL)
3091 (void) BilevelImage(thumbnail,
3092 (
double) (percentage*((MagickRealType) QuantumRange+1.0))/100.0);
3093 (void) FormatLocaleString(label,MaxTextExtent,
"threshold %g",
3094 (
double) (percentage*((MagickRealType) QuantumRange+1.0))/100.0);
3097 case EdgeDetectPreview:
3099 preview_image=EdgeImage(thumbnail,radius,exception);
3100 (void) FormatLocaleString(label,MaxTextExtent,
"edge %g",radius);
3105 preview_image=SpreadImage(thumbnail,radius,exception);
3106 (void) FormatLocaleString(label,MaxTextExtent,
"spread %g",
3110 case SolarizePreview:
3112 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3113 if (preview_image == (Image *) NULL)
3115 (void) SolarizeImage(preview_image,(
double) QuantumRange*
3117 (void) FormatLocaleString(label,MaxTextExtent,
"solarize %g",
3118 ((
double) QuantumRange*percentage)/100.0);
3124 preview_image=ShadeImage(thumbnail,MagickTrue,degrees,degrees,
3126 (void) FormatLocaleString(label,MaxTextExtent,
"shade %gx%g",
3135 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3136 if (preview_image == (Image *) NULL)
3138 raise.width=(size_t) (2*i+2);
3139 raise.height=(size_t) (2*i+2);
3142 (void) RaiseImage(preview_image,&raise,MagickTrue);
3143 (void) FormatLocaleString(label,MaxTextExtent,
3144 "raise %.20gx%.20g%+.20g%+.20g",(
double) raise.width,(
double)
3145 raise.height,(
double) raise.x,(
double) raise.y);
3148 case SegmentPreview:
3150 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3151 if (preview_image == (Image *) NULL)
3154 (void) SegmentImage(preview_image,sRGBColorspace,MagickFalse,threshold,
3156 (void) FormatLocaleString(label,MaxTextExtent,
"segment %gx%g",
3157 threshold,threshold);
3162 preview_image=SwirlImage(thumbnail,degrees,exception);
3163 (void) FormatLocaleString(label,MaxTextExtent,
"swirl %g",degrees);
3167 case ImplodePreview:
3170 preview_image=ImplodeImage(thumbnail,degrees,exception);
3171 (void) FormatLocaleString(label,MaxTextExtent,
"implode %g",degrees);
3177 preview_image=WaveImage(thumbnail,0.5*degrees,2.0*degrees,exception);
3178 (void) FormatLocaleString(label,MaxTextExtent,
"wave %gx%g",
3179 0.5*degrees,2.0*degrees);
3182 case OilPaintPreview:
3184 preview_image=OilPaintImage(thumbnail,(
double) radius,exception);
3185 (void) FormatLocaleString(label,MaxTextExtent,
"paint %g",radius);
3188 case CharcoalDrawingPreview:
3190 preview_image=CharcoalImage(thumbnail,(
double) radius,(
double) sigma,
3192 (void) FormatLocaleString(label,MaxTextExtent,
"charcoal %gx%g",
3199 filename[MaxTextExtent];
3207 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3208 if (preview_image == (Image *) NULL)
3210 preview_info->quality=(size_t) percentage;
3211 (void) FormatLocaleString(factor,MaxTextExtent,
"%.20g",(
double)
3212 preview_info->quality);
3213 file=AcquireUniqueFileResource(filename);
3215 file=close_utf8(file)-1;
3216 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,
3217 "jpeg:%s",filename);
3218 status=WriteImage(preview_info,preview_image);
3219 if (status != MagickFalse)
3224 (void) CopyMagickString(preview_info->filename,
3225 preview_image->filename,MaxTextExtent);
3226 quality_image=ReadImage(preview_info,exception);
3227 if (quality_image != (Image *) NULL)
3229 preview_image=DestroyImage(preview_image);
3230 preview_image=quality_image;
3233 (void) RelinquishUniqueFileResource(preview_image->filename);
3234 if ((GetBlobSize(preview_image)/1024) >= 1024)
3235 (void) FormatLocaleString(label,MaxTextExtent,
"quality %s\n%gmb ",
3236 factor,(
double) ((MagickOffsetType) GetBlobSize(preview_image))/
3239 if (GetBlobSize(preview_image) >= 1024)
3240 (void) FormatLocaleString(label,MaxTextExtent,
3241 "quality %s\n%gkb ",factor,(
double) ((MagickOffsetType)
3242 GetBlobSize(preview_image))/1024.0);
3244 (
void) FormatLocaleString(label,MaxTextExtent,
"quality %s\n%.20gb ",
3245 factor,(
double) ((MagickOffsetType) GetBlobSize(thumbnail)));
3249 thumbnail=DestroyImage(thumbnail);
3253 if (preview_image == (Image *) NULL)
3255 (void) DeleteImageProperty(preview_image,
"label");
3256 (void) SetImageProperty(preview_image,
"label",label);
3257 AppendImageToList(&images,preview_image);
3258 proceed=SetImageProgress(image,PreviewImageTag,(MagickOffsetType) i,
3260 if (proceed == MagickFalse)
3263 if (images == (Image *) NULL)
3265 preview_info=DestroyImageInfo(preview_info);
3266 return((Image *) NULL);
3271 montage_info=CloneMontageInfo(preview_info,(MontageInfo *) NULL);
3272 (void) CopyMagickString(montage_info->filename,image->filename,MaxTextExtent);
3273 montage_info->shadow=MagickTrue;
3274 (void) CloneString(&montage_info->tile,
"3x3");
3275 (void) CloneString(&montage_info->geometry,DefaultPreviewGeometry);
3276 (void) CloneString(&montage_info->frame,DefaultTileFrame);
3277 montage_image=MontageImages(images,montage_info,exception);
3278 montage_info=DestroyMontageInfo(montage_info);
3279 images=DestroyImageList(images);
3280 if (montage_image == (Image *) NULL)
3281 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3282 if (montage_image->montage != (
char *) NULL)
3287 montage_image->montage=(
char *) RelinquishMagickMemory(
3288 montage_image->montage);
3289 if (image->directory != (
char *) NULL)
3290 montage_image->directory=(
char *) RelinquishMagickMemory(
3291 montage_image->directory);
3293 preview_info=DestroyImageInfo(preview_info);
3294 return(montage_image);
3331MagickExport Image *RotationalBlurImage(
const Image *image,
const double angle,
3332 ExceptionInfo *exception)
3337 blur_image=RotationalBlurImageChannel(image,DefaultChannels,angle,exception);
3341MagickExport Image *RotationalBlurImageChannel(
const Image *image,
3342 const ChannelType channel,
const double angle,ExceptionInfo *exception)
3382 assert(image != (Image *) NULL);
3383 assert(image->signature == MagickCoreSignature);
3384 assert(exception != (ExceptionInfo *) NULL);
3385 assert(exception->signature == MagickCoreSignature);
3386 if (IsEventLogging() != MagickFalse)
3387 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3388#if defined(MAGICKCORE_OPENCL_SUPPORT)
3389 blur_image=AccelerateRadialBlurImage(image,channel,angle,exception);
3390 if (blur_image != (Image *) NULL)
3393 blur_image=CloneImage(image,0,0,MagickTrue,exception);
3394 if (blur_image == (Image *) NULL)
3395 return((Image *) NULL);
3396 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
3398 InheritException(exception,&blur_image->exception);
3399 blur_image=DestroyImage(blur_image);
3400 return((Image *) NULL);
3402 blur_center.x=(double) (image->columns-1)/2.0;
3403 blur_center.y=(double) (image->rows-1)/2.0;
3404 blur_radius=hypot(blur_center.x,blur_center.y);
3405 n=(size_t) fabs(4.0*DegreesToRadians(angle)*sqrt((
double) blur_radius)+2UL);
3406 theta=DegreesToRadians(angle)/(MagickRealType) (n-1);
3407 cos_theta=(MagickRealType *) AcquireQuantumMemory((
size_t) n,
3408 sizeof(*cos_theta));
3409 sin_theta=(MagickRealType *) AcquireQuantumMemory((
size_t) n,
3410 sizeof(*sin_theta));
3411 if ((cos_theta == (MagickRealType *) NULL) ||
3412 (sin_theta == (MagickRealType *) NULL))
3414 if (cos_theta != (MagickRealType *) NULL)
3415 cos_theta=(MagickRealType *) RelinquishMagickMemory(cos_theta);
3416 if (sin_theta != (MagickRealType *) NULL)
3417 sin_theta=(MagickRealType *) RelinquishMagickMemory(sin_theta);
3418 blur_image=DestroyImage(blur_image);
3419 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3421 offset=theta*(MagickRealType) (n-1)/2.0;
3422 for (i=0; i < (ssize_t) n; i++)
3424 cos_theta[i]=cos((
double) (theta*i-offset));
3425 sin_theta[i]=sin((
double) (theta*i-offset));
3432 GetMagickPixelPacket(image,&bias);
3433 image_view=AcquireVirtualCacheView(image,exception);
3434 blur_view=AcquireAuthenticCacheView(blur_image,exception);
3435#if defined(MAGICKCORE_OPENMP_SUPPORT)
3436 #pragma omp parallel for schedule(static) shared(progress,status) \
3437 magick_number_threads(image,blur_image,blur_image->rows,1)
3439 for (y=0; y < (ssize_t) blur_image->rows; y++)
3442 *magick_restrict indexes;
3445 *magick_restrict blur_indexes;
3453 if (status == MagickFalse)
3455 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
3457 if (q == (PixelPacket *) NULL)
3462 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
3463 for (x=0; x < (ssize_t) blur_image->columns; x++)
3484 center.x=(double) x-blur_center.x;
3485 center.y=(double) y-blur_center.y;
3486 radius=hypot((
double) center.x,center.y);
3491 step=(size_t) (blur_radius/radius);
3500 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
3502 for (i=0; i < (ssize_t) n; i+=(ssize_t) step)
3504 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t)
3505 (blur_center.x+center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),
3506 (ssize_t) (blur_center.y+center.x*sin_theta[i]+center.y*
3507 cos_theta[i]+0.5),&pixel,exception);
3508 qixel.red+=(MagickRealType) pixel.red;
3509 qixel.green+=(MagickRealType) pixel.green;
3510 qixel.blue+=(MagickRealType) pixel.blue;
3511 qixel.opacity+=(MagickRealType) pixel.opacity;
3512 if (image->colorspace == CMYKColorspace)
3514 indexes=GetCacheViewVirtualIndexQueue(image_view);
3515 qixel.index+=(MagickRealType) (*indexes);
3519 normalize=MagickSafeReciprocal(normalize);
3520 if ((channel & RedChannel) != 0)
3521 SetPixelRed(q,ClampToQuantum(normalize*qixel.red));
3522 if ((channel & GreenChannel) != 0)
3523 SetPixelGreen(q,ClampToQuantum(normalize*qixel.green));
3524 if ((channel & BlueChannel) != 0)
3525 SetPixelBlue(q,ClampToQuantum(normalize*qixel.blue));
3526 if ((channel & OpacityChannel) != 0)
3527 SetPixelOpacity(q,ClampToQuantum(normalize*qixel.opacity));
3528 if (((channel & IndexChannel) != 0) &&
3529 (image->colorspace == CMYKColorspace))
3530 SetPixelIndex(blur_indexes+x,ClampToQuantum(normalize*qixel.index));
3540 for (i=0; i < (ssize_t) n; i+=(ssize_t) step)
3542 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t)
3543 (blur_center.x+center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),
3544 (ssize_t) (blur_center.y+center.x*sin_theta[i]+center.y*
3545 cos_theta[i]+0.5),&pixel,exception);
3546 alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(&pixel));
3547 qixel.red+=alpha*(MagickRealType) pixel.red;
3548 qixel.green+=alpha*(MagickRealType) pixel.green;
3549 qixel.blue+=alpha*(MagickRealType) pixel.blue;
3550 qixel.opacity+=(MagickRealType) pixel.opacity;
3551 if (image->colorspace == CMYKColorspace)
3553 indexes=GetCacheViewVirtualIndexQueue(image_view);
3554 qixel.index+=alpha*(MagickRealType) (*indexes);
3559 gamma=MagickSafeReciprocal(gamma);
3560 normalize=MagickSafeReciprocal(normalize);
3561 if ((channel & RedChannel) != 0)
3562 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) qixel.red));
3563 if ((channel & GreenChannel) != 0)
3564 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType) qixel.green));
3565 if ((channel & BlueChannel) != 0)
3566 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType) qixel.blue));
3567 if ((channel & OpacityChannel) != 0)
3568 SetPixelOpacity(q,ClampToQuantum(normalize*(MagickRealType)
3570 if (((channel & IndexChannel) != 0) &&
3571 (image->colorspace == CMYKColorspace))
3572 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*(MagickRealType)
3577 if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
3579 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3584#if defined(MAGICKCORE_OPENMP_SUPPORT)
3588 proceed=SetImageProgress(image,BlurImageTag,progress,image->rows);
3589 if (proceed == MagickFalse)
3593 blur_view=DestroyCacheView(blur_view);
3594 image_view=DestroyCacheView(image_view);
3595 cos_theta=(MagickRealType *) RelinquishMagickMemory(cos_theta);
3596 sin_theta=(MagickRealType *) RelinquishMagickMemory(sin_theta);
3597 if (status == MagickFalse)
3598 blur_image=DestroyImage(blur_image);
3643MagickExport Image *SelectiveBlurImage(
const Image *image,
const double radius,
3644 const double sigma,
const double threshold,ExceptionInfo *exception)
3649 blur_image=SelectiveBlurImageChannel(image,DefaultChannels,radius,sigma,
3650 threshold,exception);
3654MagickExport Image *SelectiveBlurImageChannel(
const Image *image,
3655 const ChannelType channel,
const double radius,
const double sigma,
3656 const double threshold,ExceptionInfo *exception)
3658#define SelectiveBlurImageTag "SelectiveBlur/Image"
3697 assert(image != (Image *) NULL);
3698 assert(image->signature == MagickCoreSignature);
3699 assert(exception != (ExceptionInfo *) NULL);
3700 assert(exception->signature == MagickCoreSignature);
3701 if (IsEventLogging() != MagickFalse)
3702 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3703 width=GetOptimalKernelWidth1D(radius,sigma);
3704 kernel=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
3705 width*
sizeof(*kernel)));
3706 if (kernel == (
double *) NULL)
3707 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3708 j=(ssize_t) (width-1)/2;
3710 for (v=(-j); v <= j; v++)
3712 for (u=(-j); u <= j; u++)
3713 kernel[i++]=(
double) (exp(-((
double) u*u+v*v)/(2.0*MagickSigma*
3714 MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
3716 if (image->debug != MagickFalse)
3719 format[MaxTextExtent],
3729 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
3730 " SelectiveBlurImage with %.20gx%.20g kernel:",(
double) width,(
double)
3732 message=AcquireString(
"");
3734 for (v=0; v < (ssize_t) width; v++)
3737 (void) FormatLocaleString(format,MaxTextExtent,
"%.20g: ",(
double) v);
3738 (void) ConcatenateString(&message,format);
3739 for (u=0; u < (ssize_t) width; u++)
3741 (void) FormatLocaleString(format,MaxTextExtent,
"%+f ",*k++);
3742 (void) ConcatenateString(&message,format);
3744 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"%s",message);
3746 message=DestroyString(message);
3748 blur_image=CloneImage(image,0,0,MagickTrue,exception);
3749 if (blur_image == (Image *) NULL)
3751 kernel=(
double *) RelinquishAlignedMemory(kernel);
3752 return((Image *) NULL);
3754 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
3756 kernel=(
double *) RelinquishAlignedMemory(kernel);
3757 InheritException(exception,&blur_image->exception);
3758 blur_image=DestroyImage(blur_image);
3759 return((Image *) NULL);
3761 luminance_image=CloneImage(image,0,0,MagickTrue,exception);
3762 if (luminance_image == (Image *) NULL)
3764 kernel=(
double *) RelinquishAlignedMemory(kernel);
3765 blur_image=DestroyImage(blur_image);
3766 return((Image *) NULL);
3768 status=TransformImageColorspace(luminance_image,GRAYColorspace);
3769 if (status == MagickFalse)
3771 InheritException(exception,&luminance_image->exception);
3772 kernel=(
double *) RelinquishAlignedMemory(kernel);
3773 blur_image=DestroyImage(blur_image);
3774 luminance_image=DestroyImage(luminance_image);
3775 return((Image *) NULL);
3782 center=(ssize_t) ((image->columns+width)*((width-1)/2L)+((width-1)/2L));
3783 GetMagickPixelPacket(image,&bias);
3784 SetMagickPixelPacketBias(image,&bias);
3785 image_view=AcquireVirtualCacheView(image,exception);
3786 luminance_view=AcquireVirtualCacheView(luminance_image,exception);
3787 blur_view=AcquireAuthenticCacheView(blur_image,exception);
3788#if defined(MAGICKCORE_OPENMP_SUPPORT)
3789 #pragma omp parallel for schedule(static) shared(progress,status) \
3790 magick_number_threads(image,blur_image,image->rows,1)
3792 for (y=0; y < (ssize_t) image->rows; y++)
3801 *magick_restrict indexes;
3808 *magick_restrict blur_indexes;
3816 if (status == MagickFalse)
3818 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) (width-1)/2L),y-(ssize_t)
3819 ((width-1)/2L),image->columns+width,width,exception);
3820 l=GetCacheViewVirtualPixels(luminance_view,-((ssize_t) (width-1)/2L),y-
3821 (ssize_t) ((width-1)/2L),luminance_image->columns+width,width,exception);
3822 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
3824 if ((p == (
const PixelPacket *) NULL) ||
3825 (l == (
const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
3830 indexes=GetCacheViewVirtualIndexQueue(image_view);
3831 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
3832 for (x=0; x < (ssize_t) image->columns; x++)
3854 pixel.green=bias.green;
3855 pixel.blue=bias.blue;
3856 pixel.opacity=bias.opacity;
3857 pixel.index=bias.index;
3859 intensity=GetPixelIntensity(image,p+center);
3862 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
3864 for (v=0; v < (ssize_t) width; v++)
3866 for (u=0; u < (ssize_t) width; u++)
3868 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3869 if (fabs(contrast) < threshold)
3871 pixel.red+=(*k)*(MagickRealType) GetPixelRed(p+u+j);
3872 pixel.green+=(*k)*(MagickRealType) GetPixelGreen(p+u+j);
3873 pixel.blue+=(*k)*(MagickRealType) GetPixelBlue(p+u+j);
3878 j+=(ssize_t) (image->columns+width);
3882 gamma=MagickSafeReciprocal(gamma);
3883 if ((channel & RedChannel) != 0)
3884 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType)
3886 if ((channel & GreenChannel) != 0)
3887 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType)
3889 if ((channel & BlueChannel) != 0)
3890 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType)
3893 if ((channel & OpacityChannel) != 0)
3897 for (v=0; v < (ssize_t) width; v++)
3899 for (u=0; u < (ssize_t) width; u++)
3901 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3902 if (fabs(contrast) < threshold)
3904 pixel.opacity+=(*k)*(MagickRealType) (p+u+j)->opacity;
3909 j+=(ssize_t) (image->columns+width);
3911 gamma=MagickSafeReciprocal(gamma);
3912 SetPixelOpacity(q,ClampToQuantum(gamma*pixel.opacity));
3914 if (((channel & IndexChannel) != 0) &&
3915 (image->colorspace == CMYKColorspace))
3919 for (v=0; v < (ssize_t) width; v++)
3921 for (u=0; u < (ssize_t) width; u++)
3923 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3924 if (fabs(contrast) < threshold)
3926 pixel.index+=(*k)*(MagickRealType)
3927 GetPixelIndex(indexes+x+u+j);
3932 j+=(ssize_t) (image->columns+width);
3934 gamma=MagickSafeReciprocal(gamma);
3935 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*pixel.index));
3943 for (v=0; v < (ssize_t) width; v++)
3945 for (u=0; u < (ssize_t) width; u++)
3947 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3948 if (fabs(contrast) < threshold)
3950 alpha=(MagickRealType) (QuantumScale*(MagickRealType)
3951 GetPixelAlpha(p+u+j));
3952 pixel.red+=(*k)*alpha*(MagickRealType) GetPixelRed(p+u+j);
3953 pixel.green+=(*k)*alpha*(MagickRealType) GetPixelGreen(p+u+j);
3954 pixel.blue+=(*k)*alpha*(MagickRealType) GetPixelBlue(p+u+j);
3955 pixel.opacity+=(*k)*(MagickRealType) GetPixelOpacity(p+u+j);
3960 j+=(ssize_t) (image->columns+width);
3964 gamma=MagickSafeReciprocal(gamma);
3965 if ((channel & RedChannel) != 0)
3966 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) pixel.red));
3967 if ((channel & GreenChannel) != 0)
3968 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType)
3970 if ((channel & BlueChannel) != 0)
3971 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType)
3974 if ((channel & OpacityChannel) != 0)
3977 for (v=0; v < (ssize_t) width; v++)
3979 for (u=0; u < (ssize_t) width; u++)
3981 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3982 if (fabs(contrast) < threshold)
3983 pixel.opacity+=(*k)*(MagickRealType) GetPixelOpacity(p+u+j);
3986 j+=(ssize_t) (image->columns+width);
3988 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
3990 if (((channel & IndexChannel) != 0) &&
3991 (image->colorspace == CMYKColorspace))
3995 for (v=0; v < (ssize_t) width; v++)
3997 for (u=0; u < (ssize_t) width; u++)
3999 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
4000 if (fabs(contrast) < threshold)
4002 alpha=(MagickRealType) (QuantumScale*(MagickRealType)
4003 GetPixelAlpha(p+u+j));
4004 pixel.index+=(*k)*alpha*(MagickRealType)
4005 GetPixelIndex(indexes+x+u+j);
4010 j+=(ssize_t) (image->columns+width);
4012 gamma=MagickSafeReciprocal(gamma);
4013 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*pixel.index));
4020 sync=SyncCacheViewAuthenticPixels(blur_view,exception);
4021 if (sync == MagickFalse)
4023 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4028#if defined(MAGICKCORE_OPENMP_SUPPORT)
4032 proceed=SetImageProgress(image,SelectiveBlurImageTag,progress,
4034 if (proceed == MagickFalse)
4038 blur_image->type=image->type;
4039 blur_view=DestroyCacheView(blur_view);
4040 luminance_view=DestroyCacheView(luminance_view);
4041 image_view=DestroyCacheView(image_view);
4042 luminance_image=DestroyImage(luminance_image);
4043 kernel=(
double *) RelinquishAlignedMemory(kernel);
4044 if (status == MagickFalse)
4045 blur_image=DestroyImage(blur_image);
4081MagickExport Image *ShadeImage(
const Image *image,
const MagickBooleanType gray,
4082 const double azimuth,
const double elevation,ExceptionInfo *exception)
4084#define GetShadeIntensity(image,pixel) \
4085 ClampPixel(GetPixelIntensity((image),(pixel)))
4086#define ShadeImageTag "Shade/Image"
4111 assert(image != (
const Image *) NULL);
4112 assert(image->signature == MagickCoreSignature);
4113 assert(exception != (ExceptionInfo *) NULL);
4114 assert(exception->signature == MagickCoreSignature);
4115 if (IsEventLogging() != MagickFalse)
4116 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4117 linear_image=CloneImage(image,0,0,MagickTrue,exception);
4118 shade_image=CloneImage(image,0,0,MagickTrue,exception);
4119 if ((linear_image == (Image *) NULL) || (shade_image == (Image *) NULL))
4121 if (linear_image != (Image *) NULL)
4122 linear_image=DestroyImage(linear_image);
4123 if (shade_image != (Image *) NULL)
4124 shade_image=DestroyImage(shade_image);
4125 return((Image *) NULL);
4127 if (SetImageStorageClass(shade_image,DirectClass) == MagickFalse)
4129 InheritException(exception,&shade_image->exception);
4130 linear_image=DestroyImage(linear_image);
4131 shade_image=DestroyImage(shade_image);
4132 return((Image *) NULL);
4137 light.x=(double) QuantumRange*cos(DegreesToRadians(azimuth))*
4138 cos(DegreesToRadians(elevation));
4139 light.y=(double) QuantumRange*sin(DegreesToRadians(azimuth))*
4140 cos(DegreesToRadians(elevation));
4141 light.z=(double) QuantumRange*sin(DegreesToRadians(elevation));
4147 image_view=AcquireVirtualCacheView(linear_image,exception);
4148 shade_view=AcquireAuthenticCacheView(shade_image,exception);
4149#if defined(MAGICKCORE_OPENMP_SUPPORT)
4150 #pragma omp parallel for schedule(static) shared(progress,status) \
4151 magick_number_threads(linear_image,shade_image,linear_image->rows,1)
4153 for (y=0; y < (ssize_t) linear_image->rows; y++)
4165 *magick_restrict s0,
4166 *magick_restrict s1,
4167 *magick_restrict s2;
4175 if (status == MagickFalse)
4177 p=GetCacheViewVirtualPixels(image_view,-1,y-1,linear_image->columns+2,3,
4179 q=QueueCacheViewAuthenticPixels(shade_view,0,y,shade_image->columns,1,
4181 if ((p == (PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
4189 normal.z=2.0*(double) QuantumRange;
4190 for (x=0; x < (ssize_t) linear_image->columns; x++)
4196 s1=s0+image->columns+2;
4197 s2=s1+image->columns+2;
4198 normal.x=(double) (GetShadeIntensity(linear_image,s0-1)+
4199 GetShadeIntensity(linear_image,s1-1)+
4200 GetShadeIntensity(linear_image,s2-1)-
4201 GetShadeIntensity(linear_image,s0+1)-
4202 GetShadeIntensity(linear_image,s1+1)-
4203 GetShadeIntensity(linear_image,s2+1));
4204 normal.y=(double) (GetShadeIntensity(linear_image,s2-1)+
4205 GetShadeIntensity(linear_image,s2)+
4206 GetShadeIntensity(linear_image,s2+1)-
4207 GetShadeIntensity(linear_image,s0-1)-
4208 GetShadeIntensity(linear_image,s0)-
4209 GetShadeIntensity(linear_image,s0+1));
4210 if ((fabs(normal.x) <= MagickEpsilon) &&
4211 (fabs(normal.y) <= MagickEpsilon))
4216 distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
4217 if (distance > MagickEpsilon)
4219 normal_distance=normal.x*normal.x+normal.y*normal.y+normal.z*
4221 if (normal_distance > (MagickEpsilon*MagickEpsilon))
4222 shade=distance/sqrt((
double) normal_distance);
4225 if (gray != MagickFalse)
4227 SetPixelRed(q,shade);
4228 SetPixelGreen(q,shade);
4229 SetPixelBlue(q,shade);
4233 SetPixelRed(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4235 SetPixelGreen(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4236 GetPixelGreen(s1)));
4237 SetPixelBlue(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4240 q->opacity=s1->opacity;
4244 if (SyncCacheViewAuthenticPixels(shade_view,exception) == MagickFalse)
4246 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4251#if defined(MAGICKCORE_OPENMP_SUPPORT)
4255 proceed=SetImageProgress(image,ShadeImageTag,progress,image->rows);
4256 if (proceed == MagickFalse)
4260 shade_view=DestroyCacheView(shade_view);
4261 image_view=DestroyCacheView(image_view);
4262 linear_image=DestroyImage(linear_image);
4263 if (status == MagickFalse)
4264 shade_image=DestroyImage(shade_image);
4265 return(shade_image);
4311MagickExport Image *SharpenImage(
const Image *image,
const double radius,
4312 const double sigma,ExceptionInfo *exception)
4317 sharp_image=SharpenImageChannel(image,DefaultChannels,radius,sigma,exception);
4318 return(sharp_image);
4321MagickExport Image *SharpenImageChannel(
const Image *image,
4322 const ChannelType channel,
const double radius,
const double sigma,
4323 ExceptionInfo *exception)
4346 assert(image != (
const Image *) NULL);
4347 assert(image->signature == MagickCoreSignature);
4348 assert(exception != (ExceptionInfo *) NULL);
4349 assert(exception->signature == MagickCoreSignature);
4350 if (IsEventLogging() != MagickFalse)
4351 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4352 width=GetOptimalKernelWidth2D(radius,sigma);
4353 kernel_info=AcquireKernelInfo((
const char *) NULL);
4355 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
4356 (void) memset(kernel_info,0,
sizeof(*kernel_info));
4357 kernel_info->width=width;
4358 kernel_info->height=width;
4359 kernel_info->x=(ssize_t) (width-1)/2;
4360 kernel_info->y=(ssize_t) (width-1)/2;
4361 kernel_info->signature=MagickCoreSignature;
4362 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
4363 kernel_info->width,kernel_info->height*
sizeof(*kernel_info->values)));
4364 if (kernel_info->values == (
double *) NULL)
4366 kernel_info=DestroyKernelInfo(kernel_info);
4367 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
4370 j=(ssize_t) (kernel_info->width-1)/2;
4372 for (v=(-j); v <= j; v++)
4374 for (u=(-j); u <= j; u++)
4376 kernel_info->values[i]=(double) (-exp(-((
double) u*u+v*v)/(2.0*
4377 MagickSigma*MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
4378 normalize+=kernel_info->values[i];
4382 kernel_info->values[i/2]=(double) ((-2.0)*normalize);
4384 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
4385 normalize+=kernel_info->values[i];
4386 gamma=MagickSafeReciprocal(normalize);
4387 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
4388 kernel_info->values[i]*=gamma;
4389 sharp_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
4390 kernel_info,exception);
4391 kernel_info=DestroyKernelInfo(kernel_info);
4392 return(sharp_image);
4423MagickExport Image *SpreadImage(
const Image *image,
const double radius,
4424 ExceptionInfo *exception)
4426#define SpreadImageTag "Spread/Image"
4445 **magick_restrict random_info;
4453#if defined(MAGICKCORE_OPENMP_SUPPORT)
4461 assert(image != (Image *) NULL);
4462 assert(image->signature == MagickCoreSignature);
4463 assert(exception != (ExceptionInfo *) NULL);
4464 assert(exception->signature == MagickCoreSignature);
4465 if (IsEventLogging() != MagickFalse)
4466 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4467 spread_image=CloneImage(image,0,0,MagickTrue,exception);
4468 if (spread_image == (Image *) NULL)
4469 return((Image *) NULL);
4470 if (SetImageStorageClass(spread_image,DirectClass) == MagickFalse)
4472 InheritException(exception,&spread_image->exception);
4473 spread_image=DestroyImage(spread_image);
4474 return((Image *) NULL);
4481 GetMagickPixelPacket(spread_image,&bias);
4482 width=GetOptimalKernelWidth1D(radius,0.5);
4483 random_info=AcquireRandomInfoTLS();
4484 image_view=AcquireVirtualCacheView(image,exception);
4485 spread_view=AcquireAuthenticCacheView(spread_image,exception);
4486#if defined(MAGICKCORE_OPENMP_SUPPORT)
4487 key=GetRandomSecretKey(random_info[0]);
4488 #pragma omp parallel for schedule(static) shared(progress,status) \
4489 magick_number_threads(image,spread_image,spread_image->rows,key == ~0UL)
4491 for (y=0; y < (ssize_t) spread_image->rows; y++)
4494 id = GetOpenMPThreadId();
4500 *magick_restrict indexes;
4508 if (status == MagickFalse)
4510 q=QueueCacheViewAuthenticPixels(spread_view,0,y,spread_image->columns,1,
4512 if (q == (PixelPacket *) NULL)
4517 indexes=GetCacheViewAuthenticIndexQueue(spread_view);
4519 for (x=0; x < (ssize_t) spread_image->columns; x++)
4524 point.x=GetPseudoRandomValue(random_info[
id]);
4525 point.y=GetPseudoRandomValue(random_info[
id]);
4526 status=InterpolateMagickPixelPacket(image,image_view,image->interpolate,
4527 (
double) x+width*(point.x-0.5),(
double) y+width*(point.y-0.5),&pixel,
4529 if (status == MagickFalse)
4531 SetPixelPacket(spread_image,&pixel,q,indexes+x);
4534 if (SyncCacheViewAuthenticPixels(spread_view,exception) == MagickFalse)
4536 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4541#if defined(MAGICKCORE_OPENMP_SUPPORT)
4545 proceed=SetImageProgress(image,SpreadImageTag,progress,image->rows);
4546 if (proceed == MagickFalse)
4550 spread_view=DestroyCacheView(spread_view);
4551 image_view=DestroyCacheView(image_view);
4552 random_info=DestroyRandomInfoTLS(random_info);
4553 if (status == MagickFalse)
4554 spread_image=DestroyImage(spread_image);
4555 return(spread_image);
4603MagickExport Image *UnsharpMaskImage(
const Image *image,
const double radius,
4604 const double sigma,
const double gain,
const double threshold,
4605 ExceptionInfo *exception)
4611 sharp_image=UnsharpMaskImageChannel(image,DefaultChannels,radius,sigma,gain,
4612 threshold,exception);
4614 return(sharp_image);
4617MagickExport Image *UnsharpMaskImageChannel(
const Image *image,
4618 const ChannelType channel,
const double radius,
const double sigma,
4619 const double gain,
const double threshold,ExceptionInfo *exception)
4621#define SharpenImageTag "Sharpen/Image"
4645 assert(image != (
const Image *) NULL);
4646 assert(image->signature == MagickCoreSignature);
4647 assert(exception != (ExceptionInfo *) NULL);
4648 assert(exception->signature == MagickCoreSignature);
4649 if (IsEventLogging() != MagickFalse)
4650 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4659 unsharp_image=BlurImageChannel(image,(ChannelType) (channel &~ SyncChannels),
4660 radius,sigma,exception);
4661 if (unsharp_image == (Image *) NULL)
4662 return((Image *) NULL);
4663 quantum_threshold=(MagickRealType) QuantumRange*threshold;
4669 GetMagickPixelPacket(image,&bias);
4670 image_view=AcquireVirtualCacheView(image,exception);
4671 unsharp_view=AcquireAuthenticCacheView(unsharp_image,exception);
4672#if defined(MAGICKCORE_OPENMP_SUPPORT)
4673 #pragma omp parallel for schedule(static) shared(progress,status) \
4674 magick_number_threads(image,unsharp_image,image->rows,1)
4676 for (y=0; y < (ssize_t) image->rows; y++)
4682 *magick_restrict indexes;
4688 *magick_restrict unsharp_indexes;
4696 if (status == MagickFalse)
4698 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
4699 q=GetCacheViewAuthenticPixels(unsharp_view,0,y,unsharp_image->columns,1,
4701 if ((p == (
const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
4706 indexes=GetCacheViewVirtualIndexQueue(image_view);
4707 unsharp_indexes=GetCacheViewAuthenticIndexQueue(unsharp_view);
4709 pixel.green=bias.green;
4710 pixel.blue=bias.blue;
4711 pixel.opacity=bias.opacity;
4712 pixel.index=bias.index;
4713 for (x=0; x < (ssize_t) image->columns; x++)
4715 if ((channel & RedChannel) != 0)
4717 pixel.red=(MagickRealType) GetPixelRed(p)-(MagickRealType)
4719 if (fabs(2.0*pixel.red) < quantum_threshold)
4720 pixel.red=(MagickRealType) GetPixelRed(p);
4722 pixel.red=(MagickRealType) GetPixelRed(p)+(pixel.red*gain);
4723 SetPixelRed(q,ClampToQuantum(pixel.red));
4725 if ((channel & GreenChannel) != 0)
4727 pixel.green=(MagickRealType) GetPixelGreen(p)-(MagickRealType)
4729 if (fabs(2.0*pixel.green) < quantum_threshold)
4730 pixel.green=(MagickRealType) GetPixelGreen(p);
4732 pixel.green=(MagickRealType) GetPixelGreen(p)+(pixel.green*gain);
4733 SetPixelGreen(q,ClampToQuantum(pixel.green));
4735 if ((channel & BlueChannel) != 0)
4737 pixel.blue=(MagickRealType) GetPixelBlue(p)-(MagickRealType) q->blue;
4738 if (fabs(2.0*pixel.blue) < quantum_threshold)
4739 pixel.blue=(MagickRealType) GetPixelBlue(p);
4741 pixel.blue=(MagickRealType) GetPixelBlue(p)+(pixel.blue*gain);
4742 SetPixelBlue(q,ClampToQuantum(pixel.blue));
4744 if ((channel & OpacityChannel) != 0)
4746 pixel.opacity=(MagickRealType) GetPixelOpacity(p)-(MagickRealType)
4748 if (fabs(2.0*pixel.opacity) < quantum_threshold)
4749 pixel.opacity=(MagickRealType) GetPixelOpacity(p);
4751 pixel.opacity=(MagickRealType) GetPixelOpacity(p)+
4752 (pixel.opacity*gain);
4753 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
4755 if (((channel & IndexChannel) != 0) &&
4756 (image->colorspace == CMYKColorspace))
4758 pixel.index=(MagickRealType) GetPixelIndex(indexes+x)-
4759 (MagickRealType) GetPixelIndex(unsharp_indexes+x);
4760 if (fabs(2.0*pixel.index) < quantum_threshold)
4761 pixel.index=(MagickRealType) GetPixelIndex(indexes+x);
4763 pixel.index=(MagickRealType) GetPixelIndex(indexes+x)+
4765 SetPixelIndex(unsharp_indexes+x,ClampToQuantum(pixel.index));
4770 if (SyncCacheViewAuthenticPixels(unsharp_view,exception) == MagickFalse)
4772 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4777#if defined(MAGICKCORE_OPENMP_SUPPORT)
4781 proceed=SetImageProgress(image,SharpenImageTag,progress,image->rows);
4782 if (proceed == MagickFalse)
4786 unsharp_image->type=image->type;
4787 unsharp_view=DestroyCacheView(unsharp_view);
4788 image_view=DestroyCacheView(image_view);
4789 if (status == MagickFalse)
4790 unsharp_image=DestroyImage(unsharp_image);
4791 return(unsharp_image);