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(f != (Quantum *) NULL);
970 assert(g != (Quantum *) NULL);
973 r=p+(y_offset*((ssize_t) columns+2)+x_offset);
974#if defined(MAGICKCORE_OPENMP_SUPPORT)
975 #pragma omp parallel for schedule(static) \
976 magick_number_threads(image,image,rows,1)
978 for (y=0; y < (ssize_t) rows; y++)
989 for (x=0; x < (ssize_t) columns; x++)
991 v=(SignedQuantum) p[i];
992 if ((SignedQuantum) r[i] >= (v+ScaleCharToQuantum(2)))
993 v+=ScaleCharToQuantum(1);
998 for (x=0; x < (ssize_t) columns; x++)
1000 v=(SignedQuantum) p[i];
1001 if ((SignedQuantum) r[i] <= (v-ScaleCharToQuantum(2)))
1002 v-=ScaleCharToQuantum(1);
1010 r=q+(y_offset*((ssize_t) columns+2)+x_offset);
1011 s=q-(y_offset*((ssize_t) columns+2)+x_offset);
1012#if defined(MAGICKCORE_OPENMP_SUPPORT)
1013 #pragma omp parallel for schedule(static) \
1014 magick_number_threads(image,image,rows,1)
1016 for (y=0; y < (ssize_t) rows; y++)
1025 i=(2*y+1)+y*columns;
1027 for (x=0; x < (ssize_t) columns; x++)
1029 v=(SignedQuantum) q[i];
1030 if (((SignedQuantum) s[i] >= (v+ScaleCharToQuantum(2))) &&
1031 ((SignedQuantum) r[i] > v))
1032 v+=ScaleCharToQuantum(1);
1037 for (x=0; x < (ssize_t) columns; x++)
1039 v=(SignedQuantum) q[i];
1040 if (((SignedQuantum) s[i] <= (v-ScaleCharToQuantum(2))) &&
1041 ((SignedQuantum) r[i] < v))
1042 v-=ScaleCharToQuantum(1);
1051#define DespeckleImageTag "Despeckle/Image"
1071 *magick_restrict buffer,
1072 *magick_restrict pixels;
1078 static const ssize_t
1079 X[4] = {0, 1, 1,-1},
1080 Y[4] = {1, 0, 1, 1};
1085 assert(image != (
const Image *) NULL);
1086 assert(image->signature == MagickCoreSignature);
1088 assert(exception->signature == MagickCoreSignature);
1089 if (IsEventLogging() != MagickFalse)
1090 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1091#if defined(MAGICKCORE_OPENCL_SUPPORT)
1092 despeckle_image=AccelerateDespeckleImage(image, exception);
1093 if (despeckle_image != (
Image *) NULL)
1094 return(despeckle_image);
1096 despeckle_image=CloneImage(image,0,0,MagickTrue,exception);
1097 if (despeckle_image == (
Image *) NULL)
1098 return((
Image *) NULL);
1099 if (SetImageStorageClass(despeckle_image,DirectClass) == MagickFalse)
1101 InheritException(exception,&despeckle_image->exception);
1102 despeckle_image=DestroyImage(despeckle_image);
1103 return((
Image *) NULL);
1108 if ((image->columns > (MAGICK_SIZE_MAX-2)) ||
1109 (image->rows > (MAGICK_SIZE_MAX-2)))
1111 despeckle_image=DestroyImage(despeckle_image);
1112 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1114 length=(image->columns+2)*(image->rows+2);
1115 pixel_info=AcquireVirtualMemory(length,
sizeof(*pixels));
1116 buffer_info=AcquireVirtualMemory(length,
sizeof(*buffer));
1121 buffer_info=RelinquishVirtualMemory(buffer_info);
1123 pixel_info=RelinquishVirtualMemory(pixel_info);
1124 despeckle_image=DestroyImage(despeckle_image);
1125 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1127 pixels=(Quantum *) GetVirtualMemoryBlob(pixel_info);
1128 buffer=(Quantum *) GetVirtualMemoryBlob(buffer_info);
1133 number_channels=(size_t) (image->colorspace == CMYKColorspace ? 5 : 4);
1134 image_view=AcquireVirtualCacheView(image,exception);
1135 despeckle_view=AcquireAuthenticCacheView(despeckle_image,exception);
1136 for (i=0; i < (ssize_t) number_channels; i++)
1146 if (status == MagickFalse)
1148 if ((image->matte == MagickFalse) && (i == 3))
1150 (void) memset(pixels,0,length*
sizeof(*pixels));
1151 j=(ssize_t) image->columns+2;
1152 for (y=0; y < (ssize_t) image->rows; y++)
1155 *magick_restrict indexes;
1160 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1163 indexes=GetCacheViewVirtualIndexQueue(image_view);
1165 for (x=0; x < (ssize_t) image->columns; x++)
1169 case 0: pixels[j]=GetPixelRed(p);
break;
1170 case 1: pixels[j]=GetPixelGreen(p);
break;
1171 case 2: pixels[j]=GetPixelBlue(p);
break;
1172 case 3: pixels[j]=GetPixelOpacity(p);
break;
1173 case 4: pixels[j]=GetPixelBlack(indexes+x);
break;
1181 (void) memset(buffer,0,length*
sizeof(*buffer));
1182 for (k=0; k < 4; k++)
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);
1186 Hull(image,-X[k],-Y[k],image->columns,image->rows,-1,pixels,buffer);
1187 Hull(image,X[k],Y[k],image->columns,image->rows,-1,pixels,buffer);
1189 j=(ssize_t) image->columns+2;
1190 for (y=0; y < (ssize_t) image->rows; y++)
1196 *magick_restrict indexes;
1201 q=GetCacheViewAuthenticPixels(despeckle_view,0,y,despeckle_image->columns,
1205 indexes=GetCacheViewAuthenticIndexQueue(despeckle_view);
1207 for (x=0; x < (ssize_t) image->columns; x++)
1211 case 0: SetPixelRed(q,pixels[j]);
break;
1212 case 1: SetPixelGreen(q,pixels[j]);
break;
1213 case 2: SetPixelBlue(q,pixels[j]);
break;
1214 case 3: SetPixelOpacity(q,pixels[j]);
break;
1215 case 4: SetPixelIndex(indexes+x,pixels[j]);
break;
1221 sync=SyncCacheViewAuthenticPixels(despeckle_view,exception);
1222 if (sync == MagickFalse)
1229 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1234 proceed=SetImageProgress(image,DespeckleImageTag,(MagickOffsetType) i,
1236 if (proceed == MagickFalse)
1240 despeckle_view=DestroyCacheView(despeckle_view);
1241 image_view=DestroyCacheView(image_view);
1242 buffer_info=RelinquishVirtualMemory(buffer_info);
1243 pixel_info=RelinquishVirtualMemory(pixel_info);
1244 despeckle_image->type=image->type;
1245 if (status == MagickFalse)
1246 despeckle_image=DestroyImage(despeckle_image);
1247 return(despeckle_image);
1279MagickExport
Image *EdgeImage(
const Image *image,
const double radius,
1294 assert(image != (
const Image *) NULL);
1295 assert(image->signature == MagickCoreSignature);
1297 assert(exception->signature == MagickCoreSignature);
1298 if (IsEventLogging() != MagickFalse)
1299 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1300 width=GetOptimalKernelWidth1D(radius,0.5);
1301 kernel_info=AcquireKernelInfo((
const char *) NULL);
1303 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1304 (void) memset(kernel_info,0,
sizeof(*kernel_info));
1305 kernel_info->width=width;
1306 kernel_info->height=width;
1307 kernel_info->x=(ssize_t) (kernel_info->width-1)/2;
1308 kernel_info->y=(ssize_t) (kernel_info->height-1)/2;
1309 kernel_info->signature=MagickCoreSignature;
1310 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
1311 kernel_info->width,kernel_info->height*
sizeof(*kernel_info->values)));
1312 if (kernel_info->values == (
double *) NULL)
1314 kernel_info=DestroyKernelInfo(kernel_info);
1315 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1317 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1318 kernel_info->values[i]=(-1.0);
1319 kernel_info->values[i/2]=(double) kernel_info->width*kernel_info->height-1.0;
1320 edge_image=(
Image *) NULL;
1321#if defined(MAGICKCORE_OPENCL_SUPPORT)
1322 edge_image=AccelerateConvolveImageChannel(image,DefaultChannels,kernel_info,
1325 if (edge_image == (
Image *) NULL)
1326 edge_image=MorphologyImageChannel(image,DefaultChannels,ConvolveMorphology,
1327 1,kernel_info,exception);
1328 kernel_info=DestroyKernelInfo(kernel_info);
1365MagickExport
Image *EmbossImage(
const Image *image,
const double radius,
1390 assert(image != (
const Image *) NULL);
1391 assert(image->signature == MagickCoreSignature);
1393 assert(exception->signature == MagickCoreSignature);
1394 if (IsEventLogging() != MagickFalse)
1395 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1396 width=GetOptimalKernelWidth1D(radius,sigma);
1397 kernel_info=AcquireKernelInfo((
const char *) NULL);
1399 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1400 kernel_info->width=width;
1401 kernel_info->height=width;
1402 kernel_info->x=(ssize_t) (width-1)/2;
1403 kernel_info->y=(ssize_t) (width-1)/2;
1404 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
1405 kernel_info->width,kernel_info->width*
sizeof(*kernel_info->values)));
1406 if (kernel_info->values == (
double *) NULL)
1408 kernel_info=DestroyKernelInfo(kernel_info);
1409 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1411 j=(ssize_t) (kernel_info->width-1)/2;
1414 for (v=(-j); v <= j; v++)
1416 for (u=(-j); u <= j; u++)
1418 kernel_info->values[i]=(double) (((u < 0) || (v < 0) ? -8.0 :
1419 8.0)*exp(-((double) u*u+v*v)/(2.0*MagickSigma*MagickSigma))/
1420 (2.0*MagickPI*MagickSigma*MagickSigma));
1422 kernel_info->values[i]=0.0;
1428 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1429 normalize+=kernel_info->values[i];
1430 gamma=PerceptibleReciprocal(normalize);
1431 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
1432 kernel_info->values[i]*=gamma;
1433 emboss_image=(
Image *) NULL;
1434#if defined(MAGICKCORE_OPENCL_SUPPORT)
1435 emboss_image=AccelerateConvolveImageChannel(image,DefaultChannels,kernel_info,
1438 if (emboss_image == (
Image *) NULL)
1439 emboss_image=MorphologyImageChannel(image,DefaultChannels,
1440 ConvolveMorphology,1,kernel_info,exception);
1441 kernel_info=DestroyKernelInfo(kernel_info);
1442 if (emboss_image != (
Image *) NULL)
1443 (void) EqualizeImageChannel(emboss_image,(ChannelType)
1444 (AllChannels &~ SyncChannels));
1445 return(emboss_image);
1486 filter_image=FilterImageChannel(image,DefaultChannels,kernel,exception);
1487 return(filter_image);
1490MagickExport
Image *FilterImageChannel(
const Image *image,
1493#define FilterImageTag "Filter/Image"
1520#ifdef MAGICKCORE_CLPERFMARKER
1521 clBeginPerfMarkerAMD(__FUNCTION__,
"");
1527 assert(image != (
Image *) NULL);
1528 assert(image->signature == MagickCoreSignature);
1530 assert(exception->signature == MagickCoreSignature);
1531 if (IsEventLogging() != MagickFalse)
1532 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1533 if ((kernel->width % 2) == 0)
1534 ThrowImageException(OptionError,
"KernelWidthMustBeAnOddNumber");
1535 if (image->debug != MagickFalse)
1538 format[MaxTextExtent],
1548 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
1549 " FilterImage with %.20gx%.20g kernel:",(double) kernel->width,(
double)
1551 message=AcquireString(
"");
1553 for (v=0; v < (ssize_t) kernel->height; v++)
1556 (void) FormatLocaleString(format,MaxTextExtent,
"%.20g: ",(
double) v);
1557 (void) ConcatenateString(&message,format);
1558 for (u=0; u < (ssize_t) kernel->width; u++)
1560 (void) FormatLocaleString(format,MaxTextExtent,
"%g ",*k++);
1561 (void) ConcatenateString(&message,format);
1563 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"%s",message);
1565 message=DestroyString(message);
1567#if defined(MAGICKCORE_OPENCL_SUPPORT)
1568 filter_image=AccelerateConvolveImageChannel(image,channel,kernel,exception);
1569 if (filter_image != (
Image *) NULL)
1571#ifdef MAGICKCORE_CLPERFMARKER
1572 clEndPerfMarkerAMD();
1574 return(filter_image);
1577 filter_image=CloneImage(image,0,0,MagickTrue,exception);
1578 if (filter_image == (
Image *) NULL)
1579 return((
Image *) NULL);
1580 if (SetImageStorageClass(filter_image,DirectClass) == MagickFalse)
1582 InheritException(exception,&filter_image->exception);
1583 filter_image=DestroyImage(filter_image);
1584 return((
Image *) NULL);
1589 filter_kernel=(MagickRealType *) MagickAssumeAligned(AcquireAlignedMemory(
1590 kernel->width,kernel->height*
sizeof(*filter_kernel)));
1591 if (filter_kernel == (MagickRealType *) NULL)
1593 filter_image=DestroyImage(filter_image);
1594 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1596 for (i=0; i < (ssize_t) (kernel->width*kernel->height); i++)
1597 filter_kernel[i]=(MagickRealType) kernel->values[i];
1603 GetMagickPixelPacket(image,&bias);
1604 SetMagickPixelPacketBias(image,&bias);
1605 image_view=AcquireVirtualCacheView(image,exception);
1606 filter_view=AcquireAuthenticCacheView(filter_image,exception);
1607#if defined(MAGICKCORE_OPENMP_SUPPORT)
1608 #pragma omp parallel for schedule(static) shared(progress,status) \
1609 magick_number_threads(image,filter_image,image->rows,1)
1611 for (y=0; y < (ssize_t) image->rows; y++)
1617 *magick_restrict indexes;
1623 *magick_restrict filter_indexes;
1631 if (status == MagickFalse)
1633 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) (kernel->width-1)/2L),y-
1634 (ssize_t) ((kernel->height-1)/2L),image->columns+kernel->width,
1635 kernel->height,exception);
1636 q=GetCacheViewAuthenticPixels(filter_view,0,y,filter_image->columns,1,
1643 indexes=GetCacheViewVirtualIndexQueue(image_view);
1644 filter_indexes=GetCacheViewAuthenticIndexQueue(filter_view);
1645 for (x=0; x < (ssize_t) image->columns; x++)
1650 const MagickRealType
1654 *magick_restrict kernel_pixels;
1663 pixel.green=bias.green;
1664 pixel.blue=bias.blue;
1665 pixel.opacity=bias.opacity;
1666 pixel.index=bias.index;
1669 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
1671 for (v=0; v < (ssize_t) kernel->width; v++)
1673 for (u=0; u < (ssize_t) kernel->height; u++)
1675 pixel.red+=(*k)*(double) kernel_pixels[u].red;
1676 pixel.green+=(*k)*(double) kernel_pixels[u].green;
1677 pixel.blue+=(*k)*(double) kernel_pixels[u].blue;
1680 kernel_pixels+=image->columns+kernel->width;
1682 if ((channel & RedChannel) != 0)
1683 SetPixelRed(q,ClampToQuantum(pixel.red));
1684 if ((channel & GreenChannel) != 0)
1685 SetPixelGreen(q,ClampToQuantum(pixel.green));
1686 if ((channel & BlueChannel) != 0)
1687 SetPixelBlue(q,ClampToQuantum(pixel.blue));
1688 if ((channel & OpacityChannel) != 0)
1692 for (v=0; v < (ssize_t) kernel->width; v++)
1694 for (u=0; u < (ssize_t) kernel->height; u++)
1696 pixel.opacity+=(*k)*(MagickRealType) kernel_pixels[u].opacity;
1699 kernel_pixels+=image->columns+kernel->width;
1701 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
1703 if (((channel & IndexChannel) != 0) &&
1704 (image->colorspace == CMYKColorspace))
1707 *magick_restrict kernel_indexes;
1710 kernel_indexes=indexes;
1711 for (v=0; v < (ssize_t) kernel->width; v++)
1713 for (u=0; u < (ssize_t) kernel->height; u++)
1715 pixel.index+=(*k)*(double) GetPixelIndex(kernel_indexes+u);
1718 kernel_indexes+=image->columns+kernel->width;
1720 SetPixelIndex(filter_indexes+x,ClampToQuantum(pixel.index));
1730 for (v=0; v < (ssize_t) kernel->width; v++)
1732 for (u=0; u < (ssize_t) kernel->height; u++)
1734 alpha=(MagickRealType) QuantumScale*((MagickRealType)
1735 QuantumRange-(MagickRealType) GetPixelOpacity(kernel_pixels+u));
1736 pixel.red+=(*k)*alpha*(double) GetPixelRed(kernel_pixels+u);
1737 pixel.green+=(*k)*alpha*(double) GetPixelGreen(kernel_pixels+u);
1738 pixel.blue+=(*k)*alpha*(double) GetPixelBlue(kernel_pixels+u);
1742 kernel_pixels+=image->columns+kernel->width;
1744 gamma=PerceptibleReciprocal(gamma);
1745 if ((channel & RedChannel) != 0)
1746 SetPixelRed(q,ClampToQuantum(gamma*(
double) pixel.red));
1747 if ((channel & GreenChannel) != 0)
1748 SetPixelGreen(q,ClampToQuantum(gamma*(
double) pixel.green));
1749 if ((channel & BlueChannel) != 0)
1750 SetPixelBlue(q,ClampToQuantum(gamma*(
double) pixel.blue));
1751 if ((channel & OpacityChannel) != 0)
1755 for (v=0; v < (ssize_t) kernel->width; v++)
1757 for (u=0; u < (ssize_t) kernel->height; u++)
1759 pixel.opacity+=(*k)*(double) GetPixelOpacity(kernel_pixels+u);
1762 kernel_pixels+=image->columns+kernel->width;
1764 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
1766 if (((channel & IndexChannel) != 0) &&
1767 (image->colorspace == CMYKColorspace))
1770 *magick_restrict kernel_indexes;
1774 kernel_indexes=indexes;
1775 for (v=0; v < (ssize_t) kernel->width; v++)
1777 for (u=0; u < (ssize_t) kernel->height; u++)
1779 alpha=(MagickRealType) (QuantumScale*((
double) QuantumRange-
1780 (double) kernel_pixels[u].opacity));
1781 pixel.index+=(*k)*alpha*(MagickRealType)
1782 GetPixelIndex(kernel_indexes+u);
1785 kernel_pixels+=image->columns+kernel->width;
1786 kernel_indexes+=image->columns+kernel->width;
1788 SetPixelIndex(filter_indexes+x,ClampToQuantum(gamma*(
double)
1796 sync=SyncCacheViewAuthenticPixels(filter_view,exception);
1797 if (sync == MagickFalse)
1799 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1804#if defined(MAGICKCORE_OPENMP_SUPPORT)
1808 proceed=SetImageProgress(image,FilterImageTag,progress,image->rows);
1809 if (proceed == MagickFalse)
1813 filter_image->type=image->type;
1814 filter_view=DestroyCacheView(filter_view);
1815 image_view=DestroyCacheView(image_view);
1816 filter_kernel=(MagickRealType *) RelinquishAlignedMemory(filter_kernel);
1817 if (status == MagickFalse)
1818 filter_image=DestroyImage(filter_image);
1819#ifdef MAGICKCORE_CLPERFMARKER
1820 clEndPerfMarkerAMD();
1822 return(filter_image);
1864MagickExport
Image *GaussianBlurImage(
const Image *image,
const double radius,
1870 blur_image=GaussianBlurImageChannel(image,DefaultChannels,radius,sigma,
1875MagickExport
Image *GaussianBlurImageChannel(
const Image *image,
1876 const ChannelType channel,
const double radius,
const double sigma,
1880 geometry[MaxTextExtent];
1888 assert(image != (
const Image *) NULL);
1889 assert(image->signature == MagickCoreSignature);
1891 assert(exception->signature == MagickCoreSignature);
1892 if (IsEventLogging() != MagickFalse)
1893 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1894 (void) FormatLocaleString(geometry,MaxTextExtent,
"gaussian:%.20gx%.20g",
1896 kernel_info=AcquireKernelInfo(geometry);
1898 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
1899 blur_image=(
Image *) NULL;
1900#if defined(MAGICKCORE_OPENCL_SUPPORT)
1901 blur_image=AccelerateConvolveImageChannel(image,channel,kernel_info,
1904 if (blur_image == (
Image *) NULL)
1905 blur_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
1906 kernel_info,exception);
1907 kernel_info=DestroyKernelInfo(kernel_info);
1955static double *GetMotionBlurKernel(
const size_t width,
const double sigma)
1967 if (IsEventLogging() != MagickFalse)
1968 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1969 kernel=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
1971 if (kernel == (
double *) NULL)
1974 for (i=0; i < (ssize_t) width; i++)
1976 kernel[i]=(double) (exp((-((
double) i*i)/(
double) (2.0*MagickSigma*
1977 MagickSigma)))/(MagickSQ2PI*MagickSigma));
1978 normalize+=kernel[i];
1980 for (i=0; i < (ssize_t) width; i++)
1981 kernel[i]/=normalize;
1985MagickExport
Image *MotionBlurImage(
const Image *image,
const double radius,
1986 const double sigma,
const double angle,
ExceptionInfo *exception)
1991 motion_blur=MotionBlurImageChannel(image,DefaultChannels,radius,sigma,angle,
1993 return(motion_blur);
1996MagickExport
Image *MotionBlurImageChannel(
const Image *image,
1997 const ChannelType channel,
const double radius,
const double sigma,
2000#define BlurImageTag "Blur/Image"
2036 assert(image != (
Image *) NULL);
2037 assert(image->signature == MagickCoreSignature);
2039 assert(exception->signature == MagickCoreSignature);
2040 if (IsEventLogging() != MagickFalse)
2041 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2042 width=GetOptimalKernelWidth1D(radius,sigma);
2043 kernel=GetMotionBlurKernel(width,sigma);
2044 if (kernel == (
double *) NULL)
2045 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2046 offset=(
OffsetInfo *) AcquireQuantumMemory(width,
sizeof(*offset));
2049 kernel=(
double *) RelinquishAlignedMemory(kernel);
2050 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2053 point.x=(double) width*sin(DegreesToRadians(angle));
2054 point.y=(double) width*cos(DegreesToRadians(angle));
2055 for (i=0; i < (ssize_t) width; i++)
2057 offset[i].x=CastDoubleToLong(ceil((
double) (i*point.y)/
2058 hypot(point.x,point.y)-0.5));
2059 offset[i].y=CastDoubleToLong(ceil((
double) (i*point.x)/
2060 hypot(point.x,point.y)-0.5));
2066#if defined(MAGICKCORE_OPENCL_SUPPORT)
2067 blur_image=AccelerateMotionBlurImage(image,channel,kernel,width,offset,
2069 if (blur_image != (
Image *) NULL)
2072 blur_image=CloneImage(image,0,0,MagickTrue,exception);
2073 if (blur_image == (
Image *) NULL)
2075 kernel=(
double *) RelinquishAlignedMemory(kernel);
2076 offset=(
OffsetInfo *) RelinquishMagickMemory(offset);
2077 return((
Image *) NULL);
2079 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
2081 kernel=(
double *) RelinquishAlignedMemory(kernel);
2082 offset=(
OffsetInfo *) RelinquishMagickMemory(offset);
2083 InheritException(exception,&blur_image->exception);
2084 blur_image=DestroyImage(blur_image);
2085 return((
Image *) NULL);
2090 GetMagickPixelPacket(image,&bias);
2091 image_view=AcquireVirtualCacheView(image,exception);
2092 blur_view=AcquireAuthenticCacheView(blur_image,exception);
2093#if defined(MAGICKCORE_OPENMP_SUPPORT)
2094 #pragma omp parallel for schedule(static) shared(progress,status) \
2095 magick_number_threads(image,blur_image,image->rows,1)
2097 for (y=0; y < (ssize_t) image->rows; y++)
2100 *magick_restrict blur_indexes;
2108 if (status == MagickFalse)
2110 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
2117 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
2118 for (x=0; x < (ssize_t) image->columns; x++)
2127 *magick_restrict indexes;
2137 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
2139 for (i=0; i < (ssize_t) width; i++)
2141 (void) GetOneCacheViewVirtualPixel(image_view,x+offset[i].x,y+
2142 offset[i].y,&pixel,exception);
2143 qixel.red+=(*k)*(double) pixel.red;
2144 qixel.green+=(*k)*(double) pixel.green;
2145 qixel.blue+=(*k)*(double) pixel.blue;
2146 qixel.opacity+=(*k)*(double) pixel.opacity;
2147 if (image->colorspace == CMYKColorspace)
2149 indexes=GetCacheViewVirtualIndexQueue(image_view);
2150 qixel.index+=(*k)*(double) (*indexes);
2154 if ((channel & RedChannel) != 0)
2155 SetPixelRed(q,ClampToQuantum(qixel.red));
2156 if ((channel & GreenChannel) != 0)
2157 SetPixelGreen(q,ClampToQuantum(qixel.green));
2158 if ((channel & BlueChannel) != 0)
2159 SetPixelBlue(q,ClampToQuantum(qixel.blue));
2160 if ((channel & OpacityChannel) != 0)
2161 SetPixelOpacity(q,ClampToQuantum(qixel.opacity));
2162 if (((channel & IndexChannel) != 0) &&
2163 (image->colorspace == CMYKColorspace))
2164 SetPixelIndex(blur_indexes+x,ClampToQuantum(qixel.index));
2172 for (i=0; i < (ssize_t) width; i++)
2174 (void) GetOneCacheViewVirtualPixel(image_view,x+offset[i].x,y+
2175 offset[i].y,&pixel,exception);
2176 alpha=(MagickRealType) (QuantumScale*(
double)
2177 GetPixelAlpha(&pixel));
2178 qixel.red+=(*k)*alpha*(double) pixel.red;
2179 qixel.green+=(*k)*alpha*(double) pixel.green;
2180 qixel.blue+=(*k)*alpha*(double) pixel.blue;
2181 qixel.opacity+=(*k)*(double) pixel.opacity;
2182 if (image->colorspace == CMYKColorspace)
2184 indexes=GetCacheViewVirtualIndexQueue(image_view);
2185 qixel.index+=(*k)*alpha*(double) GetPixelIndex(indexes);
2190 gamma=PerceptibleReciprocal(gamma);
2191 if ((channel & RedChannel) != 0)
2192 SetPixelRed(q,ClampToQuantum(gamma*qixel.red));
2193 if ((channel & GreenChannel) != 0)
2194 SetPixelGreen(q,ClampToQuantum(gamma*qixel.green));
2195 if ((channel & BlueChannel) != 0)
2196 SetPixelBlue(q,ClampToQuantum(gamma*qixel.blue));
2197 if ((channel & OpacityChannel) != 0)
2198 SetPixelOpacity(q,ClampToQuantum(qixel.opacity));
2199 if (((channel & IndexChannel) != 0) &&
2200 (image->colorspace == CMYKColorspace))
2201 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*qixel.index));
2205 if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
2207 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2212#if defined(MAGICKCORE_OPENMP_SUPPORT)
2216 proceed=SetImageProgress(image,BlurImageTag,progress,image->rows);
2217 if (proceed == MagickFalse)
2221 blur_view=DestroyCacheView(blur_view);
2222 image_view=DestroyCacheView(image_view);
2223 kernel=(
double *) RelinquishAlignedMemory(kernel);
2224 offset=(
OffsetInfo *) RelinquishMagickMemory(offset);
2225 if (status == MagickFalse)
2226 blur_image=DestroyImage(blur_image);
2264MagickExport
Image *KuwaharaImage(
const Image *image,
const double radius,
2270 kuwahara_image=KuwaharaImageChannel(image,DefaultChannels,radius,sigma,
2272 return(kuwahara_image);
2275MagickExport
Image *KuwaharaImageChannel(
const Image *image,
2276 const ChannelType channel,
const double radius,
const double sigma,
2279#define KuwaharaImageTag "Kiwahara/Image"
2304 assert(image != (
Image *) NULL);
2305 assert(image->signature == MagickCoreSignature);
2307 assert(exception->signature == MagickCoreSignature);
2308 if (IsEventLogging() != MagickFalse)
2309 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2311 width=(size_t) radius+1;
2312 gaussian_image=BlurImage(image,radius,sigma,exception);
2313 if (gaussian_image == (
Image *) NULL)
2314 return((
Image *) NULL);
2315 kuwahara_image=CloneImage(image,0,0,MagickTrue,exception);
2316 if (kuwahara_image == (
Image *) NULL)
2318 gaussian_image=DestroyImage(gaussian_image);
2319 return((
Image *) NULL);
2321 if (SetImageStorageClass(kuwahara_image,DirectClass) == MagickFalse)
2323 InheritException(exception,&kuwahara_image->exception);
2324 gaussian_image=DestroyImage(gaussian_image);
2325 kuwahara_image=DestroyImage(kuwahara_image);
2326 return((
Image *) NULL);
2333 image_view=AcquireVirtualCacheView(gaussian_image,exception);
2334 kuwahara_view=AcquireAuthenticCacheView(kuwahara_image,exception);
2335#if defined(MAGICKCORE_OPENMP_SUPPORT)
2336 #pragma omp parallel for schedule(static) shared(progress,status) \
2337 magick_number_threads(image,kuwahara_image,kuwahara_image->rows,1)
2339 for (y=0; y < (ssize_t) kuwahara_image->rows; y++)
2342 *magick_restrict kuwahara_indexes;
2350 if (status == MagickFalse)
2352 q=QueueCacheViewAuthenticPixels(kuwahara_view,0,y,kuwahara_image->columns,1,
2359 kuwahara_indexes=GetCacheViewAuthenticIndexQueue(kuwahara_view);
2360 for (x=0; x < (ssize_t) kuwahara_image->columns; x++)
2375 min_variance=MagickMaximumValue;
2376 SetGeometry(gaussian_image,&target);
2377 quadrant.width=width;
2378 quadrant.height=width;
2379 for (i=0; i < 4; i++)
2402 quadrant.x=x-(ssize_t) (width-1);
2403 quadrant.y=y-(ssize_t) (width-1);
2408 quadrant.y=y-(ssize_t) (width-1);
2413 quadrant.x=x-(ssize_t) (width-1);
2419 p=GetCacheViewVirtualPixels(image_view,quadrant.x,quadrant.y,
2420 quadrant.width,quadrant.height,exception);
2423 GetMagickPixelPacket(image,&mean);
2425 for (n=0; n < (ssize_t) (width*width); n++)
2427 mean.red+=(double) k->red;
2428 mean.green+=(double) k->green;
2429 mean.blue+=(double) k->blue;
2432 mean.red/=(double) (width*width);
2433 mean.green/=(double) (width*width);
2434 mean.blue/=(double) (width*width);
2437 for (n=0; n < (ssize_t) (width*width); n++)
2442 luma=GetPixelLuma(image,k);
2443 variance+=(luma-MagickPixelLuma(&mean))*(luma-MagickPixelLuma(&mean));
2446 if (variance < min_variance)
2448 min_variance=variance;
2457 status=InterpolateMagickPixelPacket(gaussian_image,image_view,
2458 UndefinedInterpolatePixel,(
double) target.x+target.width/2.0,
2459 (
double) target.y+target.height/2.0,&pixel,exception);
2460 if (status == MagickFalse)
2462 SetPixelPacket(kuwahara_image,&pixel,q,kuwahara_indexes+x);
2465 if (SyncCacheViewAuthenticPixels(kuwahara_view,exception) == MagickFalse)
2467 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2472#if defined(MAGICKCORE_OPENMP_SUPPORT)
2476 proceed=SetImageProgress(image,KuwaharaImageTag,progress,image->rows);
2477 if (proceed == MagickFalse)
2481 kuwahara_view=DestroyCacheView(kuwahara_view);
2482 image_view=DestroyCacheView(image_view);
2483 gaussian_image=DestroyImage(gaussian_image);
2484 if (status == MagickFalse)
2485 kuwahara_image=DestroyImage(kuwahara_image);
2486 return(kuwahara_image);
2522MagickExport
Image *LocalContrastImage(
const Image *image,
const double radius,
2525#define LocalContrastImageTag "LocalContrast/Image"
2553 assert(image != (
const Image *) NULL);
2554 assert(image->signature == MagickCoreSignature);
2556 assert(exception->signature == MagickCoreSignature);
2557 if (IsEventLogging() != MagickFalse)
2558 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2559#if defined(MAGICKCORE_OPENCL_SUPPORT)
2560 contrast_image=AccelerateLocalContrastImage(image,radius,strength,exception);
2561 if (contrast_image != (
Image *) NULL)
2562 return(contrast_image);
2564 contrast_image=CloneImage(image,0,0,MagickTrue,exception);
2565 if (contrast_image == (
Image *) NULL)
2566 return((
Image *) NULL);
2567 if (SetImageStorageClass(contrast_image,DirectClass) == MagickFalse)
2569 InheritException(exception,&contrast_image->exception);
2570 contrast_image=DestroyImage(contrast_image);
2571 return((
Image *) NULL);
2573 image_view=AcquireVirtualCacheView(image,exception);
2574 contrast_view=AcquireAuthenticCacheView(contrast_image,exception);
2575 scanLineSize=(ssize_t) MagickMax(image->columns,image->rows);
2576 width=(ssize_t) scanLineSize*0.002*fabs(radius);
2577 scanLineSize+=(2*width);
2578 scanline_info=AcquireVirtualMemory(GetOpenMPMaximumThreads()*
2579 scanLineSize,
sizeof(*scanline));
2582 contrast_view=DestroyCacheView(contrast_view);
2583 image_view=DestroyCacheView(image_view);
2584 contrast_image=DestroyImage(contrast_image);
2585 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2587 scanline=(
float *) GetVirtualMemoryBlob(scanline_info);
2591 interImage_info=AcquireVirtualMemory(image->rows*(image->columns+(2*width)),
2592 sizeof(*interImage));
2595 scanline_info=RelinquishVirtualMemory(scanline_info);
2596 contrast_view=DestroyCacheView(contrast_view);
2597 image_view=DestroyCacheView(image_view);
2598 contrast_image=DestroyImage(contrast_image);
2599 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
2601 interImage=(
float *) GetVirtualMemoryBlob(interImage_info);
2602 totalWeight=(width+1)*(width+1);
2611#if defined(MAGICKCORE_OPENMP_SUPPORT)
2612 #pragma omp parallel for schedule(static) \
2613 magick_number_threads(image,image,image->columns,1)
2615 for (x=0; x < (ssize_t) image->columns; x++)
2618 id = GetOpenMPThreadId();
2634 if (status == MagickFalse)
2637 pixels+=
id*scanLineSize;
2639 p=GetCacheViewVirtualPixels(image_view,x,-width,1,image->rows+(2*width),
2646 for (y=0; y < (ssize_t) image->rows+(2*width); y++)
2648 *pix++=(float)GetPixelLuma(image,p);
2651 out=interImage+x+width;
2652 for (y=0; y < (ssize_t) image->rows; y++)
2661 for (i=0; i < width; i++)
2663 sum+=weight*(*pix++);
2666 for (i=width+1; i < (2*width); i++)
2668 sum+=weight*(*pix++);
2672 *out=sum/totalWeight;
2674 if (x <= width && x != 0)
2676 if ((x > (ssize_t) image->columns-width-2) &&
2677 (x != (ssize_t) image->columns-1))
2678 *(out+((image->columns-x-1)*2))=*out;
2679 out+=image->columns+(width*2);
2690#if defined(MAGICKCORE_OPENMP_SUPPORT)
2691#pragma omp parallel for schedule(static) \
2692 magick_number_threads(image,image,image->rows,1)
2694 for (y=0; y < (ssize_t) image->rows; y++)
2697 id = GetOpenMPThreadId();
2715 if (status == MagickFalse)
2718 pixels+=
id*scanLineSize;
2719 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,
2721 q=GetCacheViewAuthenticPixels(contrast_view,0,y,image->columns,1,
2728 memcpy(pixels,interImage+(y*(image->columns+(2*width))),(image->columns+
2729 (2*width))*
sizeof(
float));
2730 for (x=0; x < (ssize_t) image->columns; x++)
2741 for (i=0; i < width; i++)
2743 sum+=weight*(*pix++);
2746 for (i=width+1; i < (2*width); i++)
2748 sum+=weight*(*pix++);
2752 srcVal=(float) GetPixelLuma(image,p);
2753 mult=(srcVal-(sum/totalWeight))*(float) (0.01*strength);
2754 mult=(srcVal+mult)/srcVal;
2755 SetPixelRed(q,ClampToQuantum((MagickRealType) GetPixelRed(p)*
2756 (MagickRealType) mult));
2757 SetPixelGreen(q,ClampToQuantum((MagickRealType) GetPixelGreen(p)*
2758 (MagickRealType) mult));
2759 SetPixelBlue(q,ClampToQuantum((MagickRealType) GetPixelBlue(p)*
2760 (MagickRealType) mult));
2764 if (SyncCacheViewAuthenticPixels(contrast_view,exception) == MagickFalse)
2768 scanline_info=RelinquishVirtualMemory(scanline_info);
2769 interImage_info=RelinquishVirtualMemory(interImage_info);
2770 contrast_view=DestroyCacheView(contrast_view);
2771 image_view=DestroyCacheView(image_view);
2772 if (status == MagickFalse)
2773 contrast_image=DestroyImage(contrast_image);
2774 return(contrast_image);
2807MagickExport
Image *PreviewImage(
const Image *image,
const PreviewType preview,
2810#define NumberTiles 9
2811#define PreviewImageTag "Preview/Image"
2812#define DefaultPreviewGeometry "204x204+10+10"
2815 factor[MaxTextExtent],
2816 label[MaxTextExtent];
2858 assert(image != (
Image *) NULL);
2859 assert(image->signature == MagickCoreSignature);
2860 if (IsEventLogging() != MagickFalse)
2861 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2865 preview_info=AcquireImageInfo();
2866 SetGeometry(image,&geometry);
2867 (void) ParseMetaGeometry(DefaultPreviewGeometry,&geometry.x,&geometry.y,
2868 &geometry.width,&geometry.height);
2869 images=NewImageList();
2871 GetQuantizeInfo(&quantize_info);
2877 for (i=0; i < NumberTiles; i++)
2879 thumbnail=ThumbnailImage(image,geometry.width,geometry.height,exception);
2880 if (thumbnail == (
Image *) NULL)
2882 (void) SetImageProgressMonitor(thumbnail,(MagickProgressMonitor) NULL,
2884 (void) SetImageProperty(thumbnail,
"label",DefaultTileLabel);
2885 if (i == (NumberTiles/2))
2887 (void) QueryColorDatabase(
"#dfdfdf",&thumbnail->matte_color,exception);
2888 AppendImageToList(&images,thumbnail);
2896 preview_image=RotateImage(thumbnail,degrees,exception);
2897 (void) FormatLocaleString(label,MaxTextExtent,
"rotate %g",degrees);
2903 preview_image=ShearImage(thumbnail,degrees,degrees,exception);
2904 (void) FormatLocaleString(label,MaxTextExtent,
"shear %gx%g",
2905 degrees,2.0*degrees);
2910 x=(ssize_t) ((i+1)*thumbnail->columns)/NumberTiles;
2911 y=(ssize_t) ((i+1)*thumbnail->rows)/NumberTiles;
2912 preview_image=RollImage(thumbnail,x,y,exception);
2913 (void) FormatLocaleString(label,MaxTextExtent,
"roll %+.20gx%+.20g",
2914 (
double) x,(double) y);
2919 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2920 if (preview_image == (
Image *) NULL)
2922 (void) FormatLocaleString(factor,MaxTextExtent,
"100,100,%g",
2924 (void) ModulateImage(preview_image,factor);
2925 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2928 case SaturationPreview:
2930 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2931 if (preview_image == (
Image *) NULL)
2933 (void) FormatLocaleString(factor,MaxTextExtent,
"100,%g",2.0*percentage);
2934 (void) ModulateImage(preview_image,factor);
2935 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2938 case BrightnessPreview:
2940 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2941 if (preview_image == (
Image *) NULL)
2943 (void) FormatLocaleString(factor,MaxTextExtent,
"%g",2.0*percentage);
2944 (void) ModulateImage(preview_image,factor);
2945 (void) FormatLocaleString(label,MaxTextExtent,
"modulate %s",factor);
2951 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2952 if (preview_image == (
Image *) NULL)
2955 (void) GammaImageChannel(preview_image,DefaultChannels,gamma);
2956 (void) FormatLocaleString(label,MaxTextExtent,
"gamma %g",gamma);
2961 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2962 if (preview_image != (
Image *) NULL)
2963 for (x=0; x < i; x++)
2964 (
void) ContrastImage(preview_image,MagickTrue);
2965 (void) FormatLocaleString(label,MaxTextExtent,
"contrast (%.20g)",
2971 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2972 if (preview_image == (
Image *) NULL)
2974 for (x=0; x < i; x++)
2975 (
void) ContrastImage(preview_image,MagickFalse);
2976 (void) FormatLocaleString(label,MaxTextExtent,
"+contrast (%.20g)",
2980 case GrayscalePreview:
2982 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2983 if (preview_image == (
Image *) NULL)
2986 quantize_info.number_colors=colors;
2987 quantize_info.colorspace=GRAYColorspace;
2988 (void) QuantizeImage(&quantize_info,preview_image);
2989 (void) FormatLocaleString(label,MaxTextExtent,
2990 "-colorspace gray -colors %.20g",(
double) colors);
2993 case QuantizePreview:
2995 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
2996 if (preview_image == (
Image *) NULL)
2999 quantize_info.number_colors=colors;
3000 (void) QuantizeImage(&quantize_info,preview_image);
3001 (void) FormatLocaleString(label,MaxTextExtent,
"colors %.20g",(
double)
3005 case DespecklePreview:
3007 for (x=0; x < (i-1); x++)
3009 preview_image=DespeckleImage(thumbnail,exception);
3010 if (preview_image == (
Image *) NULL)
3012 thumbnail=DestroyImage(thumbnail);
3013 thumbnail=preview_image;
3015 preview_image=DespeckleImage(thumbnail,exception);
3016 if (preview_image == (
Image *) NULL)
3018 (void) FormatLocaleString(label,MaxTextExtent,
"despeckle (%.20g)",
3022 case ReduceNoisePreview:
3024 preview_image=StatisticImage(thumbnail,NonpeakStatistic,(
size_t) radius,
3025 (
size_t) radius,exception);
3026 (void) FormatLocaleString(label,MaxTextExtent,
"noise %g",radius);
3029 case AddNoisePreview:
3035 (void) CopyMagickString(factor,
"uniform",MaxTextExtent);
3040 (void) CopyMagickString(factor,
"gaussian",MaxTextExtent);
3045 (void) CopyMagickString(factor,
"multiplicative",MaxTextExtent);
3050 (void) CopyMagickString(factor,
"impulse",MaxTextExtent);
3055 (void) CopyMagickString(factor,
"laplacian",MaxTextExtent);
3060 (void) CopyMagickString(factor,
"poisson",MaxTextExtent);
3065 (void) CopyMagickString(thumbnail->magick,
"NULL",MaxTextExtent);
3069 preview_image=StatisticImage(thumbnail,NonpeakStatistic,(
size_t) i,
3070 (
size_t) i,exception);
3071 (void) FormatLocaleString(label,MaxTextExtent,
"+noise %s",factor);
3074 case SharpenPreview:
3076 preview_image=SharpenImage(thumbnail,radius,sigma,exception);
3077 (void) FormatLocaleString(label,MaxTextExtent,
"sharpen %gx%g",
3083 preview_image=BlurImage(thumbnail,radius,sigma,exception);
3084 (void) FormatLocaleString(label,MaxTextExtent,
"blur %gx%g",radius,
3088 case ThresholdPreview:
3090 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3091 if (preview_image == (
Image *) NULL)
3093 (void) BilevelImage(thumbnail,
3094 (
double) (percentage*((MagickRealType) QuantumRange+1.0))/100.0);
3095 (void) FormatLocaleString(label,MaxTextExtent,
"threshold %g",
3096 (
double) (percentage*((MagickRealType) QuantumRange+1.0))/100.0);
3099 case EdgeDetectPreview:
3101 preview_image=EdgeImage(thumbnail,radius,exception);
3102 (void) FormatLocaleString(label,MaxTextExtent,
"edge %g",radius);
3107 preview_image=SpreadImage(thumbnail,radius,exception);
3108 (void) FormatLocaleString(label,MaxTextExtent,
"spread %g",
3112 case SolarizePreview:
3114 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3115 if (preview_image == (
Image *) NULL)
3117 (void) SolarizeImage(preview_image,(
double) QuantumRange*
3119 (void) FormatLocaleString(label,MaxTextExtent,
"solarize %g",
3120 ((
double) QuantumRange*percentage)/100.0);
3126 preview_image=ShadeImage(thumbnail,MagickTrue,degrees,degrees,
3128 (void) FormatLocaleString(label,MaxTextExtent,
"shade %gx%g",
3137 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3138 if (preview_image == (
Image *) NULL)
3140 raise.width=(size_t) (2*i+2);
3141 raise.height=(size_t) (2*i+2);
3144 (void) RaiseImage(preview_image,&raise,MagickTrue);
3145 (void) FormatLocaleString(label,MaxTextExtent,
3146 "raise %.20gx%.20g%+.20g%+.20g",(
double) raise.width,(double)
3147 raise.height,(
double) raise.x,(double) raise.y);
3150 case SegmentPreview:
3152 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3153 if (preview_image == (
Image *) NULL)
3156 (void) SegmentImage(preview_image,sRGBColorspace,MagickFalse,threshold,
3158 (void) FormatLocaleString(label,MaxTextExtent,
"segment %gx%g",
3159 threshold,threshold);
3164 preview_image=SwirlImage(thumbnail,degrees,exception);
3165 (void) FormatLocaleString(label,MaxTextExtent,
"swirl %g",degrees);
3169 case ImplodePreview:
3172 preview_image=ImplodeImage(thumbnail,degrees,exception);
3173 (void) FormatLocaleString(label,MaxTextExtent,
"implode %g",degrees);
3179 preview_image=WaveImage(thumbnail,0.5*degrees,2.0*degrees,exception);
3180 (void) FormatLocaleString(label,MaxTextExtent,
"wave %gx%g",
3181 0.5*degrees,2.0*degrees);
3184 case OilPaintPreview:
3186 preview_image=OilPaintImage(thumbnail,(
double) radius,exception);
3187 (void) FormatLocaleString(label,MaxTextExtent,
"paint %g",radius);
3190 case CharcoalDrawingPreview:
3192 preview_image=CharcoalImage(thumbnail,(
double) radius,(
double) sigma,
3194 (void) FormatLocaleString(label,MaxTextExtent,
"charcoal %gx%g",
3201 filename[MaxTextExtent];
3209 preview_image=CloneImage(thumbnail,0,0,MagickTrue,exception);
3210 if (preview_image == (
Image *) NULL)
3212 preview_info->quality=(size_t) percentage;
3213 (void) FormatLocaleString(factor,MaxTextExtent,
"%.20g",(
double)
3214 preview_info->quality);
3215 file=AcquireUniqueFileResource(filename);
3218 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,
3219 "jpeg:%s",filename);
3220 status=WriteImage(preview_info,preview_image);
3221 if (status != MagickFalse)
3226 (void) CopyMagickString(preview_info->filename,
3227 preview_image->filename,MaxTextExtent);
3228 quality_image=ReadImage(preview_info,exception);
3229 if (quality_image != (
Image *) NULL)
3231 preview_image=DestroyImage(preview_image);
3232 preview_image=quality_image;
3235 (void) RelinquishUniqueFileResource(preview_image->filename);
3236 if ((GetBlobSize(preview_image)/1024) >= 1024)
3237 (
void) FormatLocaleString(label,MaxTextExtent,
"quality %s\n%gmb ",
3238 factor,(
double) ((MagickOffsetType) GetBlobSize(preview_image))/
3241 if (GetBlobSize(preview_image) >= 1024)
3242 (void) FormatLocaleString(label,MaxTextExtent,
3243 "quality %s\n%gkb ",factor,(
double) ((MagickOffsetType)
3244 GetBlobSize(preview_image))/1024.0);
3246 (
void) FormatLocaleString(label,MaxTextExtent,
"quality %s\n%.20gb ",
3247 factor,(
double) ((MagickOffsetType) GetBlobSize(thumbnail)));
3251 thumbnail=DestroyImage(thumbnail);
3255 if (preview_image == (
Image *) NULL)
3257 (void) DeleteImageProperty(preview_image,
"label");
3258 (void) SetImageProperty(preview_image,
"label",label);
3259 AppendImageToList(&images,preview_image);
3260 proceed=SetImageProgress(image,PreviewImageTag,(MagickOffsetType) i,
3262 if (proceed == MagickFalse)
3265 if (images == (
Image *) NULL)
3267 preview_info=DestroyImageInfo(preview_info);
3268 return((
Image *) NULL);
3273 montage_info=CloneMontageInfo(preview_info,(
MontageInfo *) NULL);
3274 (void) CopyMagickString(montage_info->filename,image->filename,MaxTextExtent);
3275 montage_info->shadow=MagickTrue;
3276 (void) CloneString(&montage_info->tile,
"3x3");
3277 (void) CloneString(&montage_info->geometry,DefaultPreviewGeometry);
3278 (void) CloneString(&montage_info->frame,DefaultTileFrame);
3279 montage_image=MontageImages(images,montage_info,exception);
3280 montage_info=DestroyMontageInfo(montage_info);
3281 images=DestroyImageList(images);
3282 if (montage_image == (
Image *) NULL)
3283 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3284 if (montage_image->montage != (
char *) NULL)
3289 montage_image->montage=(
char *) RelinquishMagickMemory(
3290 montage_image->montage);
3291 if (image->directory != (
char *) NULL)
3292 montage_image->directory=(
char *) RelinquishMagickMemory(
3293 montage_image->directory);
3295 preview_info=DestroyImageInfo(preview_info);
3296 return(montage_image);
3333MagickExport
Image *RotationalBlurImage(
const Image *image,
const double angle,
3339 blur_image=RotationalBlurImageChannel(image,DefaultChannels,angle,exception);
3343MagickExport
Image *RotationalBlurImageChannel(
const Image *image,
3344 const ChannelType channel,
const double angle,
ExceptionInfo *exception)
3384 assert(image != (
Image *) NULL);
3385 assert(image->signature == MagickCoreSignature);
3387 assert(exception->signature == MagickCoreSignature);
3388 if (IsEventLogging() != MagickFalse)
3389 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3390#if defined(MAGICKCORE_OPENCL_SUPPORT)
3391 blur_image=AccelerateRadialBlurImage(image,channel,angle,exception);
3392 if (blur_image != (
Image *) NULL)
3395 blur_image=CloneImage(image,0,0,MagickTrue,exception);
3396 if (blur_image == (
Image *) NULL)
3397 return((
Image *) NULL);
3398 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
3400 InheritException(exception,&blur_image->exception);
3401 blur_image=DestroyImage(blur_image);
3402 return((
Image *) NULL);
3404 blur_center.x=(double) (image->columns-1)/2.0;
3405 blur_center.y=(double) (image->rows-1)/2.0;
3406 blur_radius=hypot(blur_center.x,blur_center.y);
3407 n=(size_t) fabs(4.0*DegreesToRadians(angle)*sqrt((
double) blur_radius)+2UL);
3408 theta=DegreesToRadians(angle)/(MagickRealType) (n-1);
3409 cos_theta=(MagickRealType *) AcquireQuantumMemory((
size_t) n,
3410 sizeof(*cos_theta));
3411 sin_theta=(MagickRealType *) AcquireQuantumMemory((
size_t) n,
3412 sizeof(*sin_theta));
3413 if ((cos_theta == (MagickRealType *) NULL) ||
3414 (sin_theta == (MagickRealType *) NULL))
3416 if (cos_theta != (MagickRealType *) NULL)
3417 cos_theta=(MagickRealType *) RelinquishMagickMemory(cos_theta);
3418 if (sin_theta != (MagickRealType *) NULL)
3419 sin_theta=(MagickRealType *) RelinquishMagickMemory(sin_theta);
3420 blur_image=DestroyImage(blur_image);
3421 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3423 offset=theta*(MagickRealType) (n-1)/2.0;
3424 for (i=0; i < (ssize_t) n; i++)
3426 cos_theta[i]=cos((
double) (theta*i-offset));
3427 sin_theta[i]=sin((
double) (theta*i-offset));
3434 GetMagickPixelPacket(image,&bias);
3435 image_view=AcquireVirtualCacheView(image,exception);
3436 blur_view=AcquireAuthenticCacheView(blur_image,exception);
3437#if defined(MAGICKCORE_OPENMP_SUPPORT)
3438 #pragma omp parallel for schedule(static) shared(progress,status) \
3439 magick_number_threads(image,blur_image,blur_image->rows,1)
3441 for (y=0; y < (ssize_t) blur_image->rows; y++)
3444 *magick_restrict indexes;
3447 *magick_restrict blur_indexes;
3455 if (status == MagickFalse)
3457 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
3464 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
3465 for (x=0; x < (ssize_t) blur_image->columns; x++)
3486 center.x=(double) x-blur_center.x;
3487 center.y=(double) y-blur_center.y;
3488 radius=hypot((
double) center.x,center.y);
3493 step=(size_t) (blur_radius/radius);
3502 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
3504 for (i=0; i < (ssize_t) n; i+=(ssize_t) step)
3506 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t)
3507 (blur_center.x+center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),
3508 (ssize_t) (blur_center.y+center.x*sin_theta[i]+center.y*
3509 cos_theta[i]+0.5),&pixel,exception);
3510 qixel.red+=(MagickRealType) pixel.red;
3511 qixel.green+=(MagickRealType) pixel.green;
3512 qixel.blue+=(MagickRealType) pixel.blue;
3513 qixel.opacity+=(MagickRealType) pixel.opacity;
3514 if (image->colorspace == CMYKColorspace)
3516 indexes=GetCacheViewVirtualIndexQueue(image_view);
3517 qixel.index+=(MagickRealType) (*indexes);
3521 normalize=PerceptibleReciprocal(normalize);
3522 if ((channel & RedChannel) != 0)
3523 SetPixelRed(q,ClampToQuantum(normalize*qixel.red));
3524 if ((channel & GreenChannel) != 0)
3525 SetPixelGreen(q,ClampToQuantum(normalize*qixel.green));
3526 if ((channel & BlueChannel) != 0)
3527 SetPixelBlue(q,ClampToQuantum(normalize*qixel.blue));
3528 if ((channel & OpacityChannel) != 0)
3529 SetPixelOpacity(q,ClampToQuantum(normalize*qixel.opacity));
3530 if (((channel & IndexChannel) != 0) &&
3531 (image->colorspace == CMYKColorspace))
3532 SetPixelIndex(blur_indexes+x,ClampToQuantum(normalize*qixel.index));
3542 for (i=0; i < (ssize_t) n; i+=(ssize_t) step)
3544 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t)
3545 (blur_center.x+center.x*cos_theta[i]-center.y*sin_theta[i]+0.5),
3546 (ssize_t) (blur_center.y+center.x*sin_theta[i]+center.y*
3547 cos_theta[i]+0.5),&pixel,exception);
3548 alpha=(MagickRealType) (QuantumScale*GetPixelAlpha(&pixel));
3549 qixel.red+=alpha*(MagickRealType) pixel.red;
3550 qixel.green+=alpha*(MagickRealType) pixel.green;
3551 qixel.blue+=alpha*(MagickRealType) pixel.blue;
3552 qixel.opacity+=(MagickRealType) pixel.opacity;
3553 if (image->colorspace == CMYKColorspace)
3555 indexes=GetCacheViewVirtualIndexQueue(image_view);
3556 qixel.index+=alpha*(MagickRealType) (*indexes);
3561 gamma=PerceptibleReciprocal(gamma);
3562 normalize=PerceptibleReciprocal(normalize);
3563 if ((channel & RedChannel) != 0)
3564 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) qixel.red));
3565 if ((channel & GreenChannel) != 0)
3566 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType) qixel.green));
3567 if ((channel & BlueChannel) != 0)
3568 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType) qixel.blue));
3569 if ((channel & OpacityChannel) != 0)
3570 SetPixelOpacity(q,ClampToQuantum(normalize*(MagickRealType)
3572 if (((channel & IndexChannel) != 0) &&
3573 (image->colorspace == CMYKColorspace))
3574 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*(MagickRealType)
3579 if (SyncCacheViewAuthenticPixels(blur_view,exception) == MagickFalse)
3581 if (image->progress_monitor != (MagickProgressMonitor) NULL)
3586#if defined(MAGICKCORE_OPENMP_SUPPORT)
3590 proceed=SetImageProgress(image,BlurImageTag,progress,image->rows);
3591 if (proceed == MagickFalse)
3595 blur_view=DestroyCacheView(blur_view);
3596 image_view=DestroyCacheView(image_view);
3597 cos_theta=(MagickRealType *) RelinquishMagickMemory(cos_theta);
3598 sin_theta=(MagickRealType *) RelinquishMagickMemory(sin_theta);
3599 if (status == MagickFalse)
3600 blur_image=DestroyImage(blur_image);
3645MagickExport
Image *SelectiveBlurImage(
const Image *image,
const double radius,
3646 const double sigma,
const double threshold,
ExceptionInfo *exception)
3651 blur_image=SelectiveBlurImageChannel(image,DefaultChannels,radius,sigma,
3652 threshold,exception);
3656MagickExport
Image *SelectiveBlurImageChannel(
const Image *image,
3657 const ChannelType channel,
const double radius,
const double sigma,
3660#define SelectiveBlurImageTag "SelectiveBlur/Image"
3699 assert(image != (
Image *) NULL);
3700 assert(image->signature == MagickCoreSignature);
3702 assert(exception->signature == MagickCoreSignature);
3703 if (IsEventLogging() != MagickFalse)
3704 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
3705 width=GetOptimalKernelWidth1D(radius,sigma);
3706 kernel=(
double *) MagickAssumeAligned(AcquireAlignedMemory((
size_t) width,
3707 width*
sizeof(*kernel)));
3708 if (kernel == (
double *) NULL)
3709 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
3710 j=(ssize_t) (width-1)/2;
3712 for (v=(-j); v <= j; v++)
3714 for (u=(-j); u <= j; u++)
3715 kernel[i++]=(
double) (exp(-((
double) u*u+v*v)/(2.0*MagickSigma*
3716 MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
3718 if (image->debug != MagickFalse)
3721 format[MaxTextExtent],
3731 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
3732 " SelectiveBlurImage with %.20gx%.20g kernel:",(double) width,(
double)
3734 message=AcquireString(
"");
3736 for (v=0; v < (ssize_t) width; v++)
3739 (void) FormatLocaleString(format,MaxTextExtent,
"%.20g: ",(
double) v);
3740 (void) ConcatenateString(&message,format);
3741 for (u=0; u < (ssize_t) width; u++)
3743 (void) FormatLocaleString(format,MaxTextExtent,
"%+f ",*k++);
3744 (void) ConcatenateString(&message,format);
3746 (void) LogMagickEvent(TransformEvent,GetMagickModule(),
"%s",message);
3748 message=DestroyString(message);
3750 blur_image=CloneImage(image,0,0,MagickTrue,exception);
3751 if (blur_image == (
Image *) NULL)
3753 kernel=(
double *) RelinquishAlignedMemory(kernel);
3754 return((
Image *) NULL);
3756 if (SetImageStorageClass(blur_image,DirectClass) == MagickFalse)
3758 kernel=(
double *) RelinquishAlignedMemory(kernel);
3759 InheritException(exception,&blur_image->exception);
3760 blur_image=DestroyImage(blur_image);
3761 return((
Image *) NULL);
3763 luminance_image=CloneImage(image,0,0,MagickTrue,exception);
3764 if (luminance_image == (
Image *) NULL)
3766 kernel=(
double *) RelinquishAlignedMemory(kernel);
3767 blur_image=DestroyImage(blur_image);
3768 return((
Image *) NULL);
3770 status=TransformImageColorspace(luminance_image,GRAYColorspace);
3771 if (status == MagickFalse)
3773 InheritException(exception,&luminance_image->exception);
3774 kernel=(
double *) RelinquishAlignedMemory(kernel);
3775 blur_image=DestroyImage(blur_image);
3776 luminance_image=DestroyImage(luminance_image);
3777 return((
Image *) NULL);
3784 center=(ssize_t) ((image->columns+width)*((width-1)/2L)+((width-1)/2L));
3785 GetMagickPixelPacket(image,&bias);
3786 SetMagickPixelPacketBias(image,&bias);
3787 image_view=AcquireVirtualCacheView(image,exception);
3788 luminance_view=AcquireVirtualCacheView(luminance_image,exception);
3789 blur_view=AcquireAuthenticCacheView(blur_image,exception);
3790#if defined(MAGICKCORE_OPENMP_SUPPORT)
3791 #pragma omp parallel for schedule(static) shared(progress,status) \
3792 magick_number_threads(image,blur_image,image->rows,1)
3794 for (y=0; y < (ssize_t) image->rows; y++)
3803 *magick_restrict indexes;
3810 *magick_restrict blur_indexes;
3818 if (status == MagickFalse)
3820 p=GetCacheViewVirtualPixels(image_view,-((ssize_t) (width-1)/2L),y-(ssize_t)
3821 ((width-1)/2L),image->columns+width,width,exception);
3822 l=GetCacheViewVirtualPixels(luminance_view,-((ssize_t) (width-1)/2L),y-
3823 (ssize_t) ((width-1)/2L),luminance_image->columns+width,width,exception);
3824 q=GetCacheViewAuthenticPixels(blur_view,0,y,blur_image->columns,1,
3832 indexes=GetCacheViewVirtualIndexQueue(image_view);
3833 blur_indexes=GetCacheViewAuthenticIndexQueue(blur_view);
3834 for (x=0; x < (ssize_t) image->columns; x++)
3856 pixel.green=bias.green;
3857 pixel.blue=bias.blue;
3858 pixel.opacity=bias.opacity;
3859 pixel.index=bias.index;
3861 intensity=GetPixelIntensity(image,p+center);
3864 if (((channel & OpacityChannel) == 0) || (image->matte == MagickFalse))
3866 for (v=0; v < (ssize_t) width; v++)
3868 for (u=0; u < (ssize_t) width; u++)
3870 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3871 if (fabs(contrast) < threshold)
3873 pixel.red+=(*k)*(MagickRealType) GetPixelRed(p+u+j);
3874 pixel.green+=(*k)*(MagickRealType) GetPixelGreen(p+u+j);
3875 pixel.blue+=(*k)*(MagickRealType) GetPixelBlue(p+u+j);
3880 j+=(ssize_t) (image->columns+width);
3884 gamma=PerceptibleReciprocal(gamma);
3885 if ((channel & RedChannel) != 0)
3886 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType)
3888 if ((channel & GreenChannel) != 0)
3889 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType)
3891 if ((channel & BlueChannel) != 0)
3892 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType)
3895 if ((channel & OpacityChannel) != 0)
3899 for (v=0; v < (ssize_t) width; v++)
3901 for (u=0; u < (ssize_t) width; u++)
3903 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3904 if (fabs(contrast) < threshold)
3906 pixel.opacity+=(*k)*(MagickRealType) (p+u+j)->opacity;
3911 j+=(ssize_t) (image->columns+width);
3913 gamma=PerceptibleReciprocal(gamma);
3914 SetPixelOpacity(q,ClampToQuantum(gamma*pixel.opacity));
3916 if (((channel & IndexChannel) != 0) &&
3917 (image->colorspace == CMYKColorspace))
3921 for (v=0; v < (ssize_t) width; v++)
3923 for (u=0; u < (ssize_t) width; u++)
3925 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3926 if (fabs(contrast) < threshold)
3928 pixel.index+=(*k)*(MagickRealType)
3929 GetPixelIndex(indexes+x+u+j);
3934 j+=(ssize_t) (image->columns+width);
3936 gamma=PerceptibleReciprocal(gamma);
3937 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*pixel.index));
3945 for (v=0; v < (ssize_t) width; v++)
3947 for (u=0; u < (ssize_t) width; u++)
3949 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3950 if (fabs(contrast) < threshold)
3952 alpha=(MagickRealType) (QuantumScale*(MagickRealType)
3953 GetPixelAlpha(p+u+j));
3954 pixel.red+=(*k)*alpha*(MagickRealType) GetPixelRed(p+u+j);
3955 pixel.green+=(*k)*alpha*(MagickRealType) GetPixelGreen(p+u+j);
3956 pixel.blue+=(*k)*alpha*(MagickRealType) GetPixelBlue(p+u+j);
3957 pixel.opacity+=(*k)*(MagickRealType) GetPixelOpacity(p+u+j);
3962 j+=(ssize_t) (image->columns+width);
3966 gamma=PerceptibleReciprocal(gamma);
3967 if ((channel & RedChannel) != 0)
3968 SetPixelRed(q,ClampToQuantum(gamma*(MagickRealType) pixel.red));
3969 if ((channel & GreenChannel) != 0)
3970 SetPixelGreen(q,ClampToQuantum(gamma*(MagickRealType)
3972 if ((channel & BlueChannel) != 0)
3973 SetPixelBlue(q,ClampToQuantum(gamma*(MagickRealType)
3976 if ((channel & OpacityChannel) != 0)
3979 for (v=0; v < (ssize_t) width; v++)
3981 for (u=0; u < (ssize_t) width; u++)
3983 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
3984 if (fabs(contrast) < threshold)
3985 pixel.opacity+=(*k)*(MagickRealType) GetPixelOpacity(p+u+j);
3988 j+=(ssize_t) (image->columns+width);
3990 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
3992 if (((channel & IndexChannel) != 0) &&
3993 (image->colorspace == CMYKColorspace))
3997 for (v=0; v < (ssize_t) width; v++)
3999 for (u=0; u < (ssize_t) width; u++)
4001 contrast=GetPixelIntensity(luminance_image,l+u+j)-intensity;
4002 if (fabs(contrast) < threshold)
4004 alpha=(MagickRealType) (QuantumScale*(MagickRealType)
4005 GetPixelAlpha(p+u+j));
4006 pixel.index+=(*k)*alpha*(MagickRealType)
4007 GetPixelIndex(indexes+x+u+j);
4012 j+=(ssize_t) (image->columns+width);
4014 gamma=PerceptibleReciprocal(gamma);
4015 SetPixelIndex(blur_indexes+x,ClampToQuantum(gamma*pixel.index));
4022 sync=SyncCacheViewAuthenticPixels(blur_view,exception);
4023 if (sync == MagickFalse)
4025 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4030#if defined(MAGICKCORE_OPENMP_SUPPORT)
4034 proceed=SetImageProgress(image,SelectiveBlurImageTag,progress,
4036 if (proceed == MagickFalse)
4040 blur_image->type=image->type;
4041 blur_view=DestroyCacheView(blur_view);
4042 luminance_view=DestroyCacheView(luminance_view);
4043 image_view=DestroyCacheView(image_view);
4044 luminance_image=DestroyImage(luminance_image);
4045 kernel=(
double *) RelinquishAlignedMemory(kernel);
4046 if (status == MagickFalse)
4047 blur_image=DestroyImage(blur_image);
4083MagickExport
Image *ShadeImage(
const Image *image,
const MagickBooleanType gray,
4084 const double azimuth,
const double elevation,
ExceptionInfo *exception)
4086#define GetShadeIntensity(image,pixel) \
4087 ClampPixel(GetPixelIntensity((image),(pixel)))
4088#define ShadeImageTag "Shade/Image"
4113 assert(image != (
const Image *) NULL);
4114 assert(image->signature == MagickCoreSignature);
4116 assert(exception->signature == MagickCoreSignature);
4117 if (IsEventLogging() != MagickFalse)
4118 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4119 linear_image=CloneImage(image,0,0,MagickTrue,exception);
4120 shade_image=CloneImage(image,0,0,MagickTrue,exception);
4121 if ((linear_image == (
Image *) NULL) || (shade_image == (
Image *) NULL))
4123 if (linear_image != (
Image *) NULL)
4124 linear_image=DestroyImage(linear_image);
4125 if (shade_image != (
Image *) NULL)
4126 shade_image=DestroyImage(shade_image);
4127 return((
Image *) NULL);
4129 if (SetImageStorageClass(shade_image,DirectClass) == MagickFalse)
4131 InheritException(exception,&shade_image->exception);
4132 linear_image=DestroyImage(linear_image);
4133 shade_image=DestroyImage(shade_image);
4134 return((
Image *) NULL);
4139 light.x=(double) QuantumRange*cos(DegreesToRadians(azimuth))*
4140 cos(DegreesToRadians(elevation));
4141 light.y=(double) QuantumRange*sin(DegreesToRadians(azimuth))*
4142 cos(DegreesToRadians(elevation));
4143 light.z=(double) QuantumRange*sin(DegreesToRadians(elevation));
4149 image_view=AcquireVirtualCacheView(linear_image,exception);
4150 shade_view=AcquireAuthenticCacheView(shade_image,exception);
4151#if defined(MAGICKCORE_OPENMP_SUPPORT)
4152 #pragma omp parallel for schedule(static) shared(progress,status) \
4153 magick_number_threads(linear_image,shade_image,linear_image->rows,1)
4155 for (y=0; y < (ssize_t) linear_image->rows; y++)
4167 *magick_restrict s0,
4168 *magick_restrict s1,
4169 *magick_restrict s2;
4177 if (status == MagickFalse)
4179 p=GetCacheViewVirtualPixels(image_view,-1,y-1,linear_image->columns+2,3,
4181 q=QueueCacheViewAuthenticPixels(shade_view,0,y,shade_image->columns,1,
4191 normal.z=2.0*(double) QuantumRange;
4192 for (x=0; x < (ssize_t) linear_image->columns; x++)
4198 s1=s0+image->columns+2;
4199 s2=s1+image->columns+2;
4200 normal.x=(double) (GetShadeIntensity(linear_image,s0-1)+
4201 GetShadeIntensity(linear_image,s1-1)+
4202 GetShadeIntensity(linear_image,s2-1)-
4203 GetShadeIntensity(linear_image,s0+1)-
4204 GetShadeIntensity(linear_image,s1+1)-
4205 GetShadeIntensity(linear_image,s2+1));
4206 normal.y=(double) (GetShadeIntensity(linear_image,s2-1)+
4207 GetShadeIntensity(linear_image,s2)+
4208 GetShadeIntensity(linear_image,s2+1)-
4209 GetShadeIntensity(linear_image,s0-1)-
4210 GetShadeIntensity(linear_image,s0)-
4211 GetShadeIntensity(linear_image,s0+1));
4212 if ((fabs(normal.x) <= MagickEpsilon) &&
4213 (fabs(normal.y) <= MagickEpsilon))
4218 distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
4219 if (distance > MagickEpsilon)
4221 normal_distance=normal.x*normal.x+normal.y*normal.y+normal.z*
4223 if (normal_distance > (MagickEpsilon*MagickEpsilon))
4224 shade=distance/sqrt((
double) normal_distance);
4227 if (gray != MagickFalse)
4229 SetPixelRed(q,shade);
4230 SetPixelGreen(q,shade);
4231 SetPixelBlue(q,shade);
4235 SetPixelRed(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4237 SetPixelGreen(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4238 GetPixelGreen(s1)));
4239 SetPixelBlue(q,ClampToQuantum(QuantumScale*shade*(MagickRealType)
4242 q->opacity=s1->opacity;
4246 if (SyncCacheViewAuthenticPixels(shade_view,exception) == MagickFalse)
4248 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4253#if defined(MAGICKCORE_OPENMP_SUPPORT)
4257 proceed=SetImageProgress(image,ShadeImageTag,progress,image->rows);
4258 if (proceed == MagickFalse)
4262 shade_view=DestroyCacheView(shade_view);
4263 image_view=DestroyCacheView(image_view);
4264 linear_image=DestroyImage(linear_image);
4265 if (status == MagickFalse)
4266 shade_image=DestroyImage(shade_image);
4267 return(shade_image);
4313MagickExport
Image *SharpenImage(
const Image *image,
const double radius,
4319 sharp_image=SharpenImageChannel(image,DefaultChannels,radius,sigma,exception);
4320 return(sharp_image);
4323MagickExport
Image *SharpenImageChannel(
const Image *image,
4324 const ChannelType channel,
const double radius,
const double sigma,
4348 assert(image != (
const Image *) NULL);
4349 assert(image->signature == MagickCoreSignature);
4351 assert(exception->signature == MagickCoreSignature);
4352 if (IsEventLogging() != MagickFalse)
4353 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4354 width=GetOptimalKernelWidth2D(radius,sigma);
4355 kernel_info=AcquireKernelInfo((
const char *) NULL);
4357 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
4358 (void) memset(kernel_info,0,
sizeof(*kernel_info));
4359 kernel_info->width=width;
4360 kernel_info->height=width;
4361 kernel_info->x=(ssize_t) (width-1)/2;
4362 kernel_info->y=(ssize_t) (width-1)/2;
4363 kernel_info->signature=MagickCoreSignature;
4364 kernel_info->values=(
double *) MagickAssumeAligned(AcquireAlignedMemory(
4365 kernel_info->width,kernel_info->height*
sizeof(*kernel_info->values)));
4366 if (kernel_info->values == (
double *) NULL)
4368 kernel_info=DestroyKernelInfo(kernel_info);
4369 ThrowImageException(ResourceLimitError,
"MemoryAllocationFailed");
4372 j=(ssize_t) (kernel_info->width-1)/2;
4374 for (v=(-j); v <= j; v++)
4376 for (u=(-j); u <= j; u++)
4378 kernel_info->values[i]=(double) (-exp(-((
double) u*u+v*v)/(2.0*
4379 MagickSigma*MagickSigma))/(2.0*MagickPI*MagickSigma*MagickSigma));
4380 normalize+=kernel_info->values[i];
4384 kernel_info->values[i/2]=(double) ((-2.0)*normalize);
4386 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
4387 normalize+=kernel_info->values[i];
4388 gamma=PerceptibleReciprocal(normalize);
4389 for (i=0; i < (ssize_t) (kernel_info->width*kernel_info->height); i++)
4390 kernel_info->values[i]*=gamma;
4391 sharp_image=MorphologyImageChannel(image,channel,ConvolveMorphology,1,
4392 kernel_info,exception);
4393 kernel_info=DestroyKernelInfo(kernel_info);
4394 return(sharp_image);
4425MagickExport
Image *SpreadImage(
const Image *image,
const double radius,
4428#define SpreadImageTag "Spread/Image"
4447 **magick_restrict random_info;
4455#if defined(MAGICKCORE_OPENMP_SUPPORT)
4463 assert(image != (
Image *) NULL);
4464 assert(image->signature == MagickCoreSignature);
4466 assert(exception->signature == MagickCoreSignature);
4467 if (IsEventLogging() != MagickFalse)
4468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4469 spread_image=CloneImage(image,0,0,MagickTrue,exception);
4470 if (spread_image == (
Image *) NULL)
4471 return((
Image *) NULL);
4472 if (SetImageStorageClass(spread_image,DirectClass) == MagickFalse)
4474 InheritException(exception,&spread_image->exception);
4475 spread_image=DestroyImage(spread_image);
4476 return((
Image *) NULL);
4483 GetMagickPixelPacket(spread_image,&bias);
4484 width=GetOptimalKernelWidth1D(radius,0.5);
4485 random_info=AcquireRandomInfoTLS();
4486 image_view=AcquireVirtualCacheView(image,exception);
4487 spread_view=AcquireAuthenticCacheView(spread_image,exception);
4488#if defined(MAGICKCORE_OPENMP_SUPPORT)
4489 key=GetRandomSecretKey(random_info[0]);
4490 #pragma omp parallel for schedule(static) shared(progress,status) \
4491 magick_number_threads(image,spread_image,spread_image->rows,key == ~0UL)
4493 for (y=0; y < (ssize_t) spread_image->rows; y++)
4496 id = GetOpenMPThreadId();
4502 *magick_restrict indexes;
4510 if (status == MagickFalse)
4512 q=QueueCacheViewAuthenticPixels(spread_view,0,y,spread_image->columns,1,
4519 indexes=GetCacheViewAuthenticIndexQueue(spread_view);
4521 for (x=0; x < (ssize_t) spread_image->columns; x++)
4526 point.x=GetPseudoRandomValue(random_info[
id]);
4527 point.y=GetPseudoRandomValue(random_info[
id]);
4528 status=InterpolateMagickPixelPacket(image,image_view,image->interpolate,
4529 (
double) x+width*(point.x-0.5),(
double) y+width*(point.y-0.5),&pixel,
4531 if (status == MagickFalse)
4533 SetPixelPacket(spread_image,&pixel,q,indexes+x);
4536 if (SyncCacheViewAuthenticPixels(spread_view,exception) == MagickFalse)
4538 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4543#if defined(MAGICKCORE_OPENMP_SUPPORT)
4547 proceed=SetImageProgress(image,SpreadImageTag,progress,image->rows);
4548 if (proceed == MagickFalse)
4552 spread_view=DestroyCacheView(spread_view);
4553 image_view=DestroyCacheView(image_view);
4554 random_info=DestroyRandomInfoTLS(random_info);
4555 if (status == MagickFalse)
4556 spread_image=DestroyImage(spread_image);
4557 return(spread_image);
4605MagickExport
Image *UnsharpMaskImage(
const Image *image,
const double radius,
4606 const double sigma,
const double gain,
const double threshold,
4613 sharp_image=UnsharpMaskImageChannel(image,DefaultChannels,radius,sigma,gain,
4614 threshold,exception);
4616 return(sharp_image);
4619MagickExport
Image *UnsharpMaskImageChannel(
const Image *image,
4620 const ChannelType channel,
const double radius,
const double sigma,
4621 const double gain,
const double threshold,
ExceptionInfo *exception)
4623#define SharpenImageTag "Sharpen/Image"
4647 assert(image != (
const Image *) NULL);
4648 assert(image->signature == MagickCoreSignature);
4650 assert(exception->signature == MagickCoreSignature);
4651 if (IsEventLogging() != MagickFalse)
4652 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
4661 unsharp_image=BlurImageChannel(image,(ChannelType) (channel &~ SyncChannels),
4662 radius,sigma,exception);
4663 if (unsharp_image == (
Image *) NULL)
4664 return((
Image *) NULL);
4665 quantum_threshold=(MagickRealType) QuantumRange*threshold;
4671 GetMagickPixelPacket(image,&bias);
4672 image_view=AcquireVirtualCacheView(image,exception);
4673 unsharp_view=AcquireAuthenticCacheView(unsharp_image,exception);
4674#if defined(MAGICKCORE_OPENMP_SUPPORT)
4675 #pragma omp parallel for schedule(static) shared(progress,status) \
4676 magick_number_threads(image,unsharp_image,image->rows,1)
4678 for (y=0; y < (ssize_t) image->rows; y++)
4684 *magick_restrict indexes;
4690 *magick_restrict unsharp_indexes;
4698 if (status == MagickFalse)
4700 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
4701 q=GetCacheViewAuthenticPixels(unsharp_view,0,y,unsharp_image->columns,1,
4708 indexes=GetCacheViewVirtualIndexQueue(image_view);
4709 unsharp_indexes=GetCacheViewAuthenticIndexQueue(unsharp_view);
4711 pixel.green=bias.green;
4712 pixel.blue=bias.blue;
4713 pixel.opacity=bias.opacity;
4714 pixel.index=bias.index;
4715 for (x=0; x < (ssize_t) image->columns; x++)
4717 if ((channel & RedChannel) != 0)
4719 pixel.red=(MagickRealType) GetPixelRed(p)-(MagickRealType)
4721 if (fabs(2.0*pixel.red) < quantum_threshold)
4722 pixel.red=(MagickRealType) GetPixelRed(p);
4724 pixel.red=(MagickRealType) GetPixelRed(p)+(pixel.red*gain);
4725 SetPixelRed(q,ClampToQuantum(pixel.red));
4727 if ((channel & GreenChannel) != 0)
4729 pixel.green=(MagickRealType) GetPixelGreen(p)-(MagickRealType)
4731 if (fabs(2.0*pixel.green) < quantum_threshold)
4732 pixel.green=(MagickRealType) GetPixelGreen(p);
4734 pixel.green=(MagickRealType) GetPixelGreen(p)+(pixel.green*gain);
4735 SetPixelGreen(q,ClampToQuantum(pixel.green));
4737 if ((channel & BlueChannel) != 0)
4739 pixel.blue=(MagickRealType) GetPixelBlue(p)-(MagickRealType) q->blue;
4740 if (fabs(2.0*pixel.blue) < quantum_threshold)
4741 pixel.blue=(MagickRealType) GetPixelBlue(p);
4743 pixel.blue=(MagickRealType) GetPixelBlue(p)+(pixel.blue*gain);
4744 SetPixelBlue(q,ClampToQuantum(pixel.blue));
4746 if ((channel & OpacityChannel) != 0)
4748 pixel.opacity=(MagickRealType) GetPixelOpacity(p)-(MagickRealType)
4750 if (fabs(2.0*pixel.opacity) < quantum_threshold)
4751 pixel.opacity=(MagickRealType) GetPixelOpacity(p);
4753 pixel.opacity=(MagickRealType) GetPixelOpacity(p)+
4754 (pixel.opacity*gain);
4755 SetPixelOpacity(q,ClampToQuantum(pixel.opacity));
4757 if (((channel & IndexChannel) != 0) &&
4758 (image->colorspace == CMYKColorspace))
4760 pixel.index=(MagickRealType) GetPixelIndex(indexes+x)-
4761 (MagickRealType) GetPixelIndex(unsharp_indexes+x);
4762 if (fabs(2.0*pixel.index) < quantum_threshold)
4763 pixel.index=(MagickRealType) GetPixelIndex(indexes+x);
4765 pixel.index=(MagickRealType) GetPixelIndex(indexes+x)+
4767 SetPixelIndex(unsharp_indexes+x,ClampToQuantum(pixel.index));
4772 if (SyncCacheViewAuthenticPixels(unsharp_view,exception) == MagickFalse)
4774 if (image->progress_monitor != (MagickProgressMonitor) NULL)
4779#if defined(MAGICKCORE_OPENMP_SUPPORT)
4783 proceed=SetImageProgress(image,SharpenImageTag,progress,image->rows);
4784 if (proceed == MagickFalse)
4788 unsharp_image->type=image->type;
4789 unsharp_view=DestroyCacheView(unsharp_view);
4790 image_view=DestroyCacheView(image_view);
4791 if (status == MagickFalse)
4792 unsharp_image=DestroyImage(unsharp_image);
4793 return(unsharp_image);