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"
94#ifdef MAGICKCORE_CLPERFMARKER
95#include "CLPerfMarker.h"
138MagickExport
Image *AdaptiveBlurImage(
const Image *image,
const double radius,
144 blur_image=AdaptiveBlurImageChannel(image,DefaultChannels,radius,sigma,
149MagickExport
Image *AdaptiveBlurImageChannel(
const Image *image,
150 const ChannelType channel,
const double radius,
const double sigma,
153#define AdaptiveBlurImageTag "Convolve/Image"
154#define MagickSigma (fabs(sigma) < MagickEpsilon ? MagickEpsilon : sigma)
192 assert(image != (
const Image *) NULL);
193 assert(image->signature == MagickCoreSignature);
195 assert(exception->signature == MagickCoreSignature);
196 if (IsEventLogging() != MagickFalse)
197 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
198 blur_image=CloneImage(image,0,0,MagickTrue,exception);
199 if (blur_image == (
Image *) NULL)
200 return((
Image *) NULL);
201 if (fabs(sigma) <= MagickEpsilon)
203 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
205 InheritException(exception,&blur_image->exception);
206 blur_image=DestroyImage(blur_image);
207 return((
Image *) NULL);
212 edge_image=EdgeImage(image,radius,exception);
213 if (edge_image == (
Image *) NULL)
215 blur_image=DestroyImage(blur_image);
216 return((
Image *) NULL);
218 (void) AutoLevelImage(edge_image);
219 gaussian_image=BlurImage(edge_image,radius,sigma,exception);
220 if (gaussian_image != (
Image *) NULL)
222 edge_image=DestroyImage(edge_image);
223 edge_image=gaussian_image;
225 (void) AutoLevelImage(edge_image);
229 width=GetOptimalKernelWidth2D(radius,sigma);
230 kernel=(
double **) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
232 if (kernel == (
double **) NULL)
234 edge_image=DestroyImage(edge_image);
235 blur_image=DestroyImage(blur_image);
236 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
238 (void) memset(kernel,0,(
size_t) width*
sizeof(*kernel));
239 for (i=0; i < (ssize_t) width; i+=2)
241 kernel[i]=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t)
242 (width-i),(width-i)*
sizeof(**kernel)));
243 if (kernel[i] == (
double *) NULL)
246 j=(ssize_t) (width-i-1)/2;
248 for (v=(-j); v <= j; v++)
250 for (u=(-j); u <= j; u++)
252 kernel[i][k]=(double) (exp(-((
double) u*u+v*v)/(2.0*MagickSigma*
253 MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
254 normalize+=kernel[i][k];
258 kernel[i][(k-1)/2]+=(1.0-normalize);
259 if (sigma < MagickEpsilon)
260 kernel[i][(k-1)/2]=1.0;
262 if (i < (ssize_t) width)
264 for (i-=2; i >= 0; i-=2)
265 kernel[i]=(
double *) RelinquishAlignedMemory(kernel[i]);
266 kernel=(
double **) RelinquishAlignedMemory(kernel);
267 edge_image=DestroyImage(edge_image);
268 blur_image=DestroyImage(blur_image);
269 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
276 GetMagickPixelPacket(image,&bias);
277 SetMagickPixelPacketBias(image,&bias);
278 image_view=AcquireVirtualCacheView(image,exception);
279 edge_view=AcquireVirtualCacheView(edge_image,exception);
280 blur_view=AcquireAuthenticCacheView(blur_image,exception);
281#if defined(MAGICKCORE_OPENMP_SUPPORT)
282 #pragma omp parallel for schedule(static) shared(progress,status) \
283 magick_number_threads(image,blur_image,blur_image->rows,1)
285 for (y=0; y < (ssize_t) blur_image->rows; y++)
288 *magick_restrict indexes;
295 *magick_restrict blur_indexes;
303 if (status == MagickFalse)
305 r=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns,1,exception);
306 q=QueueCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
313 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
314 for (x=0; x < (ssize_t) blur_image->columns; x++)
332 i=CastDoubleToLong(ceil((
double) width*QuantumScale*
333 GetPixelIntensity(edge_image,r)-0.5));
337 if (i > (ssize_t) width)
341 p=GetCacheViewVirtualPixels(image_view,x-((ssize_t) (width-i)/2L),y-
342 (ssize_t) ((width-i)/2L),width-i,width-i,exception);
345 indexes=GetCacheViewVirtualIndexQueue(image_view);
347 pixel.green=bias.green;
348 pixel.blue=bias.blue;
349 pixel.opacity=bias.opacity;
350 pixel.index=bias.index;
352 for (v=0; v < (ssize_t) (width-i); v++)
354 for (u=0; u < (ssize_t) (width-i); u++)
357 if (((channel & OpacityChannel) != 0) &&
358 (image->matte != MagickFalse))
359 alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(p));
360 if ((channel & RedChannel) != 0)
361 pixel.red+=(*k)*alpha*(double) GetPixelRed(p);
362 if ((channel & GreenChannel) != 0)
363 pixel.green+=(*k)*alpha*(double) GetPixelGreen(p);
364 if ((channel & BlueChannel) != 0)
365 pixel.blue+=(*k)*alpha*(double) GetPixelBlue(p);
366 if ((channel & OpacityChannel) != 0)
367 pixel.opacity+=(*k)*(double) GetPixelOpacity(p);
368 if (((channel & IndexChannel) != 0) &&
369 (image->colorspace == CMYKColorspace))
370 pixel.index+=(*k)*alpha*(double) GetPixelIndex(indexes+x+(width-i)*
377 gamma=PerceptibleReciprocal(gamma);
378 if ((channel & RedChannel) != 0)
379 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) pixel.red));
380 if ((channel & GreenChannel) != 0)
381 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType) pixel.green));
382 if ((channel & BlueChannel) != 0)
383 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType) pixel.blue));
384 if ((channel & OpacityChannel) != 0)
385 SetPixelOpacity(q,ClampToQuantum((MagickRealType) pixel.opacity));
386 if (((channel & IndexChannel) != 0) &&
387 (image->colorspace == CMYKColorspace))
388 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*(MagickRealType)
393 if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
395 if (image->progress_monitor != (MagickProgressMonitor) NULL)
400#if defined(MAGICKCORE_OPENMP_SUPPORT)
404 proceed=SetImageProgress(image,AdaptiveBlurImageTag,progress,
406 if (proceed == MagickFalse)
410 blur_image->type=image->type;
411 blur_view=DestroyCacheView(blur_view);
412 edge_view=DestroyCacheView(edge_view);
413 image_view=DestroyCacheView(image_view);
414 edge_image=DestroyImage(edge_image);
415 for (i=0; i < (ssize_t) width; i+=2)
416 kernel[i]=(
double *) RelinquishAlignedMemory(kernel[i]);
417 kernel=(
double **) RelinquishAlignedMemory(kernel);
418 if (status == MagickFalse)
419 blur_image=DestroyImage(blur_image);
463MagickExport
Image *AdaptiveSharpenImage(
const Image *image,
const double radius,
469 sharp_image=AdaptiveSharpenImageChannel(image,DefaultChannels,radius,sigma,
474MagickExport
Image *AdaptiveSharpenImageChannel(
const Image *image,
475 const ChannelType channel,
const double radius,
const double sigma,
478#define AdaptiveSharpenImageTag "Convolve/Image"
479#define MagickSigma (fabs(sigma) < MagickEpsilon ? MagickEpsilon : sigma)
517 assert(image != (
const Image *) NULL);
518 assert(image->signature == MagickCoreSignature);
520 assert(exception->signature == MagickCoreSignature);
521 if (IsEventLogging() != MagickFalse)
522 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
523 sharp_image=CloneImage(image,0,0,MagickTrue,exception);
524 if (sharp_image == (
Image *) NULL)
525 return((
Image *) NULL);
526 if (fabs(sigma) <= MagickEpsilon)
528 if (SetImageStorageClass(sharp_image,DirectClass) == MagickFalse)
530 InheritException(exception,&sharp_image->exception);
531 sharp_image=DestroyImage(sharp_image);
532 return((
Image *) NULL);
537 edge_image=EdgeImage(image,radius,exception);
538 if (edge_image == (
Image *) NULL)
540 sharp_image=DestroyImage(sharp_image);
541 return((
Image *) NULL);
543 (void) AutoLevelImage(edge_image);
544 gaussian_image=BlurImage(edge_image,radius,sigma,exception);
545 if (gaussian_image != (
Image *) NULL)
547 edge_image=DestroyImage(edge_image);
548 edge_image=gaussian_image;
550 (void) AutoLevelImage(edge_image);
554 width=GetOptimalKernelWidth2D(radius,sigma);
555 kernel=(
double **) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
557 if (kernel == (
double **) NULL)
559 edge_image=DestroyImage(edge_image);
560 sharp_image=DestroyImage(sharp_image);
561 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
563 (void) memset(kernel,0,(
size_t) width*
sizeof(*kernel));
564 for (i=0; i < (ssize_t) width; i+=2)
566 kernel[i]=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t)
567 (width-i),(width-i)*
sizeof(**kernel)));
568 if (kernel[i] == (
double *) NULL)
571 j=(ssize_t) (width-i-1)/2;
573 for (v=(-j); v <= j; v++)
575 for (u=(-j); u <= j; u++)
577 kernel[i][k]=(double) (-exp(-((
double) u*u+v*v)/(2.0*MagickSigma*
578 MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
579 normalize+=kernel[i][k];
583 kernel[i][(k-1)/2]=(
double) ((-2.0)*normalize);
584 if (sigma < MagickEpsilon)
585 kernel[i][(k-1)/2]=1.0;
587 if (i < (ssize_t) width)
589 for (i-=2; i >= 0; i-=2)
590 kernel[i]=(
double *) RelinquishAlignedMemory(kernel[i]);
591 kernel=(
double **) RelinquishAlignedMemory(kernel);
592 edge_image=DestroyImage(edge_image);
593 sharp_image=DestroyImage(sharp_image);
594 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
601 GetMagickPixelPacket(image,&bias);
602 SetMagickPixelPacketBias(image,&bias);
603 image_view=AcquireVirtualCacheView(image,exception);
604 edge_view=AcquireVirtualCacheView(edge_image,exception);
605 sharp_view=AcquireAuthenticCacheView(sharp_image,exception);
606#if defined(MAGICKCORE_OPENMP_SUPPORT)
607 #pragma omp parallel for schedule(static) shared(progress,status) \
608 magick_number_threads(image,sharp_image,sharp_image->rows,1)
610 for (y=0; y < (ssize_t) sharp_image->rows; y++)
613 *magick_restrict indexes;
620 *magick_restrict sharp_indexes;
628 if (status == MagickFalse)
630 r=GetCacheViewVirtualPixels(edge_view,0,y,edge_image->columns,1,exception);
631 q=QueueCacheViewAuthenticPixels(sharp_view,0,y,sharp_image->columns,1,
638 sharp_indexes=GetCacheViewAuthenticIndexQueue(sharp_view);
639 for (x=0; x < (ssize_t) sharp_image->columns; x++)
657 i=CastDoubleToLong(ceil((
double) width*(1.0-QuantumScale*
658 GetPixelIntensity(edge_image,r))-0.5));
662 if (i > (ssize_t) width)
666 p=GetCacheViewVirtualPixels(image_view,x-((ssize_t) (width-i)/2L),y-
667 (ssize_t) ((width-i)/2L),width-i,width-i,exception);
670 indexes=GetCacheViewVirtualIndexQueue(image_view);
673 pixel.green=bias.green;
674 pixel.blue=bias.blue;
675 pixel.opacity=bias.opacity;
676 pixel.index=bias.index;
677 for (v=0; v < (ssize_t) (width-i); v++)
679 for (u=0; u < (ssize_t) (width-i); u++)
682 if (((channel & OpacityChannel) != 0) &&
683 (image->matte != MagickFalse))
684 alpha=(MagickRealType) (QuantumScale*(MagickRealType)
686 if ((channel & RedChannel) != 0)
687 pixel.red+=(*k)*alpha*(MagickRealType) GetPixelRed(p);
688 if ((channel & GreenChannel) != 0)
689 pixel.green+=(*k)*alpha*(MagickRealType) GetPixelGreen(p);
690 if ((channel & BlueChannel) != 0)
691 pixel.blue+=(*k)*alpha*(MagickRealType) GetPixelBlue(p);
692 if ((channel & OpacityChannel) != 0)
693 pixel.opacity+=(*k)*(MagickRealType) GetPixelOpacity(p);
694 if (((channel & IndexChannel) != 0) &&
695 (image->colorspace == CMYKColorspace))
696 pixel.index+=(*k)*alpha*(MagickRealType)
697 GetPixelIndex(indexes+x+(width-i)*v+u);
703 gamma=PerceptibleReciprocal(gamma);
704 if ((channel & RedChannel) != 0)
705 SetPixelRed(q,ClampToQuantum(gamma*pixel.red));
706 if ((channel & GreenChannel) != 0)
707 SetPixelGreen(q,ClampToQuantum(gamma*pixel.green));
708 if ((channel & BlueChannel) != 0)
709 SetPixelBlue(q,ClampToQuantum(gamma*pixel.blue));
710 if ((channel & OpacityChannel) != 0)
711 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
712 if (((channel & IndexChannel) != 0) &&
713 (image->colorspace == CMYKColorspace))
714 SetPixelIndex(sharp_indexes+x,ClampToQuantum(gamma*pixel.index));
718 if (SyncCacheViewAuthenticPixels(sharp_view,exception) == MagickFalse)
720 if (image->progress_monitor != (MagickProgressMonitor) NULL)
725#if defined(MAGICKCORE_OPENMP_SUPPORT)
729 proceed=SetImageProgress(image,AdaptiveSharpenImageTag,progress,
731 if (proceed == MagickFalse)
735 sharp_image->type=image->type;
736 sharp_view=DestroyCacheView(sharp_view);
737 edge_view=DestroyCacheView(edge_view);
738 image_view=DestroyCacheView(image_view);
739 edge_image=DestroyImage(edge_image);
740 for (i=0; i < (ssize_t) width; i+=2)
741 kernel[i]=(
double *) RelinquishAlignedMemory(kernel[i]);
742 kernel=(
double **) RelinquishAlignedMemory(kernel);
743 if (status == MagickFalse)
744 sharp_image=DestroyImage(sharp_image);
786MagickExport
Image *BlurImage(
const Image *image,
const double radius,
792 blur_image=BlurImageChannel(image,DefaultChannels,radius,sigma,exception);
796MagickExport
Image *BlurImageChannel(
const Image *image,
797 const ChannelType channel,
const double radius,
const double sigma,
801 geometry[MaxTextExtent];
809 assert(image != (
const Image *) NULL);
810 assert(image->signature == MagickCoreSignature);
812 assert(exception->signature == MagickCoreSignature);
813 if (IsEventLogging() != MagickFalse)
814 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
815#if defined(MAGICKCORE_OPENCL_SUPPORT)
816 blur_image=AccelerateBlurImage(image,channel,radius,sigma,exception);
817 if (blur_image != (
Image *) NULL)
820 (void) FormatLocaleString(geometry,MaxTextExtent,
821 "blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma);
822 kernel_info=AcquireKernelInfo(geometry);
824 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
825 blur_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
826 kernel_info,exception);
827 kernel_info=DestroyKernelInfo(kernel_info);
865MagickExport
Image *ConvolveImage(
const Image *image,
const size_t order,
871#ifdef MAGICKCORE_CLPERFMARKER
872 clBeginPerfMarkerAMD(__FUNCTION__,
"");
875 convolve_image=ConvolveImageChannel(image,DefaultChannels,order,kernel,
878#ifdef MAGICKCORE_CLPERFMARKER
879 clEndPerfMarkerAMD();
881 return(convolve_image);
884MagickExport
Image *ConvolveImageChannel(
const Image *image,
885 const ChannelType channel,
const size_t order,
const double *kernel,
897 kernel_info=AcquireKernelInfo((
const char *) NULL);
899 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
900 kernel_info->width=order;
901 kernel_info->height=order;
902 kernel_info->x=(ssize_t) (order-1)/2;
903 kernel_info->y=(ssize_t) (order-1)/2;
904 kernel_info->signature=MagickCoreSignature;
905 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
906 kernel_info->width,kernel_info->width*
sizeof(*kernel_info->values)));
907 if (kernel_info->values == (
double *) NULL)
909 kernel_info=DestroyKernelInfo(kernel_info);
910 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
912 for (i=0; i < (ssize_t) (order*order); i++)
913 kernel_info->values[i]=kernel[i];
914 convolve_image=(
Image *) NULL;
915#if defined(MAGICKCORE_OPENCL_SUPPORT)
916 convolve_image=AccelerateConvolveImageChannel(image,channel,kernel_info,
919 if (convolve_image == (
Image *) NULL)
920 convolve_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
921 kernel_info,exception);
922 kernel_info=DestroyKernelInfo(kernel_info);
923 return(convolve_image);
956static void Hull(
const Image *image,
const ssize_t x_offset,
957 const ssize_t y_offset,
const size_t columns,
const size_t rows,
958 const int polarity,Quantum *magick_restrict f,Quantum *magick_restrict g)
969 assert(image != (
const Image *) NULL);
970 assert(image->signature == MagickCoreSignature);
971 assert(f != (Quantum *) NULL);
972 assert(g != (Quantum *) NULL);
973 assert(columns <= (MAGICK_SSIZE_MAX-2));
974 p=f+(ptrdiff_t) (columns+2);
975 q=g+(ptrdiff_t) (columns+2);
976 r=p+(ptrdiff_t) (y_offset*((ssize_t) columns+2)+x_offset);
977#if defined(MAGICKCORE_OPENMP_SUPPORT)
978 #pragma omp parallel for schedule(static) \
979 magick_number_threads(image,image,rows,2)
981 for (y=0; y < (ssize_t) rows; y++)
992 for (x=0; x < (ssize_t) columns; x++)
994 v=(SignedQuantum) p[i];
995 if ((SignedQuantum) r[i] >= (v+ScaleCharToQuantum(2)))
996 v+=ScaleCharToQuantum(1);
1001 for (x=0; x < (ssize_t) columns; x++)
1003 v=(SignedQuantum) p[i];
1004 if ((SignedQuantum) r[i] <= (v-ScaleCharToQuantum(2)))
1005 v-=ScaleCharToQuantum(1);
1011 p=f+(ptrdiff_t) (columns+2);
1012 q=g+(ptrdiff_t) (columns+2);
1013 r=q+(ptrdiff_t) (y_offset*((ssize_t) columns+2)+x_offset);
1014 s=q-(ptrdiff_t) (y_offset*((ssize_t) columns+2)+x_offset);
1015#if defined(MAGICKCORE_OPENMP_SUPPORT)
1016 #pragma omp parallel for schedule(static) \
1017 magick_number_threads(image,image,rows,2)
1019 for (y=0; y < (ssize_t) rows; y++)
1028 i=(2*y+1)+y*columns;
1030 for (x=0; x < (ssize_t) columns; x++)
1032 v=(SignedQuantum) q[i];
1033 if (((SignedQuantum) s[i] >= (v+ScaleCharToQuantum(2))) &&
1034 ((SignedQuantum) r[i] > v))
1035 v+=ScaleCharToQuantum(1);
1040 for (x=0; x < (ssize_t) columns; x++)
1042 v=(SignedQuantum) q[i];
1043 if (((SignedQuantum) s[i] <= (v-ScaleCharToQuantum(2))) &&
1044 ((SignedQuantum) r[i] < v))
1045 v-=ScaleCharToQuantum(1);
1054#define DespeckleImageTag "Despeckle/Image"
1074 *magick_restrict buffer,
1075 *magick_restrict pixels;
1081 static const ssize_t
1082 X[4] = {0, 1, 1,-1},
1083 Y[4] = {1, 0, 1, 1};
1088 assert(image != (
const Image *) NULL);
1089 assert(image->signature == MagickCoreSignature);
1091 assert(exception->signature == MagickCoreSignature);
1092 if (IsEventLogging() != MagickFalse)
1093 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1094#if defined(MAGICKCORE_OPENCL_SUPPORT)
1095 despeckle_image=AccelerateDespeckleImage(image, exception);
1096 if (despeckle_image != (
Image *) NULL)
1097 return(despeckle_image);
1099 despeckle_image=CloneImage(image,0,0,MagickTrue,exception);
1100 if (despeckle_image == (
Image *) NULL)
1101 return((
Image *) NULL);
1102 if (SetImageStorageClass(despeckle_image,DirectClass) == MagickFalse)
1104 InheritException(exception,&despeckle_image->exception);
1105 despeckle_image=DestroyImage(despeckle_image);
1106 return((
Image *) NULL);
1111 length=(size_t) ((image->columns+2)*(image->rows+2));
1112 pixel_info=AcquireVirtualMemory(length,
sizeof(*pixels));
1113 buffer_info=AcquireVirtualMemory(length,
sizeof(*buffer));
1118 buffer_info=RelinquishVirtualMemory(buffer_info);
1120 pixel_info=RelinquishVirtualMemory(pixel_info);
1121 despeckle_image=DestroyImage(despeckle_image);
1122 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1124 pixels=(Quantum *) GetVirtualMemoryBlob(pixel_info);
1125 buffer=(Quantum *) GetVirtualMemoryBlob(buffer_info);
1130 number_channels=(size_t) (image->colorspace == CMYKColorspace ? 5 : 4);
1131 image_view=AcquireVirtualCacheView(image,exception);
1132 despeckle_view=AcquireAuthenticCacheView(despeckle_image,exception);
1133 for (i=0; i < (ssize_t) number_channels; i++)
1143 if (status == MagickFalse)
1145 if ((image->matte == MagickFalse) && (i == 3))
1147 (void) memset(pixels,0,length*
sizeof(*pixels));
1148 j=(ssize_t) image->columns+2;
1149 for (y=0; y < (ssize_t) image->rows; y++)
1152 *magick_restrict indexes;
1157 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1160 indexes=GetCacheViewVirtualIndexQueue(image_view);
1162 for (x=0; x < (ssize_t) image->columns; x++)
1166 case 0: pixels[j]=GetPixelRed(p);
break;
1167 case 1: pixels[j]=GetPixelGreen(p);
break;
1168 case 2: pixels[j]=GetPixelBlue(p);
break;
1169 case 3: pixels[j]=GetPixelOpacity(p);
break;
1170 case 4: pixels[j]=GetPixelBlack(indexes+x);
break;
1178 (void) memset(buffer,0,length*
sizeof(*buffer));
1179 for (k=0; k < 4; k++)
1181 Hull(image,X[k],Y[k],image->columns,image->rows,1,pixels,buffer);
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);
1186 j=(ssize_t) image->columns+2;
1187 for (y=0; y < (ssize_t) image->rows; y++)
1193 *magick_restrict indexes;
1198 q=GetCacheViewAuthenticPixels(despeckle_view,0,y,despeckle_image->columns,
1202 indexes=GetCacheViewAuthenticIndexQueue(despeckle_view);
1204 for (x=0; x < (ssize_t) image->columns; x++)
1208 case 0: SetPixelRed(q,pixels[j]);
break;
1209 case 1: SetPixelGreen(q,pixels[j]);
break;
1210 case 2: SetPixelBlue(q,pixels[j]);
break;
1211 case 3: SetPixelOpacity(q,pixels[j]);
break;
1212 case 4: SetPixelIndex(indexes+x,pixels[j]);
break;
1218 sync=SyncCacheViewAuthenticPixels(despeckle_view,exception);
1219 if (sync == MagickFalse)
1226 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1231 proceed=SetImageProgress(image,DespeckleImageTag,(MagickOffsetType) i,
1233 if (proceed == MagickFalse)
1237 despeckle_view=DestroyCacheView(despeckle_view);
1238 image_view=DestroyCacheView(image_view);
1239 buffer_info=RelinquishVirtualMemory(buffer_info);
1240 pixel_info=RelinquishVirtualMemory(pixel_info);
1241 despeckle_image->type=image->type;
1242 if (status == MagickFalse)
1243 despeckle_image=DestroyImage(despeckle_image);
1244 return(despeckle_image);
1276MagickExport
Image *EdgeImage(
const Image *image,
const double radius,
1291 assert(image != (
const Image *) NULL);
1292 assert(image->signature == MagickCoreSignature);
1294 assert(exception->signature == MagickCoreSignature);
1295 if (IsEventLogging() != MagickFalse)
1296 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1297 width=GetOptimalKernelWidth1D(radius,0.5);
1298 kernel_info=AcquireKernelInfo((
const char *) NULL);
1300 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1301 (void) memset(kernel_info,0,
sizeof(*kernel_info));
1302 kernel_info->width=width;
1303 kernel_info->height=width;
1304 kernel_info->x=(ssize_t) (kernel_info->width-1)/2;
1305 kernel_info->y=(ssize_t) (kernel_info->height-1)/2;
1306 kernel_info->signature=MagickCoreSignature;
1307 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
1308 kernel_info->width,kernel_info->height*
sizeof(*kernel_info->values)));
1309 if (kernel_info->values == (
double *) NULL)
1311 kernel_info=DestroyKernelInfo(kernel_info);
1312 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1314 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1315 kernel_info->values[i]=(-1.0);
1316 kernel_info->values[i/2]=(double) kernel_info->width*kernel_info->height-1.0;
1317 edge_image=(
Image *) NULL;
1318#if defined(MAGICKCORE_OPENCL_SUPPORT)
1319 edge_image=AccelerateConvolveImageChannel(image,DefaultChannels,kernel_info,
1322 if (edge_image == (
Image *) NULL)
1323 edge_image=MorphologyImageChannel(image,DefaultChannels,ConvolveMorphology,
1324 1,kernel_info,exception);
1325 kernel_info=DestroyKernelInfo(kernel_info);
1362MagickExport
Image *EmbossImage(
const Image *image,
const double radius,
1387 assert(image != (
const Image *) NULL);
1388 assert(image->signature == MagickCoreSignature);
1390 assert(exception->signature == MagickCoreSignature);
1391 if (IsEventLogging() != MagickFalse)
1392 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1393 width=GetOptimalKernelWidth1D(radius,sigma);
1394 kernel_info=AcquireKernelInfo((
const char *) NULL);
1396 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1397 kernel_info->width=width;
1398 kernel_info->height=width;
1399 kernel_info->x=(ssize_t) (width-1)/2;
1400 kernel_info->y=(ssize_t) (width-1)/2;
1401 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
1402 kernel_info->width,kernel_info->width*
sizeof(*kernel_info->values)));
1403 if (kernel_info->values == (
double *) NULL)
1405 kernel_info=DestroyKernelInfo(kernel_info);
1406 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1408 j=(ssize_t) (kernel_info->width-1)/2;
1411 for (v=(-j); v <= j; v++)
1413 for (u=(-j); u <= j; u++)
1415 kernel_info->values[i]=(double) (((u < 0) || (v < 0) ? -8.0 :
1416 8.0)*exp(-((
double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
1417 (2.0*MagickPI*MagickSigma*MagickSigma));
1419 kernel_info->values[i]=0.0;
1425 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1426 normalize+=kernel_info->values[i];
1427 gamma=PerceptibleReciprocal(normalize);
1428 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1429 kernel_info->values[i]*=gamma;
1430 emboss_image=(
Image *) NULL;
1431#if defined(MAGICKCORE_OPENCL_SUPPORT)
1432 emboss_image=AccelerateConvolveImageChannel(image,DefaultChannels,kernel_info,
1435 if (emboss_image == (
Image *) NULL)
1436 emboss_image=MorphologyImageChannel(image,DefaultChannels,
1437 ConvolveMorphology,1,kernel_info,exception);
1438 kernel_info=DestroyKernelInfo(kernel_info);
1439 if (emboss_image != (
Image *) NULL)
1440 (void) EqualizeImageChannel(emboss_image,(ChannelType)
1441 (AllChannels &~ SyncChannels));
1442 return(emboss_image);
1483 filter_image=FilterImageChannel(image,DefaultChannels,kernel,exception);
1484 return(filter_image);
1487MagickExport
Image *FilterImageChannel(
const Image *image,
1490#define FilterImageTag "Filter/Image"
1517#ifdef MAGICKCORE_CLPERFMARKER
1518 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1524 assert(image != (
Image *) NULL);
1525 assert(image->signature == MagickCoreSignature);
1527 assert(exception->signature == MagickCoreSignature);
1528 if (IsEventLogging() != MagickFalse)
1529 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1530 if ((kernel->width % 2) == 0)
1531 ThrowImageException(OptionError,
"KernelWidthMustBeAnOddNumber");
1532 if (image->debug != MagickFalse)
1535 format[MaxTextExtent],
1545 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
1546 " FilterImage with %.20gx%.20g kernel:",(
double) kernel->width,(
double)
1548 message=AcquireString(
"");
1550 for (v=0; v < (ssize_t) kernel->height; v++)
1553 (void) FormatLocaleString(format,MaxTextExtent,
"%.20g: ",(
double) v);
1554 (void) ConcatenateString(&message,format);
1555 for (u=0; u < (ssize_t) kernel->width; u++)
1557 (void) FormatLocaleString(format,MaxTextExtent,
"%g ",*k++);
1558 (void) ConcatenateString(&message,format);
1560 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"%s",message);
1562 message=DestroyString(message);
1564#if defined(MAGICKCORE_OPENCL_SUPPORT)
1565 filter_image=AccelerateConvolveImageChannel(image,channel,kernel,exception);
1566 if (filter_image != (
Image *) NULL)
1568#ifdef MAGICKCORE_CLPERFMARKER
1569 clEndPerfMarkerAMD();
1571 return(filter_image);
1574 filter_image=CloneImage(image,0,0,MagickTrue,exception);
1575 if (filter_image == (
Image *) NULL)
1576 return((
Image *) NULL);
1577 if (SetImageStorageClass(filter_image,DirectClass) == MagickFalse)
1579 InheritException(exception,&filter_image->exception);
1580 filter_image=DestroyImage(filter_image);
1581 return((
Image *) NULL);
1586 filter_kernel=(MagickRealType *) MagickAssumeAligned(AcquireAlignedMemory(
1587 kernel->width,kernel->height*
sizeof(*filter_kernel)));
1588 if (filter_kernel == (MagickRealType *) NULL)
1590 filter_image=DestroyImage(filter_image);
1591 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1593 for (i=0; i < (ssize_t) (kernel->width*kernel->height); i++)
1594 filter_kernel[i]=(MagickRealType) kernel->values[i];
1600 GetMagickPixelPacket(image,&bias);
1601 SetMagickPixelPacketBias(image,&bias);
1602 image_view=AcquireVirtualCacheView(image,exception);
1603 filter_view=AcquireAuthenticCacheView(filter_image,exception);
1604#if defined(MAGICKCORE_OPENMP_SUPPORT)
1605 #pragma omp parallel for schedule(static) shared(progress,status) \
1606 magick_number_threads(image,filter_image,image->rows,1)
1608 for (y=0; y < (ssize_t) image->rows; y++)
1614 *magick_restrict indexes;
1620 *magick_restrict filter_indexes;
1628 if (status == MagickFalse)
1630 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) (kernel->width-1)/2L),y-
1631 (ssize_t) ((kernel->height-1)/2L),image->columns+kernel->width,
1632 kernel->height,exception);
1633 q=GetCacheViewAuthenticPixels(filter_view,0,y,filter_image->columns,1,
1640 indexes=GetCacheViewVirtualIndexQueue(image_view);
1641 filter_indexes=GetCacheViewAuthenticIndexQueue(filter_view);
1642 for (x=0; x < (ssize_t) image->columns; x++)
1647 const MagickRealType
1651 *magick_restrict kernel_pixels;
1660 pixel.green=bias.green;
1661 pixel.blue=bias.blue;
1662 pixel.opacity=bias.opacity;
1663 pixel.index=bias.index;
1666 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
1668 for (v=0; v < (ssize_t) kernel->width; v++)
1670 for (u=0; u < (ssize_t) kernel->height; u++)
1672 pixel.red+=(*k)*(double) kernel_pixels[u].red;
1673 pixel.green+=(*k)*(double) kernel_pixels[u].green;
1674 pixel.blue+=(*k)*(double) kernel_pixels[u].blue;
1677 kernel_pixels+=image->columns+kernel->width;
1679 if ((channel & RedChannel) != 0)
1680 SetPixelRed(q,ClampToQuantum(pixel.red));
1681 if ((channel & GreenChannel) != 0)
1682 SetPixelGreen(q,ClampToQuantum(pixel.green));
1683 if ((channel & BlueChannel) != 0)
1684 SetPixelBlue(q,ClampToQuantum(pixel.blue));
1685 if ((channel & OpacityChannel) != 0)
1689 for (v=0; v < (ssize_t) kernel->width; v++)
1691 for (u=0; u < (ssize_t) kernel->height; u++)
1693 pixel.opacity+=(*k)*(MagickRealType) kernel_pixels[u].opacity;
1696 kernel_pixels+=image->columns+kernel->width;
1698 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
1700 if (((channel & IndexChannel) != 0) &&
1701 (image->colorspace == CMYKColorspace))
1704 *magick_restrict kernel_indexes;
1707 kernel_indexes=indexes;
1708 for (v=0; v < (ssize_t) kernel->width; v++)
1710 for (u=0; u < (ssize_t) kernel->height; u++)
1712 pixel.index+=(*k)*(double) GetPixelIndex(kernel_indexes+u);
1715 kernel_indexes+=image->columns+kernel->width;
1717 SetPixelIndex(filter_indexes+x,ClampToQuantum(pixel.index));
1727 for (v=0; v < (ssize_t) kernel->width; v++)
1729 for (u=0; u < (ssize_t) kernel->height; u++)
1731 alpha=(MagickRealType) QuantumScale*((MagickRealType)
1732 QuantumRange-(MagickRealType) GetPixelOpacity(kernel_pixels+u));
1733 pixel.red+=(*k)*alpha*(double) GetPixelRed(kernel_pixels+u);
1734 pixel.green+=(*k)*alpha*(double) GetPixelGreen(kernel_pixels+u);
1735 pixel.blue+=(*k)*alpha*(double) GetPixelBlue(kernel_pixels+u);
1739 kernel_pixels+=image->columns+kernel->width;
1741 gamma=PerceptibleReciprocal(gamma);
1742 if ((channel & RedChannel) != 0)
1743 SetPixelRed(q,ClampToQuantum(gamma*(
double) pixel.red));
1744 if ((channel & GreenChannel) != 0)
1745 SetPixelGreen(q,ClampToQuantum(gamma*(
double) pixel.green));
1746 if ((channel & BlueChannel) != 0)
1747 SetPixelBlue(q,ClampToQuantum(gamma*(
double) pixel.blue));
1748 if ((channel & OpacityChannel) != 0)
1752 for (v=0; v < (ssize_t) kernel->width; v++)
1754 for (u=0; u < (ssize_t) kernel->height; u++)
1756 pixel.opacity+=(*k)*(double) GetPixelOpacity(kernel_pixels+u);
1759 kernel_pixels+=image->columns+kernel->width;
1761 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
1763 if (((channel & IndexChannel) != 0) &&
1764 (image->colorspace == CMYKColorspace))
1767 *magick_restrict kernel_indexes;
1771 kernel_indexes=indexes;
1772 for (v=0; v < (ssize_t) kernel->width; v++)
1774 for (u=0; u < (ssize_t) kernel->height; u++)
1776 alpha=(MagickRealType) (QuantumScale*((
double) QuantumRange-
1777 (
double) kernel_pixels[u].opacity));
1778 pixel.index+=(*k)*alpha*(MagickRealType)
1779 GetPixelIndex(kernel_indexes+u);
1782 kernel_pixels+=image->columns+kernel->width;
1783 kernel_indexes+=image->columns+kernel->width;
1785 SetPixelIndex(filter_indexes+x,ClampToQuantum(gamma*(
double)
1793 sync=SyncCacheViewAuthenticPixels(filter_view,exception);
1794 if (sync == MagickFalse)
1796 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1801#if defined(MAGICKCORE_OPENMP_SUPPORT)
1805 proceed=SetImageProgress(image,FilterImageTag,progress,image->rows);
1806 if (proceed == MagickFalse)
1810 filter_image->type=image->type;
1811 filter_view=DestroyCacheView(filter_view);
1812 image_view=DestroyCacheView(image_view);
1813 filter_kernel=(MagickRealType *) RelinquishAlignedMemory(filter_kernel);
1814 if (status == MagickFalse)
1815 filter_image=DestroyImage(filter_image);
1816#ifdef MAGICKCORE_CLPERFMARKER
1817 clEndPerfMarkerAMD();
1819 return(filter_image);
1861MagickExport
Image *GaussianBlurImage(
const Image *image,
const double radius,
1867 blur_image=GaussianBlurImageChannel(image,DefaultChannels,radius,sigma,
1872MagickExport
Image *GaussianBlurImageChannel(
const Image *image,
1873 const ChannelType channel,
const double radius,
const double sigma,
1877 geometry[MaxTextExtent];
1885 assert(image != (
const Image *) NULL);
1886 assert(image->signature == MagickCoreSignature);
1888 assert(exception->signature == MagickCoreSignature);
1889 if (IsEventLogging() != MagickFalse)
1890 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1891 (void) FormatLocaleString(geometry,MaxTextExtent,
"gaussian:%.20gx%.20g",
1893 kernel_info=AcquireKernelInfo(geometry);
1895 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1896 blur_image=(
Image *) NULL;
1897#if defined(MAGICKCORE_OPENCL_SUPPORT)
1898 blur_image=AccelerateConvolveImageChannel(image,channel,kernel_info,
1901 if (blur_image == (
Image *) NULL)
1902 blur_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
1903 kernel_info,exception);
1904 kernel_info=DestroyKernelInfo(kernel_info);
1952static double *GetMotionBlurKernel(
const size_t width,
const double sigma)
1964 if (IsEventLogging() != MagickFalse)
1965 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1966 kernel=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
1968 if (kernel == (
double *) NULL)
1971 for (i=0; i < (ssize_t) width; i++)
1973 kernel[i]=(double) (exp((-((
double) i*i)/(
double) (2.0*MagickSigma*
1974 MagickSigma)))/(MagickSQ2PI*MagickSigma));
1975 normalize+=kernel[i];
1977 for (i=0; i < (ssize_t) width; i++)
1978 kernel[i]/=normalize;
1982MagickExport
Image *MotionBlurImage(
const Image *image,
const double radius,
1983 const double sigma,
const double angle,
ExceptionInfo *exception)
1988 motion_blur=MotionBlurImageChannel(image,DefaultChannels,radius,sigma,angle,
1990 return(motion_blur);
1993MagickExport
Image *MotionBlurImageChannel(
const Image *image,
1994 const ChannelType channel,
const double radius,
const double sigma,
1997#define BlurImageTag "Blur/Image"
2033 assert(image != (
Image *) NULL);
2034 assert(image->signature == MagickCoreSignature);
2036 assert(exception->signature == MagickCoreSignature);
2037 if (IsEventLogging() != MagickFalse)
2038 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2039 width=GetOptimalKernelWidth1D(radius,sigma);
2040 kernel=GetMotionBlurKernel(width,sigma);
2041 if (kernel == (
double *) NULL)
2042 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2043 offset=(
OffsetInfo *) AcquireQuantumMemory(width,
sizeof(*offset));
2046 kernel=(
double *) RelinquishAlignedMemory(kernel);
2047 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2050 point.x=(double) width*sin(DegreesToRadians(angle));
2051 point.y=(double) width*cos(DegreesToRadians(angle));
2052 for (i=0; i < (ssize_t) width; i++)
2054 offset[i].x=CastDoubleToLong(ceil((
double) (i*point.y)/
2055 hypot(point.x,point.y)-0.5));
2056 offset[i].y=CastDoubleToLong(ceil((
double) (i*point.x)/
2057 hypot(point.x,point.y)-0.5));
2063#if defined(MAGICKCORE_OPENCL_SUPPORT)
2064 blur_image=AccelerateMotionBlurImage(image,channel,kernel,width,offset,
2066 if (blur_image != (
Image *) NULL)
2069 blur_image=CloneImage(image,0,0,MagickTrue,exception);
2070 if (blur_image == (
Image *) NULL)
2072 kernel=(
double *) RelinquishAlignedMemory(kernel);
2073 offset=(
OffsetInfo *) RelinquishMagickMemory(offset);
2074 return((
Image *) NULL);
2076 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
2078 kernel=(
double *) RelinquishAlignedMemory(kernel);
2079 offset=(
OffsetInfo *) RelinquishMagickMemory(offset);
2080 InheritException(exception,&blur_image->exception);
2081 blur_image=DestroyImage(blur_image);
2082 return((
Image *) NULL);
2087 GetMagickPixelPacket(image,&bias);
2088 image_view=AcquireVirtualCacheView(image,exception);
2089 blur_view=AcquireAuthenticCacheView(blur_image,exception);
2090#if defined(MAGICKCORE_OPENMP_SUPPORT)
2091 #pragma omp parallel for schedule(static) shared(progress,status) \
2092 magick_number_threads(image,blur_image,image->rows,1)
2094 for (y=0; y < (ssize_t) image->rows; y++)
2097 *magick_restrict blur_indexes;
2105 if (status == MagickFalse)
2107 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
2114 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
2115 for (x=0; x < (ssize_t) image->columns; x++)
2124 *magick_restrict indexes;
2134 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
2136 for (i=0; i < (ssize_t) width; i++)
2138 (void) GetOneCacheViewVirtualPixel(image_view,x+offset[i].x,y+
2139 offset[i].y,&pixel,exception);
2140 qixel.red+=(*k)*(double) pixel.red;
2141 qixel.green+=(*k)*(double) pixel.green;
2142 qixel.blue+=(*k)*(double) pixel.blue;
2143 qixel.opacity+=(*k)*(double) pixel.opacity;
2144 if (image->colorspace == CMYKColorspace)
2146 indexes=GetCacheViewVirtualIndexQueue(image_view);
2147 qixel.index+=(*k)*(double) (*indexes);
2151 if ((channel & RedChannel) != 0)
2152 SetPixelRed(q,ClampToQuantum(qixel.red));
2153 if ((channel & GreenChannel) != 0)
2154 SetPixelGreen(q,ClampToQuantum(qixel.green));
2155 if ((channel & BlueChannel) != 0)
2156 SetPixelBlue(q,ClampToQuantum(qixel.blue));
2157 if ((channel & OpacityChannel) != 0)
2158 SetPixelOpacity(q,ClampToQuantum(qixel.opacity));
2159 if (((channel & IndexChannel) != 0) &&
2160 (image->colorspace == CMYKColorspace))
2161 SetPixelIndex(blur_indexes+x,ClampToQuantum(qixel.index));
2169 for (i=0; i < (ssize_t) width; i++)
2171 (void) GetOneCacheViewVirtualPixel(image_view,x+offset[i].x,y+
2172 offset[i].y,&pixel,exception);
2173 alpha=(MagickRealType) (QuantumScale*(
double)
2174 GetPixelAlpha(&pixel));
2175 qixel.red+=(*k)*alpha*(double) pixel.red;
2176 qixel.green+=(*k)*alpha*(double) pixel.green;
2177 qixel.blue+=(*k)*alpha*(double) pixel.blue;
2178 qixel.opacity+=(*k)*(double) pixel.opacity;
2179 if (image->colorspace == CMYKColorspace)
2181 indexes=GetCacheViewVirtualIndexQueue(image_view);
2182 qixel.index+=(*k)*alpha*(double) GetPixelIndex(indexes);
2187 gamma=PerceptibleReciprocal(gamma);
2188 if ((channel & RedChannel) != 0)
2189 SetPixelRed(q,ClampToQuantum(gamma*qixel.red));
2190 if ((channel & GreenChannel) != 0)
2191 SetPixelGreen(q,ClampToQuantum(gamma*qixel.green));
2192 if ((channel & BlueChannel) != 0)
2193 SetPixelBlue(q,ClampToQuantum(gamma*qixel.blue));
2194 if ((channel & OpacityChannel) != 0)
2195 SetPixelOpacity(q,ClampToQuantum(qixel.opacity));
2196 if (((channel & IndexChannel) != 0) &&
2197 (image->colorspace == CMYKColorspace))
2198 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*qixel.index));
2202 if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
2204 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2209#if defined(MAGICKCORE_OPENMP_SUPPORT)
2213 proceed=SetImageProgress(image,BlurImageTag,progress,image->rows);
2214 if (proceed == MagickFalse)
2218 blur_view=DestroyCacheView(blur_view);
2219 image_view=DestroyCacheView(image_view);
2220 kernel=(
double *) RelinquishAlignedMemory(kernel);
2221 offset=(
OffsetInfo *) RelinquishMagickMemory(offset);
2222 if (status == MagickFalse)
2223 blur_image=DestroyImage(blur_image);
2261MagickExport
Image *KuwaharaImage(
const Image *image,
const double radius,
2267 kuwahara_image=KuwaharaImageChannel(image,DefaultChannels,radius,sigma,
2269 return(kuwahara_image);
2272MagickExport
Image *KuwaharaImageChannel(
const Image *image,
2273 const ChannelType channel,
const double radius,
const double sigma,
2276#define KuwaharaImageTag "Kiwahara/Image"
2301 assert(image != (
Image *) NULL);
2302 assert(image->signature == MagickCoreSignature);
2304 assert(exception->signature == MagickCoreSignature);
2305 if (IsEventLogging() != MagickFalse)
2306 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2308 width=(size_t) radius+1;
2309 gaussian_image=BlurImage(image,radius,sigma,exception);
2310 if (gaussian_image == (
Image *) NULL)
2311 return((
Image *) NULL);
2312 kuwahara_image=CloneImage(image,0,0,MagickTrue,exception);
2313 if (kuwahara_image == (
Image *) NULL)
2315 gaussian_image=DestroyImage(gaussian_image);
2316 return((
Image *) NULL);
2318 if (SetImageStorageClass(kuwahara_image,DirectClass) == MagickFalse)
2320 InheritException(exception,&kuwahara_image->exception);
2321 gaussian_image=DestroyImage(gaussian_image);
2322 kuwahara_image=DestroyImage(kuwahara_image);
2323 return((
Image *) NULL);
2330 image_view=AcquireVirtualCacheView(gaussian_image,exception);
2331 kuwahara_view=AcquireAuthenticCacheView(kuwahara_image,exception);
2332#if defined(MAGICKCORE_OPENMP_SUPPORT)
2333 #pragma omp parallel for schedule(static) shared(progress,status) \
2334 magick_number_threads(image,kuwahara_image,kuwahara_image->rows,1)
2336 for (y=0; y < (ssize_t) kuwahara_image->rows; y++)
2339 *magick_restrict kuwahara_indexes;
2347 if (status == MagickFalse)
2349 q=QueueCacheViewAuthenticPixels(kuwahara_view,0,y,kuwahara_image->columns,1,
2356 kuwahara_indexes=GetCacheViewAuthenticIndexQueue(kuwahara_view);
2357 for (x=0; x < (ssize_t) kuwahara_image->columns; x++)
2372 min_variance=MagickMaximumValue;
2373 SetGeometry(gaussian_image,&target);
2374 quadrant.width=width;
2375 quadrant.height=width;
2376 for (i=0; i < 4; i++)
2399 quadrant.x=x-(ssize_t) (width-1);
2400 quadrant.y=y-(ssize_t) (width-1);
2405 quadrant.y=y-(ssize_t) (width-1);
2410 quadrant.x=x-(ssize_t) (width-1);
2416 p=GetCacheViewVirtualPixels(image_view,quadrant.x,quadrant.y,
2417 quadrant.width,quadrant.height,exception);
2420 GetMagickPixelPacket(image,&mean);
2422 for (n=0; n < (ssize_t) (width*width); n++)
2424 mean.red+=(double) k->red;
2425 mean.green+=(double) k->green;
2426 mean.blue+=(double) k->blue;
2429 mean.red/=(double) (width*width);
2430 mean.green/=(double) (width*width);
2431 mean.blue/=(double) (width*width);
2434 for (n=0; n < (ssize_t) (width*width); n++)
2439 luma=GetPixelLuma(image,k);
2440 variance+=(luma-MagickPixelLuma(&mean))*(luma-MagickPixelLuma(&mean));
2443 if (variance < min_variance)
2445 min_variance=variance;
2454 status=InterpolateMagickPixelPacket(gaussian_image,image_view,
2455 UndefinedInterpolatePixel,(
double) target.x+target.width/2.0,
2456 (
double) target.y+target.height/2.0,&pixel,exception);
2457 if (status == MagickFalse)
2459 SetPixelPacket(kuwahara_image,&pixel,q,kuwahara_indexes+x);
2462 if (SyncCacheViewAuthenticPixels(kuwahara_view,exception) == MagickFalse)
2464 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2469#if defined(MAGICKCORE_OPENMP_SUPPORT)
2473 proceed=SetImageProgress(image,KuwaharaImageTag,progress,image->rows);
2474 if (proceed == MagickFalse)
2478 kuwahara_view=DestroyCacheView(kuwahara_view);
2479 image_view=DestroyCacheView(image_view);
2480 gaussian_image=DestroyImage(gaussian_image);
2481 if (status == MagickFalse)
2482 kuwahara_image=DestroyImage(kuwahara_image);
2483 return(kuwahara_image);
2519MagickExport
Image *LocalContrastImage(
const Image *image,
const double radius,
2522#define LocalContrastImageTag "LocalContrast/Image"
2550 assert(image != (
const Image *) NULL);
2551 assert(image->signature == MagickCoreSignature);
2553 assert(exception->signature == MagickCoreSignature);
2554 if (IsEventLogging() != MagickFalse)
2555 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2556#if defined(MAGICKCORE_OPENCL_SUPPORT)
2557 contrast_image=AccelerateLocalContrastImage(image,radius,strength,exception);
2558 if (contrast_image != (
Image *) NULL)
2559 return(contrast_image);
2561 contrast_image=CloneImage(image,0,0,MagickTrue,exception);
2562 if (contrast_image == (
Image *) NULL)
2563 return((
Image *) NULL);
2564 if (SetImageStorageClass(contrast_image,DirectClass) == MagickFalse)
2566 InheritException(exception,&contrast_image->exception);
2567 contrast_image=DestroyImage(contrast_image);
2568 return((
Image *) NULL);
2570 image_view=AcquireVirtualCacheView(image,exception);
2571 contrast_view=AcquireAuthenticCacheView(contrast_image,exception);
2572 scanLineSize=(ssize_t) MagickMax(image->columns,image->rows);
2573 width=(ssize_t) scanLineSize*0.002*fabs(radius);
2574 scanLineSize+=(2*width);
2575 scanline_info=AcquireVirtualMemory(GetOpenMPMaximumThreads()*
2576 scanLineSize,
sizeof(*scanline));
2579 contrast_view=DestroyCacheView(contrast_view);
2580 image_view=DestroyCacheView(image_view);
2581 contrast_image=DestroyImage(contrast_image);
2582 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2584 scanline=(
float *) GetVirtualMemoryBlob(scanline_info);
2588 interImage_info=AcquireVirtualMemory(image->rows*(image->columns+(2*width)),
2589 sizeof(*interImage));
2592 scanline_info=RelinquishVirtualMemory(scanline_info);
2593 contrast_view=DestroyCacheView(contrast_view);
2594 image_view=DestroyCacheView(image_view);
2595 contrast_image=DestroyImage(contrast_image);
2596 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2598 interImage=(
float *) GetVirtualMemoryBlob(interImage_info);
2599 totalWeight=(width+1)*(width+1);
2608#if defined(MAGICKCORE_OPENMP_SUPPORT)
2609 #pragma omp parallel for schedule(static) \
2610 magick_number_threads(image,image,image->columns,1)
2612 for (x=0; x < (ssize_t) image->columns; x++)
2615 id = GetOpenMPThreadId();
2631 if (status == MagickFalse)
2634 pixels+=
id*scanLineSize;
2636 p=GetCacheViewVirtualPixels(image_view,x,-width,1,image->rows+(2*width),
2643 for (y=0; y < (ssize_t) image->rows+(2*width); y++)
2645 *pix++=(float)GetPixelLuma(image,p);
2648 out=interImage+x+width;
2649 for (y=0; y < (ssize_t) image->rows; y++)
2658 for (i=0; i < width; i++)
2660 sum+=weight*(*pix++);
2663 for (i=width+1; i < (2*width); i++)
2665 sum+=weight*(*pix++);
2669 *out=sum/totalWeight;
2671 if (x <= width && x != 0)
2673 if ((x > (ssize_t) image->columns-width-2) &&
2674 (x != (ssize_t) image->columns-1))
2675 *(out+((image->columns-x-1)*2))=*out;
2676 out+=image->columns+(width*2);
2687#if defined(MAGICKCORE_OPENMP_SUPPORT)
2688#pragma omp parallel for schedule(static) \
2689 magick_number_threads(image,image,image->rows,1)
2691 for (y=0; y < (ssize_t) image->rows; y++)
2694 id = GetOpenMPThreadId();
2712 if (status == MagickFalse)
2715 pixels+=
id*scanLineSize;
2716 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,
2718 q=GetCacheViewAuthenticPixels(contrast_view,0,y,image->columns,1,
2725 memcpy(pixels,interImage+(y*(image->columns+(2*width))),(image->columns+
2726 (2*width))*
sizeof(
float));
2727 for (x=0; x < (ssize_t) image->columns; x++)
2738 for (i=0; i < width; i++)
2740 sum+=weight*(*pix++);
2743 for (i=width+1; i < (2*width); i++)
2745 sum+=weight*(*pix++);
2749 srcVal=(float) GetPixelLuma(image,p);
2750 mult=(srcVal-(sum/totalWeight))*(
float) (0.01*strength);
2751 mult=(srcVal+mult)/srcVal;
2752 SetPixelRed(q,ClampToQuantum((MagickRealType) GetPixelRed(p)*
2753 (MagickRealType) mult));
2754 SetPixelGreen(q,ClampToQuantum((MagickRealType) GetPixelGreen(p)*
2755 (MagickRealType) mult));
2756 SetPixelBlue(q,ClampToQuantum((MagickRealType) GetPixelBlue(p)*
2757 (MagickRealType) mult));
2761 if (SyncCacheViewAuthenticPixels(contrast_view,exception) == MagickFalse)
2765 scanline_info=RelinquishVirtualMemory(scanline_info);
2766 interImage_info=RelinquishVirtualMemory(interImage_info);
2767 contrast_view=DestroyCacheView(contrast_view);
2768 image_view=DestroyCacheView(image_view);
2769 if (status == MagickFalse)
2770 contrast_image=DestroyImage(contrast_image);
2771 return(contrast_image);
2804MagickExport
Image *PreviewImage(
const Image *image,
const PreviewType preview,
2807#define NumberTiles 9
2808#define PreviewImageTag "Preview/Image"
2809#define DefaultPreviewGeometry "204x204+10+10"
2812 factor[MaxTextExtent],
2813 label[MaxTextExtent];
2855 assert(image != (
Image *) NULL);
2856 assert(image->signature == MagickCoreSignature);
2857 if (IsEventLogging() != MagickFalse)
2858 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2862 preview_info=AcquireImageInfo();
2863 SetGeometry(image,&geometry);
2864 (void) ParseMetaGeometry(DefaultPreviewGeometry,&geometry.x,&geometry.y,
2865 &geometry.width,&geometry.height);
2866 images=NewImageList();
2868 GetQuantizeInfo(&quantize_info);
2874 for (i=0; i < NumberTiles; i++)
2876 thumbnail=ThumbnailImage(image,geometry.width,geometry.height,exception);
2877 if (thumbnail == (
Image *) NULL)
2879 (void) SetImageProgressMonitor(thumbnail,(MagickProgressMonitor) NULL,
2881 (void) SetImageProperty(thumbnail,
"label",DefaultTileLabel);
2882 if (i == (NumberTiles/2))
2884 (void) QueryColorDatabase(
"#dfdfdf",&thumbnail->matte_color,exception);
2885 AppendImageToList(&images,thumbnail);
2893 preview_image=RotateImage(thumbnail,degrees,exception);
2894 (void) FormatLocaleString(label,MaxTextExtent,
"rotate %g",degrees);
2900 preview_image=ShearImage(thumbnail,degrees,degrees,exception);
2901 (void) FormatLocaleString(label,MaxTextExtent,
"shear %gx%g",
2902 degrees,2.0*degrees);
2907 x=(ssize_t) ((i+1)*thumbnail->columns)/NumberTiles;
2908 y=(ssize_t) ((i+1)*thumbnail->rows)/NumberTiles;
2909 preview_image=RollImage(thumbnail,x,y,exception);
2910 (void) FormatLocaleString(label,MaxTextExtent,
"roll %+.20gx%+.20g",
2911 (
double) x,(
double) y);
2916 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2917 if (preview_image == (
Image *) NULL)
2919 (void) FormatLocaleString(factor,MaxTextExtent,
"100,100,%g",
2921 (void) ModulateImage(preview_image,factor);
2922 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2925 case SaturationPreview:
2927 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2928 if (preview_image == (
Image *) NULL)
2930 (void) FormatLocaleString(factor,MaxTextExtent,
"100,%g",2.0*percentage);
2931 (void) ModulateImage(preview_image,factor);
2932 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2935 case BrightnessPreview:
2937 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2938 if (preview_image == (
Image *) NULL)
2940 (void) FormatLocaleString(factor,MaxTextExtent,
"%g",2.0*percentage);
2941 (void) ModulateImage(preview_image,factor);
2942 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2948 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2949 if (preview_image == (
Image *) NULL)
2952 (void) GammaImageChannel(preview_image,DefaultChannels,gamma);
2953 (void) FormatLocaleString(label,MaxTextExtent,
"gamma %g",gamma);
2958 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2959 if (preview_image != (
Image *) NULL)
2960 for (x=0; x < i; x++)
2961 (
void) ContrastImage(preview_image,MagickTrue);
2962 (void) FormatLocaleString(label,MaxTextExtent,
"contrast (%.20g)",
2968 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2969 if (preview_image == (
Image *) NULL)
2971 for (x=0; x < i; x++)
2972 (
void) ContrastImage(preview_image,MagickFalse);
2973 (void) FormatLocaleString(label,MaxTextExtent,
"+contrast (%.20g)",
2977 case GrayscalePreview:
2979 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2980 if (preview_image == (
Image *) NULL)
2983 quantize_info.number_colors=colors;
2984 quantize_info.colorspace=GRAYColorspace;
2985 (void) QuantizeImage(&quantize_info,preview_image);
2986 (void) FormatLocaleString(label,MaxTextExtent,
2987 "-colorspace gray -colors %.20g",(
double) colors);
2990 case QuantizePreview:
2992 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2993 if (preview_image == (
Image *) NULL)
2996 quantize_info.number_colors=colors;
2997 (void) QuantizeImage(&quantize_info,preview_image);
2998 (void) FormatLocaleString(label,MaxTextExtent,
"colors %.20g",(
double)
3002 case DespecklePreview:
3004 for (x=0; x < (i-1); x++)
3006 preview_image=DespeckleImage(thumbnail,exception);
3007 if (preview_image == (
Image *) NULL)
3009 thumbnail=DestroyImage(thumbnail);
3010 thumbnail=preview_image;
3012 preview_image=DespeckleImage(thumbnail,exception);
3013 if (preview_image == (
Image *) NULL)
3015 (void) FormatLocaleString(label,MaxTextExtent,
"despeckle (%.20g)",
3019 case ReduceNoisePreview:
3021 preview_image=StatisticImage(thumbnail,NonpeakStatistic,(
size_t) radius,
3022 (
size_t) radius,exception);
3023 (void) FormatLocaleString(label,MaxTextExtent,
"noise %g",radius);
3026 case AddNoisePreview:
3032 (void) CopyMagickString(factor,
"uniform",MaxTextExtent);
3037 (void) CopyMagickString(factor,
"gaussian",MaxTextExtent);
3042 (void) CopyMagickString(factor,
"multiplicative",MaxTextExtent);
3047 (void) CopyMagickString(factor,
"impulse",MaxTextExtent);
3052 (void) CopyMagickString(factor,
"laplacian",MaxTextExtent);
3057 (void) CopyMagickString(factor,
"poisson",MaxTextExtent);
3062 (void) CopyMagickString(thumbnail->magick,
"NULL",MaxTextExtent);
3066 preview_image=StatisticImage(thumbnail,NonpeakStatistic,(
size_t) i,
3067 (
size_t) i,exception);
3068 (void) FormatLocaleString(label,MaxTextExtent,
"+noise %s",factor);
3071 case SharpenPreview:
3073 preview_image=SharpenImage(thumbnail,radius,sigma,exception);
3074 (void) FormatLocaleString(label,MaxTextExtent,
"sharpen %gx%g",
3080 preview_image=BlurImage(thumbnail,radius,sigma,exception);
3081 (void) FormatLocaleString(label,MaxTextExtent,
"blur %gx%g",radius,
3085 case ThresholdPreview:
3087 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3088 if (preview_image == (
Image *) NULL)
3090 (void) BilevelImage(thumbnail,
3091 (
double) (percentage*((MagickRealType) QuantumRange+1.0))/100.0);
3092 (void) FormatLocaleString(label,MaxTextExtent,
"threshold %g",
3093 (
double) (percentage*((MagickRealType) QuantumRange+1.0))/100.0);
3096 case EdgeDetectPreview:
3098 preview_image=EdgeImage(thumbnail,radius,exception);
3099 (void) FormatLocaleString(label,MaxTextExtent,
"edge %g",radius);
3104 preview_image=SpreadImage(thumbnail,radius,exception);
3105 (void) FormatLocaleString(label,MaxTextExtent,
"spread %g",
3109 case SolarizePreview:
3111 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3112 if (preview_image == (
Image *) NULL)
3114 (void) SolarizeImage(preview_image,(
double) QuantumRange*
3116 (void) FormatLocaleString(label,MaxTextExtent,
"solarize %g",
3117 ((
double) QuantumRange*percentage)/100.0);
3123 preview_image=ShadeImage(thumbnail,MagickTrue,degrees,degrees,
3125 (void) FormatLocaleString(label,MaxTextExtent,
"shade %gx%g",
3134 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3135 if (preview_image == (
Image *) NULL)
3137 raise.width=(size_t) (2*i+2);
3138 raise.height=(size_t) (2*i+2);
3141 (void) RaiseImage(preview_image,&raise,MagickTrue);
3142 (void) FormatLocaleString(label,MaxTextExtent,
3143 "raise %.20gx%.20g%+.20g%+.20g",(
double) raise.width,(
double)
3144 raise.height,(
double) raise.x,(
double) raise.y);
3147 case SegmentPreview:
3149 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3150 if (preview_image == (
Image *) NULL)
3153 (void) SegmentImage(preview_image,sRGBColorspace,MagickFalse,threshold,
3155 (void) FormatLocaleString(label,MaxTextExtent,
"segment %gx%g",
3156 threshold,threshold);
3161 preview_image=SwirlImage(thumbnail,degrees,exception);
3162 (void) FormatLocaleString(label,MaxTextExtent,
"swirl %g",degrees);
3166 case ImplodePreview:
3169 preview_image=ImplodeImage(thumbnail,degrees,exception);
3170 (void) FormatLocaleString(label,MaxTextExtent,
"implode %g",degrees);
3176 preview_image=WaveImage(thumbnail,0.5*degrees,2.0*degrees,exception);
3177 (void) FormatLocaleString(label,MaxTextExtent,
"wave %gx%g",
3178 0.5*degrees,2.0*degrees);
3181 case OilPaintPreview:
3183 preview_image=OilPaintImage(thumbnail,(
double) radius,exception);
3184 (void) FormatLocaleString(label,MaxTextExtent,
"paint %g",radius);
3187 case CharcoalDrawingPreview:
3189 preview_image=CharcoalImage(thumbnail,(
double) radius,(
double) sigma,
3191 (void) FormatLocaleString(label,MaxTextExtent,
"charcoal %gx%g",
3198 filename[MaxTextExtent];
3206 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3207 if (preview_image == (
Image *) NULL)
3209 preview_info->quality=(size_t) percentage;
3210 (void) FormatLocaleString(factor,MaxTextExtent,
"%.20g",(
double)
3211 preview_info->quality);
3212 file=AcquireUniqueFileResource(filename);
3215 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,
3216 "jpeg:%s",filename);
3217 status=WriteImage(preview_info,preview_image);
3218 if (status != MagickFalse)
3223 (void) CopyMagickString(preview_info->filename,
3224 preview_image->filename,MaxTextExtent);
3225 quality_image=ReadImage(preview_info,exception);
3226 if (quality_image != (
Image *) NULL)
3228 preview_image=DestroyImage(preview_image);
3229 preview_image=quality_image;
3232 (void) RelinquishUniqueFileResource(preview_image->filename);
3233 if ((GetBlobSize(preview_image)/1024) >= 1024)
3234 (void) FormatLocaleString(label,MaxTextExtent,
"quality %s\n%gmb ",
3235 factor,(
double) ((MagickOffsetType) GetBlobSize(preview_image))/
3238 if (GetBlobSize(preview_image) >= 1024)
3239 (void) FormatLocaleString(label,MaxTextExtent,
3240 "quality %s\n%gkb ",factor,(
double) ((MagickOffsetType)
3241 GetBlobSize(preview_image))/1024.0);
3243 (
void) FormatLocaleString(label,MaxTextExtent,
"quality %s\n%.20gb ",
3244 factor,(
double) ((MagickOffsetType) GetBlobSize(thumbnail)));
3248 thumbnail=DestroyImage(thumbnail);
3252 if (preview_image == (
Image *) NULL)
3254 (void) DeleteImageProperty(preview_image,
"label");
3255 (void) SetImageProperty(preview_image,
"label",label);
3256 AppendImageToList(&images,preview_image);
3257 proceed=SetImageProgress(image,PreviewImageTag,(MagickOffsetType) i,
3259 if (proceed == MagickFalse)
3262 if (images == (
Image *) NULL)
3264 preview_info=DestroyImageInfo(preview_info);
3265 return((
Image *) NULL);
3270 montage_info=CloneMontageInfo(preview_info,(
MontageInfo *) NULL);
3271 (void) CopyMagickString(montage_info->filename,image->filename,MaxTextExtent);
3272 montage_info->shadow=MagickTrue;
3273 (void) CloneString(&montage_info->tile,
"3x3");
3274 (void) CloneString(&montage_info->geometry,DefaultPreviewGeometry);
3275 (void) CloneString(&montage_info->frame,DefaultTileFrame);
3276 montage_image=MontageImages(images,montage_info,exception);
3277 montage_info=DestroyMontageInfo(montage_info);
3278 images=DestroyImageList(images);
3279 if (montage_image == (
Image *) NULL)
3280 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3281 if (montage_image->montage != (
char *) NULL)
3286 montage_image->montage=(
char *) RelinquishMagickMemory(
3287 montage_image->montage);
3288 if (image->directory != (
char *) NULL)
3289 montage_image->directory=(
char *) RelinquishMagickMemory(
3290 montage_image->directory);
3292 preview_info=DestroyImageInfo(preview_info);
3293 return(montage_image);
3330MagickExport
Image *RotationalBlurImage(
const Image *image,
const double angle,
3336 blur_image=RotationalBlurImageChannel(image,DefaultChannels,angle,exception);
3340MagickExport
Image *RotationalBlurImageChannel(
const Image *image,
3341 const ChannelType channel,
const double angle,
ExceptionInfo *exception)
3381 assert(image != (
Image *) NULL);
3382 assert(image->signature == MagickCoreSignature);
3384 assert(exception->signature == MagickCoreSignature);
3385 if (IsEventLogging() != MagickFalse)
3386 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3387#if defined(MAGICKCORE_OPENCL_SUPPORT)
3388 blur_image=AccelerateRadialBlurImage(image,channel,angle,exception);
3389 if (blur_image != (
Image *) NULL)
3392 blur_image=CloneImage(image,0,0,MagickTrue,exception);
3393 if (blur_image == (
Image *) NULL)
3394 return((
Image *) NULL);
3395 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
3397 InheritException(exception,&blur_image->exception);
3398 blur_image=DestroyImage(blur_image);
3399 return((
Image *) NULL);
3401 blur_center.x=(double) (image->columns-1)/2.0;
3402 blur_center.y=(double) (image->rows-1)/2.0;
3403 blur_radius=hypot(blur_center.x,blur_center.y);
3404 n=(size_t) fabs(4.0*DegreesToRadians(angle)*sqrt((
double) blur_radius)+2UL);
3405 theta=DegreesToRadians(angle)/(MagickRealType) (n-1);
3406 cos_theta=(MagickRealType *) AcquireQuantumMemory((
size_t) n,
3407 sizeof(*cos_theta));
3408 sin_theta=(MagickRealType *) AcquireQuantumMemory((
size_t) n,
3409 sizeof(*sin_theta));
3410 if ((cos_theta == (MagickRealType *) NULL) ||
3411 (sin_theta == (MagickRealType *) NULL))
3413 if (cos_theta != (MagickRealType *) NULL)
3414 cos_theta=(MagickRealType *) RelinquishMagickMemory(cos_theta);
3415 if (sin_theta != (MagickRealType *) NULL)
3416 sin_theta=(MagickRealType *) RelinquishMagickMemory(sin_theta);
3417 blur_image=DestroyImage(blur_image);
3418 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3420 offset=theta*(MagickRealType) (n-1)/2.0;
3421 for (i=0; i < (ssize_t) n; i++)
3423 cos_theta[i]=cos((
double) (theta*i-offset));
3424 sin_theta[i]=sin((
double) (theta*i-offset));
3431 GetMagickPixelPacket(image,&bias);
3432 image_view=AcquireVirtualCacheView(image,exception);
3433 blur_view=AcquireAuthenticCacheView(blur_image,exception);
3434#if defined(MAGICKCORE_OPENMP_SUPPORT)
3435 #pragma omp parallel for schedule(static) shared(progress,status) \
3436 magick_number_threads(image,blur_image,blur_image->rows,1)
3438 for (y=0; y < (ssize_t) blur_image->rows; y++)
3441 *magick_restrict indexes;
3444 *magick_restrict blur_indexes;
3452 if (status == MagickFalse)
3454 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
3461 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
3462 for (x=0; x < (ssize_t) blur_image->columns; x++)
3483 center.x=(double) x-blur_center.x;
3484 center.y=(double) y-blur_center.y;
3485 radius=hypot((
double) center.x,center.y);
3490 step=(size_t) (blur_radius/radius);
3499 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
3501 for (i=0; i < (ssize_t) n; i+=(ssize_t) step)
3503 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t)
3504 (blur_center.x+center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),
3505 (ssize_t) (blur_center.y+center.x*sin_theta[i]+center.y*
3506 cos_theta[i]+0.5),&pixel,exception);
3507 qixel.red+=(MagickRealType) pixel.red;
3508 qixel.green+=(MagickRealType) pixel.green;
3509 qixel.blue+=(MagickRealType) pixel.blue;
3510 qixel.opacity+=(MagickRealType) pixel.opacity;
3511 if (image->colorspace == CMYKColorspace)
3513 indexes=GetCacheViewVirtualIndexQueue(image_view);
3514 qixel.index+=(MagickRealType) (*indexes);
3518 normalize=PerceptibleReciprocal(normalize);
3519 if ((channel & RedChannel) != 0)
3520 SetPixelRed(q,ClampToQuantum(normalize*qixel.red));
3521 if ((channel & GreenChannel) != 0)
3522 SetPixelGreen(q,ClampToQuantum(normalize*qixel.green));
3523 if ((channel & BlueChannel) != 0)
3524 SetPixelBlue(q,ClampToQuantum(normalize*qixel.blue));
3525 if ((channel & OpacityChannel) != 0)
3526 SetPixelOpacity(q,ClampToQuantum(normalize*qixel.opacity));
3527 if (((channel & IndexChannel) != 0) &&
3528 (image->colorspace == CMYKColorspace))
3529 SetPixelIndex(blur_indexes+x,ClampToQuantum(normalize*qixel.index));
3539 for (i=0; i < (ssize_t) n; i+=(ssize_t) step)
3541 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t)
3542 (blur_center.x+center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),
3543 (ssize_t) (blur_center.y+center.x*sin_theta[i]+center.y*
3544 cos_theta[i]+0.5),&pixel,exception);
3545 alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(&pixel));
3546 qixel.red+=alpha*(MagickRealType) pixel.red;
3547 qixel.green+=alpha*(MagickRealType) pixel.green;
3548 qixel.blue+=alpha*(MagickRealType) pixel.blue;
3549 qixel.opacity+=(MagickRealType) pixel.opacity;
3550 if (image->colorspace == CMYKColorspace)
3552 indexes=GetCacheViewVirtualIndexQueue(image_view);
3553 qixel.index+=alpha*(MagickRealType) (*indexes);
3558 gamma=PerceptibleReciprocal(gamma);
3559 normalize=PerceptibleReciprocal(normalize);
3560 if ((channel & RedChannel) != 0)
3561 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) qixel.red));
3562 if ((channel & GreenChannel) != 0)
3563 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType) qixel.green));
3564 if ((channel & BlueChannel) != 0)
3565 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType) qixel.blue));
3566 if ((channel & OpacityChannel) != 0)
3567 SetPixelOpacity(q,ClampToQuantum(normalize*(MagickRealType)
3569 if (((channel & IndexChannel) != 0) &&
3570 (image->colorspace == CMYKColorspace))
3571 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*(MagickRealType)
3576 if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
3578 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3583#if defined(MAGICKCORE_OPENMP_SUPPORT)
3587 proceed=SetImageProgress(image,BlurImageTag,progress,image->rows);
3588 if (proceed == MagickFalse)
3592 blur_view=DestroyCacheView(blur_view);
3593 image_view=DestroyCacheView(image_view);
3594 cos_theta=(MagickRealType *) RelinquishMagickMemory(cos_theta);
3595 sin_theta=(MagickRealType *) RelinquishMagickMemory(sin_theta);
3596 if (status == MagickFalse)
3597 blur_image=DestroyImage(blur_image);
3642MagickExport
Image *SelectiveBlurImage(
const Image *image,
const double radius,
3643 const double sigma,
const double threshold,
ExceptionInfo *exception)
3648 blur_image=SelectiveBlurImageChannel(image,DefaultChannels,radius,sigma,
3649 threshold,exception);
3653MagickExport
Image *SelectiveBlurImageChannel(
const Image *image,
3654 const ChannelType channel,
const double radius,
const double sigma,
3657#define SelectiveBlurImageTag "SelectiveBlur/Image"
3696 assert(image != (
Image *) NULL);
3697 assert(image->signature == MagickCoreSignature);
3699 assert(exception->signature == MagickCoreSignature);
3700 if (IsEventLogging() != MagickFalse)
3701 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3702 width=GetOptimalKernelWidth1D(radius,sigma);
3703 kernel=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
3704 width*
sizeof(*kernel)));
3705 if (kernel == (
double *) NULL)
3706 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3707 j=(ssize_t) (width-1)/2;
3709 for (v=(-j); v <= j; v++)
3711 for (u=(-j); u <= j; u++)
3712 kernel[i++]=(
double) (exp(-((
double) u*u+v*v)/(2.0*MagickSigma*
3713 MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
3715 if (image->debug != MagickFalse)
3718 format[MaxTextExtent],
3728 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
3729 " SelectiveBlurImage with %.20gx%.20g kernel:",(
double) width,(
double)
3731 message=AcquireString(
"");
3733 for (v=0; v < (ssize_t) width; v++)
3736 (void) FormatLocaleString(format,MaxTextExtent,
"%.20g: ",(
double) v);
3737 (void) ConcatenateString(&message,format);
3738 for (u=0; u < (ssize_t) width; u++)
3740 (void) FormatLocaleString(format,MaxTextExtent,
"%+f ",*k++);
3741 (void) ConcatenateString(&message,format);
3743 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"%s",message);
3745 message=DestroyString(message);
3747 blur_image=CloneImage(image,0,0,MagickTrue,exception);
3748 if (blur_image == (
Image *) NULL)
3750 kernel=(
double *) RelinquishAlignedMemory(kernel);
3751 return((
Image *) NULL);
3753 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
3755 kernel=(
double *) RelinquishAlignedMemory(kernel);
3756 InheritException(exception,&blur_image->exception);
3757 blur_image=DestroyImage(blur_image);
3758 return((
Image *) NULL);
3760 luminance_image=CloneImage(image,0,0,MagickTrue,exception);
3761 if (luminance_image == (
Image *) NULL)
3763 kernel=(
double *) RelinquishAlignedMemory(kernel);
3764 blur_image=DestroyImage(blur_image);
3765 return((
Image *) NULL);
3767 status=TransformImageColorspace(luminance_image,GRAYColorspace);
3768 if (status == MagickFalse)
3770 InheritException(exception,&luminance_image->exception);
3771 kernel=(
double *) RelinquishAlignedMemory(kernel);
3772 blur_image=DestroyImage(blur_image);
3773 luminance_image=DestroyImage(luminance_image);
3774 return((
Image *) NULL);
3781 center=(ssize_t) ((image->columns+width)*((width-1)/2L)+((width-1)/2L));
3782 GetMagickPixelPacket(image,&bias);
3783 SetMagickPixelPacketBias(image,&bias);
3784 image_view=AcquireVirtualCacheView(image,exception);
3785 luminance_view=AcquireVirtualCacheView(luminance_image,exception);
3786 blur_view=AcquireAuthenticCacheView(blur_image,exception);
3787#if defined(MAGICKCORE_OPENMP_SUPPORT)
3788 #pragma omp parallel for schedule(static) shared(progress,status) \
3789 magick_number_threads(image,blur_image,image->rows,1)
3791 for (y=0; y < (ssize_t) image->rows; y++)
3800 *magick_restrict indexes;
3807 *magick_restrict blur_indexes;
3815 if (status == MagickFalse)
3817 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) (width-1)/2L),y-(ssize_t)
3818 ((width-1)/2L),image->columns+width,width,exception);
3819 l=GetCacheViewVirtualPixels(luminance_view,-((ssize_t) (width-1)/2L),y-
3820 (ssize_t) ((width-1)/2L),luminance_image->columns+width,width,exception);
3821 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
3829 indexes=GetCacheViewVirtualIndexQueue(image_view);
3830 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
3831 for (x=0; x < (ssize_t) image->columns; x++)
3853 pixel.green=bias.green;
3854 pixel.blue=bias.blue;
3855 pixel.opacity=bias.opacity;
3856 pixel.index=bias.index;
3858 intensity=GetPixelIntensity(image,p+center);
3861 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
3863 for (v=0; v < (ssize_t) width; v++)
3865 for (u=0; u < (ssize_t) width; u++)
3867 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3868 if (fabs(contrast) < threshold)
3870 pixel.red+=(*k)*(MagickRealType) GetPixelRed(p+u+j);
3871 pixel.green+=(*k)*(MagickRealType) GetPixelGreen(p+u+j);
3872 pixel.blue+=(*k)*(MagickRealType) GetPixelBlue(p+u+j);
3877 j+=(ssize_t) (image->columns+width);
3881 gamma=PerceptibleReciprocal(gamma);
3882 if ((channel & RedChannel) != 0)
3883 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType)
3885 if ((channel & GreenChannel) != 0)
3886 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType)
3888 if ((channel & BlueChannel) != 0)
3889 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType)
3892 if ((channel & OpacityChannel) != 0)
3896 for (v=0; v < (ssize_t) width; v++)
3898 for (u=0; u < (ssize_t) width; u++)
3900 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3901 if (fabs(contrast) < threshold)
3903 pixel.opacity+=(*k)*(MagickRealType) (p+u+j)->opacity;
3908 j+=(ssize_t) (image->columns+width);
3910 gamma=PerceptibleReciprocal(gamma);
3911 SetPixelOpacity(q,ClampToQuantum(gamma*pixel.opacity));
3913 if (((channel & IndexChannel) != 0) &&
3914 (image->colorspace == CMYKColorspace))
3918 for (v=0; v < (ssize_t) width; v++)
3920 for (u=0; u < (ssize_t) width; u++)
3922 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3923 if (fabs(contrast) < threshold)
3925 pixel.index+=(*k)*(MagickRealType)
3926 GetPixelIndex(indexes+x+u+j);
3931 j+=(ssize_t) (image->columns+width);
3933 gamma=PerceptibleReciprocal(gamma);
3934 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*pixel.index));
3942 for (v=0; v < (ssize_t) width; v++)
3944 for (u=0; u < (ssize_t) width; u++)
3946 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3947 if (fabs(contrast) < threshold)
3949 alpha=(MagickRealType) (QuantumScale*(MagickRealType)
3950 GetPixelAlpha(p+u+j));
3951 pixel.red+=(*k)*alpha*(MagickRealType) GetPixelRed(p+u+j);
3952 pixel.green+=(*k)*alpha*(MagickRealType) GetPixelGreen(p+u+j);
3953 pixel.blue+=(*k)*alpha*(MagickRealType) GetPixelBlue(p+u+j);
3954 pixel.opacity+=(*k)*(MagickRealType) GetPixelOpacity(p+u+j);
3959 j+=(ssize_t) (image->columns+width);
3963 gamma=PerceptibleReciprocal(gamma);
3964 if ((channel & RedChannel) != 0)
3965 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) pixel.red));
3966 if ((channel & GreenChannel) != 0)
3967 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType)
3969 if ((channel & BlueChannel) != 0)
3970 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType)
3973 if ((channel & OpacityChannel) != 0)
3976 for (v=0; v < (ssize_t) width; v++)
3978 for (u=0; u < (ssize_t) width; u++)
3980 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3981 if (fabs(contrast) < threshold)
3982 pixel.opacity+=(*k)*(MagickRealType) GetPixelOpacity(p+u+j);
3985 j+=(ssize_t) (image->columns+width);
3987 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
3989 if (((channel & IndexChannel) != 0) &&
3990 (image->colorspace == CMYKColorspace))
3994 for (v=0; v < (ssize_t) width; v++)
3996 for (u=0; u < (ssize_t) width; u++)
3998 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3999 if (fabs(contrast) < threshold)
4001 alpha=(MagickRealType) (QuantumScale*(MagickRealType)
4002 GetPixelAlpha(p+u+j));
4003 pixel.index+=(*k)*alpha*(MagickRealType)
4004 GetPixelIndex(indexes+x+u+j);
4009 j+=(ssize_t) (image->columns+width);
4011 gamma=PerceptibleReciprocal(gamma);
4012 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*pixel.index));
4019 sync=SyncCacheViewAuthenticPixels(blur_view,exception);
4020 if (sync == MagickFalse)
4022 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4027#if defined(MAGICKCORE_OPENMP_SUPPORT)
4031 proceed=SetImageProgress(image,SelectiveBlurImageTag,progress,
4033 if (proceed == MagickFalse)
4037 blur_image->type=image->type;
4038 blur_view=DestroyCacheView(blur_view);
4039 luminance_view=DestroyCacheView(luminance_view);
4040 image_view=DestroyCacheView(image_view);
4041 luminance_image=DestroyImage(luminance_image);
4042 kernel=(
double *) RelinquishAlignedMemory(kernel);
4043 if (status == MagickFalse)
4044 blur_image=DestroyImage(blur_image);
4080MagickExport
Image *ShadeImage(
const Image *image,
const MagickBooleanType gray,
4081 const double azimuth,
const double elevation,
ExceptionInfo *exception)
4083#define GetShadeIntensity(image,pixel) \
4084 ClampPixel(GetPixelIntensity((image),(pixel)))
4085#define ShadeImageTag "Shade/Image"
4110 assert(image != (
const Image *) NULL);
4111 assert(image->signature == MagickCoreSignature);
4113 assert(exception->signature == MagickCoreSignature);
4114 if (IsEventLogging() != MagickFalse)
4115 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4116 linear_image=CloneImage(image,0,0,MagickTrue,exception);
4117 shade_image=CloneImage(image,0,0,MagickTrue,exception);
4118 if ((linear_image == (
Image *) NULL) || (shade_image == (
Image *) NULL))
4120 if (linear_image != (
Image *) NULL)
4121 linear_image=DestroyImage(linear_image);
4122 if (shade_image != (
Image *) NULL)
4123 shade_image=DestroyImage(shade_image);
4124 return((
Image *) NULL);
4126 if (SetImageStorageClass(shade_image,DirectClass) == MagickFalse)
4128 InheritException(exception,&shade_image->exception);
4129 linear_image=DestroyImage(linear_image);
4130 shade_image=DestroyImage(shade_image);
4131 return((
Image *) NULL);
4136 light.x=(double) QuantumRange*cos(DegreesToRadians(azimuth))*
4137 cos(DegreesToRadians(elevation));
4138 light.y=(double) QuantumRange*sin(DegreesToRadians(azimuth))*
4139 cos(DegreesToRadians(elevation));
4140 light.z=(double) QuantumRange*sin(DegreesToRadians(elevation));
4146 image_view=AcquireVirtualCacheView(linear_image,exception);
4147 shade_view=AcquireAuthenticCacheView(shade_image,exception);
4148#if defined(MAGICKCORE_OPENMP_SUPPORT)
4149 #pragma omp parallel for schedule(static) shared(progress,status) \
4150 magick_number_threads(linear_image,shade_image,linear_image->rows,1)
4152 for (y=0; y < (ssize_t) linear_image->rows; y++)
4164 *magick_restrict s0,
4165 *magick_restrict s1,
4166 *magick_restrict s2;
4174 if (status == MagickFalse)
4176 p=GetCacheViewVirtualPixels(image_view,-1,y-1,linear_image->columns+2,3,
4178 q=QueueCacheViewAuthenticPixels(shade_view,0,y,shade_image->columns,1,
4188 normal.z=2.0*(double) QuantumRange;
4189 for (x=0; x < (ssize_t) linear_image->columns; x++)
4195 s1=s0+image->columns+2;
4196 s2=s1+image->columns+2;
4197 normal.x=(double) (GetShadeIntensity(linear_image,s0-1)+
4198 GetShadeIntensity(linear_image,s1-1)+
4199 GetShadeIntensity(linear_image,s2-1)-
4200 GetShadeIntensity(linear_image,s0+1)-
4201 GetShadeIntensity(linear_image,s1+1)-
4202 GetShadeIntensity(linear_image,s2+1));
4203 normal.y=(double) (GetShadeIntensity(linear_image,s2-1)+
4204 GetShadeIntensity(linear_image,s2)+
4205 GetShadeIntensity(linear_image,s2+1)-
4206 GetShadeIntensity(linear_image,s0-1)-
4207 GetShadeIntensity(linear_image,s0)-
4208 GetShadeIntensity(linear_image,s0+1));
4209 if ((fabs(normal.x) <= MagickEpsilon) &&
4210 (fabs(normal.y) <= MagickEpsilon))
4215 distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
4216 if (distance > MagickEpsilon)
4218 normal_distance=normal.x*normal.x+normal.y*normal.y+normal.z*
4220 if (normal_distance > (MagickEpsilon*MagickEpsilon))
4221 shade=distance/sqrt((
double) normal_distance);
4224 if (gray != MagickFalse)
4226 SetPixelRed(q,shade);
4227 SetPixelGreen(q,shade);
4228 SetPixelBlue(q,shade);
4232 SetPixelRed(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4234 SetPixelGreen(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4235 GetPixelGreen(s1)));
4236 SetPixelBlue(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4239 q->opacity=s1->opacity;
4243 if (SyncCacheViewAuthenticPixels(shade_view,exception) == MagickFalse)
4245 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4250#if defined(MAGICKCORE_OPENMP_SUPPORT)
4254 proceed=SetImageProgress(image,ShadeImageTag,progress,image->rows);
4255 if (proceed == MagickFalse)
4259 shade_view=DestroyCacheView(shade_view);
4260 image_view=DestroyCacheView(image_view);
4261 linear_image=DestroyImage(linear_image);
4262 if (status == MagickFalse)
4263 shade_image=DestroyImage(shade_image);
4264 return(shade_image);
4310MagickExport
Image *SharpenImage(
const Image *image,
const double radius,
4316 sharp_image=SharpenImageChannel(image,DefaultChannels,radius,sigma,exception);
4317 return(sharp_image);
4320MagickExport
Image *SharpenImageChannel(
const Image *image,
4321 const ChannelType channel,
const double radius,
const double sigma,
4345 assert(image != (
const Image *) NULL);
4346 assert(image->signature == MagickCoreSignature);
4348 assert(exception->signature == MagickCoreSignature);
4349 if (IsEventLogging() != MagickFalse)
4350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4351 width=GetOptimalKernelWidth2D(radius,sigma);
4352 kernel_info=AcquireKernelInfo((
const char *) NULL);
4354 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
4355 (void) memset(kernel_info,0,
sizeof(*kernel_info));
4356 kernel_info->width=width;
4357 kernel_info->height=width;
4358 kernel_info->x=(ssize_t) (width-1)/2;
4359 kernel_info->y=(ssize_t) (width-1)/2;
4360 kernel_info->signature=MagickCoreSignature;
4361 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
4362 kernel_info->width,kernel_info->height*
sizeof(*kernel_info->values)));
4363 if (kernel_info->values == (
double *) NULL)
4365 kernel_info=DestroyKernelInfo(kernel_info);
4366 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
4369 j=(ssize_t) (kernel_info->width-1)/2;
4371 for (v=(-j); v <= j; v++)
4373 for (u=(-j); u <= j; u++)
4375 kernel_info->values[i]=(double) (-exp(-((
double) u*u+v*v)/(2.0*
4376 MagickSigma*MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
4377 normalize+=kernel_info->values[i];
4381 kernel_info->values[i/2]=(double) ((-2.0)*normalize);
4383 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
4384 normalize+=kernel_info->values[i];
4385 gamma=PerceptibleReciprocal(normalize);
4386 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
4387 kernel_info->values[i]*=gamma;
4388 sharp_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
4389 kernel_info,exception);
4390 kernel_info=DestroyKernelInfo(kernel_info);
4391 return(sharp_image);
4422MagickExport
Image *SpreadImage(
const Image *image,
const double radius,
4425#define SpreadImageTag "Spread/Image"
4444 **magick_restrict random_info;
4452#if defined(MAGICKCORE_OPENMP_SUPPORT)
4460 assert(image != (
Image *) NULL);
4461 assert(image->signature == MagickCoreSignature);
4463 assert(exception->signature == MagickCoreSignature);
4464 if (IsEventLogging() != MagickFalse)
4465 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4466 spread_image=CloneImage(image,0,0,MagickTrue,exception);
4467 if (spread_image == (
Image *) NULL)
4468 return((
Image *) NULL);
4469 if (SetImageStorageClass(spread_image,DirectClass) == MagickFalse)
4471 InheritException(exception,&spread_image->exception);
4472 spread_image=DestroyImage(spread_image);
4473 return((
Image *) NULL);
4480 GetMagickPixelPacket(spread_image,&bias);
4481 width=GetOptimalKernelWidth1D(radius,0.5);
4482 random_info=AcquireRandomInfoTLS();
4483 image_view=AcquireVirtualCacheView(image,exception);
4484 spread_view=AcquireAuthenticCacheView(spread_image,exception);
4485#if defined(MAGICKCORE_OPENMP_SUPPORT)
4486 key=GetRandomSecretKey(random_info[0]);
4487 #pragma omp parallel for schedule(static) shared(progress,status) \
4488 magick_number_threads(image,spread_image,spread_image->rows,key == ~0UL)
4490 for (y=0; y < (ssize_t) spread_image->rows; y++)
4493 id = GetOpenMPThreadId();
4499 *magick_restrict indexes;
4507 if (status == MagickFalse)
4509 q=QueueCacheViewAuthenticPixels(spread_view,0,y,spread_image->columns,1,
4516 indexes=GetCacheViewAuthenticIndexQueue(spread_view);
4518 for (x=0; x < (ssize_t) spread_image->columns; x++)
4523 point.x=GetPseudoRandomValue(random_info[
id]);
4524 point.y=GetPseudoRandomValue(random_info[
id]);
4525 status=InterpolateMagickPixelPacket(image,image_view,image->interpolate,
4526 (
double) x+width*(point.x-0.5),(
double) y+width*(point.y-0.5),&pixel,
4528 if (status == MagickFalse)
4530 SetPixelPacket(spread_image,&pixel,q,indexes+x);
4533 if (SyncCacheViewAuthenticPixels(spread_view,exception) == MagickFalse)
4535 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4540#if defined(MAGICKCORE_OPENMP_SUPPORT)
4544 proceed=SetImageProgress(image,SpreadImageTag,progress,image->rows);
4545 if (proceed == MagickFalse)
4549 spread_view=DestroyCacheView(spread_view);
4550 image_view=DestroyCacheView(image_view);
4551 random_info=DestroyRandomInfoTLS(random_info);
4552 if (status == MagickFalse)
4553 spread_image=DestroyImage(spread_image);
4554 return(spread_image);
4602MagickExport
Image *UnsharpMaskImage(
const Image *image,
const double radius,
4603 const double sigma,
const double gain,
const double threshold,
4610 sharp_image=UnsharpMaskImageChannel(image,DefaultChannels,radius,sigma,gain,
4611 threshold,exception);
4613 return(sharp_image);
4616MagickExport
Image *UnsharpMaskImageChannel(
const Image *image,
4617 const ChannelType channel,
const double radius,
const double sigma,
4618 const double gain,
const double threshold,
ExceptionInfo *exception)
4620#define SharpenImageTag "Sharpen/Image"
4644 assert(image != (
const Image *) NULL);
4645 assert(image->signature == MagickCoreSignature);
4647 assert(exception->signature == MagickCoreSignature);
4648 if (IsEventLogging() != MagickFalse)
4649 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4658 unsharp_image=BlurImageChannel(image,(ChannelType) (channel &~ SyncChannels),
4659 radius,sigma,exception);
4660 if (unsharp_image == (
Image *) NULL)
4661 return((
Image *) NULL);
4662 quantum_threshold=(MagickRealType) QuantumRange*threshold;
4668 GetMagickPixelPacket(image,&bias);
4669 image_view=AcquireVirtualCacheView(image,exception);
4670 unsharp_view=AcquireAuthenticCacheView(unsharp_image,exception);
4671#if defined(MAGICKCORE_OPENMP_SUPPORT)
4672 #pragma omp parallel for schedule(static) shared(progress,status) \
4673 magick_number_threads(image,unsharp_image,image->rows,1)
4675 for (y=0; y < (ssize_t) image->rows; y++)
4681 *magick_restrict indexes;
4687 *magick_restrict unsharp_indexes;
4695 if (status == MagickFalse)
4697 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
4698 q=GetCacheViewAuthenticPixels(unsharp_view,0,y,unsharp_image->columns,1,
4705 indexes=GetCacheViewVirtualIndexQueue(image_view);
4706 unsharp_indexes=GetCacheViewAuthenticIndexQueue(unsharp_view);
4708 pixel.green=bias.green;
4709 pixel.blue=bias.blue;
4710 pixel.opacity=bias.opacity;
4711 pixel.index=bias.index;
4712 for (x=0; x < (ssize_t) image->columns; x++)
4714 if ((channel & RedChannel) != 0)
4716 pixel.red=(MagickRealType) GetPixelRed(p)-(MagickRealType)
4718 if (fabs(2.0*pixel.red) < quantum_threshold)
4719 pixel.red=(MagickRealType) GetPixelRed(p);
4721 pixel.red=(MagickRealType) GetPixelRed(p)+(pixel.red*gain);
4722 SetPixelRed(q,ClampToQuantum(pixel.red));
4724 if ((channel & GreenChannel) != 0)
4726 pixel.green=(MagickRealType) GetPixelGreen(p)-(MagickRealType)
4728 if (fabs(2.0*pixel.green) < quantum_threshold)
4729 pixel.green=(MagickRealType) GetPixelGreen(p);
4731 pixel.green=(MagickRealType) GetPixelGreen(p)+(pixel.green*gain);
4732 SetPixelGreen(q,ClampToQuantum(pixel.green));
4734 if ((channel & BlueChannel) != 0)
4736 pixel.blue=(MagickRealType) GetPixelBlue(p)-(MagickRealType) q->blue;
4737 if (fabs(2.0*pixel.blue) < quantum_threshold)
4738 pixel.blue=(MagickRealType) GetPixelBlue(p);
4740 pixel.blue=(MagickRealType) GetPixelBlue(p)+(pixel.blue*gain);
4741 SetPixelBlue(q,ClampToQuantum(pixel.blue));
4743 if ((channel & OpacityChannel) != 0)
4745 pixel.opacity=(MagickRealType) GetPixelOpacity(p)-(MagickRealType)
4747 if (fabs(2.0*pixel.opacity) < quantum_threshold)
4748 pixel.opacity=(MagickRealType) GetPixelOpacity(p);
4750 pixel.opacity=(MagickRealType) GetPixelOpacity(p)+
4751 (pixel.opacity*gain);
4752 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
4754 if (((channel & IndexChannel) != 0) &&
4755 (image->colorspace == CMYKColorspace))
4757 pixel.index=(MagickRealType) GetPixelIndex(indexes+x)-
4758 (MagickRealType) GetPixelIndex(unsharp_indexes+x);
4759 if (fabs(2.0*pixel.index) < quantum_threshold)
4760 pixel.index=(MagickRealType) GetPixelIndex(indexes+x);
4762 pixel.index=(MagickRealType) GetPixelIndex(indexes+x)+
4764 SetPixelIndex(unsharp_indexes+x,ClampToQuantum(pixel.index));
4769 if (SyncCacheViewAuthenticPixels(unsharp_view,exception) == MagickFalse)
4771 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4776#if defined(MAGICKCORE_OPENMP_SUPPORT)
4780 proceed=SetImageProgress(image,SharpenImageTag,progress,image->rows);
4781 if (proceed == MagickFalse)
4785 unsharp_image->type=image->type;
4786 unsharp_view=DestroyCacheView(unsharp_view);
4787 image_view=DestroyCacheView(image_view);
4788 if (status == MagickFalse)
4789 unsharp_image=DestroyImage(unsharp_image);
4790 return(unsharp_image);