44#include "magick/studio.h"
45#include "magick/accelerate-private.h"
46#include "magick/artifact.h"
47#include "magick/cache.h"
48#include "magick/cache-private.h"
49#include "magick/cache-view.h"
50#include "magick/color-private.h"
51#include "magick/delegate-private.h"
52#include "magick/enhance.h"
53#include "magick/exception.h"
54#include "magick/exception-private.h"
55#include "magick/gem.h"
56#include "magick/hashmap.h"
57#include "magick/image.h"
58#include "magick/image-private.h"
59#include "magick/list.h"
60#include "magick/memory_.h"
61#include "magick/monitor-private.h"
62#include "magick/opencl.h"
63#include "magick/opencl-private.h"
64#include "magick/option.h"
65#include "magick/pixel-private.h"
66#include "magick/prepress.h"
67#include "magick/quantize.h"
68#include "magick/random_.h"
69#include "magick/random-private.h"
70#include "magick/registry.h"
71#include "magick/resize.h"
72#include "magick/resize-private.h"
73#include "magick/semaphore.h"
74#include "magick/splay-tree.h"
75#include "magick/statistic.h"
76#include "magick/string_.h"
77#include "magick/string-private.h"
78#include "magick/token.h"
80#ifdef MAGICKCORE_CLPERFMARKER
81#include "CLPerfMarker.h"
84#define MAGICK_MAX(x,y) (((x) >= (y))?(x):(y))
85#define MAGICK_MIN(x,y) (((x) <= (y))?(x):(y))
87#if defined(MAGICKCORE_OPENCL_SUPPORT)
92#define ALIGNED(pointer,type) ((((size_t)(pointer)) & (sizeof(type)-1)) == 0)
97static const ResizeWeightingFunctionType supportedResizeWeighting[] =
100 TriangleWeightingFunction,
101 HanningWeightingFunction,
102 HammingWeightingFunction,
103 BlackmanWeightingFunction,
104 CubicBCWeightingFunction,
105 SincWeightingFunction,
106 SincFastWeightingFunction,
107 LastWeightingFunction
113static Image *ComputeUnsharpMaskImageSingle(
const Image *image,
114 const double radius,
const double sigma,
const double gain,
115 const double threshold,
int blurOnly,
ExceptionInfo *exception);
121static MagickBooleanType checkAccelerateCondition(
const Image* image,
122 const ChannelType channel)
125 if (image->storage_class != DirectClass)
129 if (image->colorspace != RGBColorspace &&
130 image->colorspace != sRGBColorspace &&
131 image->colorspace != LinearGRAYColorspace &&
132 image->colorspace != GRAYColorspace)
136 if (((channel & RedChannel) == 0) ||
137 ((channel & GreenChannel) == 0) ||
138 ((channel & BlueChannel) == 0))
142 if ((GetImageVirtualPixelMethod(image) != UndefinedVirtualPixelMethod) &&
143 (GetImageVirtualPixelMethod(image) != EdgeVirtualPixelMethod))
147 if ((image->clip_mask != (
Image *) NULL) || (image->mask != (
Image *) NULL))
153static MagickBooleanType checkHistogramCondition(
Image *image,
154 const ChannelType channel)
157 if ((channel & SyncChannels) == 0)
160 if (image->intensity == Rec601LuminancePixelIntensityMethod ||
161 image->intensity == Rec709LuminancePixelIntensityMethod)
164 if (image->colorspace != sRGBColorspace)
170static MagickBooleanType checkOpenCLEnvironment(
ExceptionInfo* exception)
178 clEnv=GetDefaultOpenCLEnv();
180 GetMagickOpenCLEnvParam(clEnv,MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED,
181 sizeof(MagickBooleanType),&flag,exception);
182 if (flag != MagickFalse)
185 GetMagickOpenCLEnvParam(clEnv,MAGICK_OPENCL_ENV_PARAM_OPENCL_INITIALIZED,
186 sizeof(MagickBooleanType),&flag,exception);
187 if (flag == MagickFalse)
189 if (InitOpenCLEnv(clEnv,exception) == MagickFalse)
192 GetMagickOpenCLEnvParam(clEnv,MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED,
193 sizeof(MagickBooleanType),&flag,exception);
194 if (flag != MagickFalse)
203inline static unsigned int padGlobalWorkgroupSizeToLocalWorkgroupSize(
204 const unsigned int orgGlobalSize,
const unsigned int localGroupSize)
206 return ((orgGlobalSize+(localGroupSize-1))/localGroupSize*localGroupSize);
209static MagickBooleanType paramMatchesValue(
MagickCLEnv clEnv,
210 MagickOpenCLEnvParam param,
const char *value,
ExceptionInfo *exception)
218 status=GetMagickOpenCLEnvParam(clEnv,param,
sizeof(val),&val,exception);
219 if (status != MagickFalse)
221 status=strcmp(value,val) == 0 ? MagickTrue : MagickFalse;
222 RelinquishMagickMemory(val);
239static Image *ComputeAddNoiseImage(
const Image *image,
240 const ChannelType channel,
const NoiseType noise_type,
288 **magick_restrict random_info;
296 numRandomNumberPerPixel;
298#if defined(MAGICKCORE_OPENMP_SUPPORT)
303 outputReady = MagickFalse;
305 filteredImage = NULL;
308 filteredImageBuffer = NULL;
310 addNoiseKernel = NULL;
312 clEnv = GetDefaultOpenCLEnv();
313 context = GetOpenCLContext(clEnv);
314 queue = AcquireOpenCLCommandQueue(clEnv);
316 filteredImage = CloneImage(image,0,0,MagickTrue,exception);
317 if (filteredImage == (
Image *) NULL)
320 imageBuffer = GetAuthenticOpenCLBuffer(image,exception);
321 if (imageBuffer == (cl_mem) NULL)
323 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
324 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
327 filteredImageBuffer = GetAuthenticOpenCLBuffer(filteredImage,exception);
328 if (filteredImageBuffer == (cl_mem) NULL)
330 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
331 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
336 numRandomNumberPerPixel = 0;
338 unsigned int numRandPerChannel = 0;
346 numRandPerChannel = 1;
349 case MultiplicativeGaussianNoise:
351 numRandPerChannel = 2;
355 if ((channel & RedChannel) != 0)
356 numRandomNumberPerPixel+=numRandPerChannel;
357 if ((channel & GreenChannel) != 0)
358 numRandomNumberPerPixel+=numRandPerChannel;
359 if ((channel & BlueChannel) != 0)
360 numRandomNumberPerPixel+=numRandPerChannel;
361 if ((channel & OpacityChannel) != 0)
362 numRandomNumberPerPixel+=numRandPerChannel;
367 option=GetImageArtifact(image,
"attenuate");
368 if (option != (
char *) NULL)
369 attenuate=StringToDouble(option,(
char **) NULL);
370 random_info=AcquireRandomInfoTLS();
371#if defined(MAGICKCORE_OPENMP_SUPPORT)
372 key=GetRandomSecretKey(random_info[0]);
376 addNoiseKernel = AcquireOpenCLKernel(clEnv,MAGICK_OPENCL_ACCELERATE,
"AddNoise");
379 cl_uint computeUnitCount;
380 cl_uint workItemCount;
381 clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_MAX_COMPUTE_UNITS,
sizeof(cl_uint), &computeUnitCount, NULL);
382 workItemCount = computeUnitCount * 2 * 256;
383 inputPixelCount = (cl_int) (image->columns * image->rows);
384 pixelsPerWorkitem = (inputPixelCount + workItemCount - 1) / workItemCount;
385 pixelsPerWorkitem = ((pixelsPerWorkitem + 3) / 4) * 4;
387 local_work_size[0] = 256;
388 global_work_size[0] = workItemCount;
392 const unsigned long* s = GetRandomInfoSeed(randomInfo);
394 GetPseudoRandomValue(randomInfo);
396 randomInfo = DestroyRandomInfo(randomInfo);
400 clEnv->library->clSetKernelArg(addNoiseKernel,k++,
sizeof(cl_mem),(
void *)&imageBuffer);
401 clEnv->library->clSetKernelArg(addNoiseKernel,k++,
sizeof(cl_mem),(
void *)&filteredImageBuffer);
402 clEnv->library->clSetKernelArg(addNoiseKernel,k++,
sizeof(cl_uint),(
void *)&inputPixelCount);
403 clEnv->library->clSetKernelArg(addNoiseKernel,k++,
sizeof(cl_uint),(
void *)&pixelsPerWorkitem);
404 clEnv->library->clSetKernelArg(addNoiseKernel,k++,
sizeof(ChannelType),(
void *)&channel);
405 clEnv->library->clSetKernelArg(addNoiseKernel,k++,
sizeof(NoiseType),(
void *)&noise_type);
407 option=GetImageArtifact(image,
"attenuate");
408 if (option != (
char *) NULL)
409 attenuate=(float)StringToDouble(option,(
char **) NULL);
410 clEnv->library->clSetKernelArg(addNoiseKernel,k++,
sizeof(
float),(
void *)&attenuate);
411 clEnv->library->clSetKernelArg(addNoiseKernel,k++,
sizeof(cl_uint),(
void *)&seed0);
412 clEnv->library->clSetKernelArg(addNoiseKernel,k++,
sizeof(cl_uint),(
void *)&seed1);
413 clEnv->library->clSetKernelArg(addNoiseKernel,k++,
sizeof(
unsigned int),(
void *)&numRandomNumberPerPixel);
415 events=GetOpenCLEvents(image,&event_count);
416 clStatus=clEnv->library->clEnqueueNDRangeKernel(queue,addNoiseKernel,1,NULL,global_work_size,NULL,event_count,events,&event);
417 events=(cl_event *) RelinquishMagickMemory(events);
418 if (clStatus != CL_SUCCESS)
420 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
423 if (RecordProfileData(clEnv,AddNoiseKernel,event) == MagickFalse)
425 AddOpenCLEvent(image,event);
426 AddOpenCLEvent(filteredImage,event);
428 clEnv->library->clReleaseEvent(event);
429 outputReady=MagickTrue;
432 OpenCLLogException(__FUNCTION__,__LINE__,exception);
434 if (imageBuffer != (cl_mem) NULL)
435 clEnv->library->clReleaseMemObject(imageBuffer);
436 if (filteredImageBuffer != (cl_mem) NULL)
437 clEnv->library->clReleaseMemObject(filteredImageBuffer);
438 if (queue!=NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
439 if (addNoiseKernel!=NULL) RelinquishOpenCLKernel(clEnv, addNoiseKernel);
440 if ((outputReady == MagickFalse) && (filteredImage != NULL))
441 filteredImage=(
Image *) DestroyImage(filteredImage);
443 return(filteredImage);
446MagickPrivate
Image *AccelerateAddNoiseImage(
const Image *image,
447 const ChannelType channel,
const NoiseType noise_type,
466 magick_unreferenced(image);
467 magick_unreferenced(channel);
468 magick_unreferenced(noise_type);
469 magick_unreferenced(exception);
470 return((
Image *)NULL);
485static Image *ComputeBlurImage(
const Image* image,
const ChannelType channel,
486 const double radius,
const double sigma,
ExceptionInfo *exception)
489 geometry[MaxTextExtent];
544 filteredImage = NULL;
546 tempImageBuffer = NULL;
547 filteredImageBuffer = NULL;
548 imageKernelBuffer = NULL;
549 blurRowKernel = NULL;
550 blurColumnKernel = NULL;
554 outputReady = MagickFalse;
556 clEnv = GetDefaultOpenCLEnv();
557 context = GetOpenCLContext(clEnv);
558 queue = AcquireOpenCLCommandQueue(clEnv);
560 filteredImage = CloneImage(image,0,0,MagickTrue,exception);
561 if (filteredImage == (
Image *) NULL)
564 imageBuffer = GetAuthenticOpenCLBuffer(image,exception);
565 if (imageBuffer == (cl_mem) NULL)
567 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
568 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
571 filteredImageBuffer = GetAuthenticOpenCLBuffer(filteredImage,exception);
572 if (filteredImageBuffer == (cl_mem) NULL)
574 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
575 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
581 (void) FormatLocaleString(geometry,MaxTextExtent,
"blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma);
582 kernel=AcquireKernelInfo(geometry);
585 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"MemoryAllocationFailed.",
".");
590 kernelBufferPtr = (
float *)AcquireMagickMemory(kernel->width *
sizeof(
float));
591 if (kernelBufferPtr == (
float *) NULL)
593 (void)OpenCLThrowMagickException(exception,GetMagickModule(),
594 ResourceLimitWarning,
"AcquireMagickMemory failed.",
"'%s'",
".");
597 for (i = 0; i < kernel->width; i++)
598 kernelBufferPtr[i] = (
float)kernel->values[i];
600 imageKernelBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, kernel->width *
sizeof(
float), kernelBufferPtr, &clStatus);
601 RelinquishMagickMemory(kernelBufferPtr);
602 if (clStatus != CL_SUCCESS)
604 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
614 length = image->columns * image->rows;
615 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length * 4 *
sizeof(
float), NULL, &clStatus);
616 if (clStatus != CL_SUCCESS)
618 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
625 blurRowKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"BlurRow");
626 if (blurRowKernel == NULL)
628 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
632 blurColumnKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"BlurColumn");
633 if (blurColumnKernel == NULL)
635 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
645 imageColumns = (
unsigned int) image->columns;
646 imageRows = (
unsigned int) image->rows;
650 clStatus=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
651 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(cl_mem),(
void *)&tempImageBuffer);
652 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(ChannelType),&channel);
653 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(cl_mem),(
void *)&imageKernelBuffer);
654 kernelWidth = (
unsigned int) kernel->width;
655 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(
unsigned int),(
void *)&kernelWidth);
656 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(
unsigned int),(
void *)&imageColumns);
657 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(
unsigned int),(
void *)&imageRows);
658 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(CLPixelPacket)*(chunkSize+kernel->width),(
void *) NULL);
659 if (clStatus != CL_SUCCESS)
661 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
671 gsize[0] = chunkSize*((image->columns+chunkSize-1)/chunkSize);
672 gsize[1] = image->rows;
673 wsize[0] = chunkSize;
676 events=GetOpenCLEvents(image,&event_count);
677 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurRowKernel, 2, NULL, gsize, wsize, event_count, events, &event);
678 events=(cl_event *) RelinquishMagickMemory(events);
679 if (clStatus != CL_SUCCESS)
681 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
684 if (RecordProfileData(clEnv,BlurRowKernel,event) == MagickFalse)
686 AddOpenCLEvent(image,event);
687 AddOpenCLEvent(filteredImage,event);
689 clEnv->library->clReleaseEvent(event);
698 imageColumns = (
unsigned int) image->columns;
699 imageRows = (
unsigned int) image->rows;
703 clStatus=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(cl_mem),(
void *)&tempImageBuffer);
704 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(cl_mem),(
void *)&filteredImageBuffer);
705 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(ChannelType),&channel);
706 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(cl_mem),(
void *)&imageKernelBuffer);
707 kernelWidth = (
unsigned int) kernel->width;
708 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(
unsigned int),(
void *)&kernelWidth);
709 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(
unsigned int),(
void *)&imageColumns);
710 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(
unsigned int),(
void *)&imageRows);
711 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(cl_float4)*(chunkSize+kernel->width),(
void *) NULL);
712 if (clStatus != CL_SUCCESS)
714 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
724 gsize[0] = image->columns;
725 gsize[1] = chunkSize*((image->rows+chunkSize-1)/chunkSize);
727 wsize[1] = chunkSize;
729 events=GetOpenCLEvents(image,&event_count);
730 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurColumnKernel, 2, NULL, gsize, wsize, event_count, events, &event);
731 events=(cl_event *) RelinquishMagickMemory(events);
732 if (clStatus != CL_SUCCESS)
734 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
737 if (RecordProfileData(clEnv,BlurColumnKernel,event) == MagickFalse)
739 AddOpenCLEvent(image,event);
740 AddOpenCLEvent(filteredImage,event);
742 clEnv->library->clReleaseEvent(event);
748 outputReady=MagickTrue;
751 OpenCLLogException(__FUNCTION__,__LINE__,exception);
753 if (imageBuffer != (cl_mem) NULL)
754 clEnv->library->clReleaseMemObject(imageBuffer);
755 if (filteredImageBuffer != (cl_mem) NULL)
756 clEnv->library->clReleaseMemObject(filteredImageBuffer);
757 if (tempImageBuffer!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer);
758 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer);
759 if (blurRowKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurRowKernel);
760 if (blurColumnKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurColumnKernel);
761 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
762 if (kernel!=NULL) DestroyKernelInfo(kernel);
763 if ((outputReady == MagickFalse) && (filteredImage != NULL))
764 filteredImage=(
Image *) DestroyImage(filteredImage);
765 return(filteredImage);
768MagickPrivate
Image* AccelerateBlurImage(
const Image *image,
769 const ChannelType channel,
const double radius,
const double sigma,
775 assert(image != NULL);
778 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
779 (checkAccelerateCondition(image, channel) == MagickFalse))
782 filteredImage=ComputeBlurImage(image, channel, radius, sigma, exception);
783 return(filteredImage);
798static MagickBooleanType LaunchCompositeKernel(
const Image *image,
799 MagickCLEnv clEnv,cl_command_queue queue,cl_mem imageBuffer,
800 const unsigned int inputWidth,
const unsigned int inputHeight,
801 const unsigned int inputMatte,
const ChannelType channel,
802 const CompositeOperator compose,
const cl_mem compositeImageBuffer,
803 const unsigned int compositeWidth,
const unsigned int compositeHeight,
804 const unsigned int compositeMatte,
const float destination_dissolve,
805 const float source_dissolve)
832 compositeKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
836 clStatus = clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(cl_mem), (
void*)&imageBuffer);
837 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(
unsigned int), (
void*)&inputWidth);
838 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(
unsigned int), (
void*)&inputHeight);
839 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(
unsigned int), (
void*)&inputMatte);
840 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(cl_mem), (
void*)&compositeImageBuffer);
841 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(
unsigned int), (
void*)&compositeWidth);
842 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(
unsigned int), (
void*)&compositeHeight);
843 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(
unsigned int), (
void*)&compositeMatte);
844 composeOp = (
unsigned int)compose;
845 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(
unsigned int), (
void*)&composeOp);
846 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(ChannelType), (
void*)&channel);
847 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(
float), (
void*)&destination_dissolve);
848 clStatus |= clEnv->library->clSetKernelArg(compositeKernel, k++,
sizeof(
float), (
void*)&source_dissolve);
850 if (clStatus != CL_SUCCESS)
853 local_work_size[0] = 64;
854 local_work_size[1] = 1;
856 global_work_size[0] = padGlobalWorkgroupSizeToLocalWorkgroupSize(inputWidth,
857 (
unsigned int)local_work_size[0]);
858 global_work_size[1] = inputHeight;
859 events=GetOpenCLEvents(image,&event_count);
860 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, compositeKernel, 2, NULL,
861 global_work_size, local_work_size, event_count, events, &event);
862 events=(cl_event *) RelinquishMagickMemory(events);
863 if (clStatus == CL_SUCCESS)
864 AddOpenCLEvent(image,event);
865 clEnv->library->clReleaseEvent(event);
867 RelinquishOpenCLKernel(clEnv, compositeKernel);
869 return((clStatus == CL_SUCCESS) ? MagickTrue : MagickFalse);
872static MagickBooleanType ComputeCompositeImage(
Image *image,
873 const ChannelType channel,
const CompositeOperator compose,
874 const Image *compositeImage,
const ssize_t magick_unused(x_offset),
875 const ssize_t magick_unused(y_offset),
const float destination_dissolve,
885 compositeImageBuffer,
895 magick_unreferenced(x_offset);
896 magick_unreferenced(y_offset);
898 status = MagickFalse;
899 outputReady = MagickFalse;
901 compositeImageBuffer = NULL;
903 clEnv = GetDefaultOpenCLEnv();
904 context = GetOpenCLContext(clEnv);
905 queue = AcquireOpenCLCommandQueue(clEnv);
907 imageBuffer = GetAuthenticOpenCLBuffer(image,exception);
908 if (imageBuffer == (cl_mem) NULL)
910 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
911 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
915 compositeImageBuffer = GetAuthenticOpenCLBuffer(compositeImage,exception);
916 if (compositeImageBuffer == (cl_mem) NULL)
918 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
919 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
923 status = LaunchCompositeKernel(image,clEnv, queue, imageBuffer,
924 (
unsigned int)image->columns,
925 (
unsigned int)image->rows,
926 (
unsigned int)image->matte,
927 channel, compose, compositeImageBuffer,
928 (
unsigned int)compositeImage->columns,
929 (
unsigned int)compositeImage->rows,
930 (
unsigned int)compositeImage->matte,
931 destination_dissolve, source_dissolve);
933 if (status == MagickFalse)
936 outputReady = MagickTrue;
940 if (imageBuffer != (cl_mem) NULL)
941 clEnv->library->clReleaseMemObject(imageBuffer);
942 if (compositeImageBuffer != (cl_mem) NULL)
943 clEnv->library->clReleaseMemObject(compositeImageBuffer);
945 RelinquishOpenCLCommandQueue(clEnv, queue);
950MagickPrivate MagickBooleanType AccelerateCompositeImage(
Image *image,
951 const ChannelType channel,
const CompositeOperator compose,
952 const Image *composite,
const ssize_t x_offset,
const ssize_t y_offset,
953 const float destination_dissolve,
const float source_dissolve,
959 assert(image != NULL);
962 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
963 (checkAccelerateCondition(image, channel) == MagickFalse))
970 || image->columns != composite->columns
971 || image->rows != composite->rows)
975 case ColorDodgeCompositeOp:
976 case BlendCompositeOp:
983 status = ComputeCompositeImage(image, channel, compose, composite,
984 x_offset, y_offset, destination_dissolve, source_dissolve, exception);
1001static MagickBooleanType ComputeContrastImage(
Image *image,
1035 global_work_size[2];
1041 outputReady = MagickFalse;
1045 filterKernel = NULL;
1048 clEnv = GetDefaultOpenCLEnv();
1049 context = GetOpenCLContext(clEnv);
1051 imageBuffer=GetAuthenticOpenCLBuffer(image,exception);
1052 if (imageBuffer == (cl_mem) NULL)
1054 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
1055 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
1059 filterKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"Contrast");
1060 if (filterKernel == NULL)
1062 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
1067 clStatus=clEnv->library->clSetKernelArg(filterKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
1069 uSharpen = (sharpen == MagickFalse)?0:1;
1070 clStatus|=clEnv->library->clSetKernelArg(filterKernel,i++,
sizeof(cl_uint),&uSharpen);
1071 if (clStatus != CL_SUCCESS)
1073 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
1077 global_work_size[0] = image->columns;
1078 global_work_size[1] = image->rows;
1080 queue = AcquireOpenCLCommandQueue(clEnv);
1081 events=GetOpenCLEvents(image,&event_count);
1082 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, filterKernel, 2, NULL, global_work_size, NULL, event_count, events, &event);
1083 events=(cl_event *) RelinquishMagickMemory(events);
1084 if (clStatus != CL_SUCCESS)
1086 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
1089 if (RecordProfileData(clEnv,ContrastKernel,event) == MagickFalse)
1090 AddOpenCLEvent(image,event);
1091 clEnv->library->clReleaseEvent(event);
1092 outputReady=MagickTrue;
1095 OpenCLLogException(__FUNCTION__,__LINE__,exception);
1098 if (imageBuffer != (cl_mem) NULL)
1099 clEnv->library->clReleaseMemObject(imageBuffer);
1100 if (filterKernel!=NULL) RelinquishOpenCLKernel(clEnv, filterKernel);
1101 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
1102 return(outputReady);
1105MagickPrivate MagickBooleanType AccelerateContrastImage(
Image *image,
1111 assert(image != NULL);
1114 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
1115 (checkAccelerateCondition(image, AllChannels) == MagickFalse))
1116 return(MagickFalse);
1118 status = ComputeContrastImage(image,sharpen,exception);
1134static MagickBooleanType LaunchHistogramKernel(
MagickCLEnv clEnv,
1135 cl_command_queue queue,cl_mem imageBuffer,cl_mem histogramBuffer,
1162 global_work_size[2];
1164 histogramKernel = NULL;
1166 outputReady = MagickFalse;
1167 method = image->intensity;
1168 colorspace = image->colorspace;
1171 histogramKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"Histogram");
1172 if (histogramKernel == NULL)
1174 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
1180 clStatus=clEnv->library->clSetKernelArg(histogramKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
1181 clStatus|=clEnv->library->clSetKernelArg(histogramKernel,i++,
sizeof(ChannelType),&channel);
1182 clStatus|=clEnv->library->clSetKernelArg(histogramKernel,i++,
sizeof(cl_int),&method);
1183 clStatus|=clEnv->library->clSetKernelArg(histogramKernel,i++,
sizeof(cl_int),&colorspace);
1184 clStatus|=clEnv->library->clSetKernelArg(histogramKernel,i++,
sizeof(cl_mem),(
void *)&histogramBuffer);
1185 if (clStatus != CL_SUCCESS)
1187 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
1192 global_work_size[0] = image->columns;
1193 global_work_size[1] = image->rows;
1195 events=GetOpenCLEvents(image,&event_count);
1196 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, histogramKernel, 2, NULL, global_work_size, NULL, event_count, events, &event);
1197 events=(cl_event *) RelinquishMagickMemory(events);
1199 if (clStatus != CL_SUCCESS)
1201 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
1204 if (RecordProfileData(clEnv,HistogramKernel,event) == MagickFalse)
1205 AddOpenCLEvent(image,event);
1206 clEnv->library->clReleaseEvent(event);
1208 outputReady = MagickTrue;
1211 OpenCLLogException(__FUNCTION__,__LINE__,exception);
1213 if (histogramKernel!=NULL)
1214 RelinquishOpenCLKernel(clEnv, histogramKernel);
1216 return(outputReady);
1219MagickPrivate MagickBooleanType ComputeContrastStretchImageChannel(
Image *image,
1220 const ChannelType channel,
const double black_point,
const double white_point,
1223#define ContrastStretchImageTag "ContrastStretch/Image"
1224#define MaxRange(color) ((MagickRealType) ScaleQuantumToMap((Quantum) (color)))
1279 global_work_size[2];
1284 histogramBuffer = NULL;
1285 stretchMapBuffer = NULL;
1286 histogramKernel = NULL;
1287 stretchKernel = NULL;
1290 outputReady = MagickFalse;
1293 assert(image != (
Image *) NULL);
1294 assert(image->signature == MagickCoreSignature);
1295 if (IsEventLogging() != MagickFalse)
1296 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
1303 clEnv = GetDefaultOpenCLEnv();
1304 context = GetOpenCLContext(clEnv);
1305 queue = AcquireOpenCLCommandQueue(clEnv);
1310 length = (MaxMap+1);
1311 histogram=(cl_uint4 *) AcquireQuantumMemory(length,
sizeof(*histogram));
1313 if (histogram == (cl_uint4 *) NULL)
1314 ThrowBinaryException(ResourceLimitError,
"MemoryAllocationFailed", image->filename);
1317 (void) memset(histogram,0,length*
sizeof(*histogram));
1326 imageBuffer=GetAuthenticOpenCLBuffer(image,exception);
1327 if (imageBuffer == (cl_mem) NULL)
1329 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
1330 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
1335 histogramBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, length *
sizeof(cl_uint4), histogram, &clStatus);
1336 if (clStatus != CL_SUCCESS)
1338 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
1342 status = LaunchHistogramKernel(clEnv, queue, imageBuffer, histogramBuffer, image, channel, exception);
1343 if (status == MagickFalse)
1347 events=GetOpenCLEvents(image,&event_count);
1348 clEnv->library->clEnqueueMapBuffer(queue, histogramBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length *
sizeof(cl_uint4), event_count, events, NULL, &clStatus);
1349 events=(cl_event *) RelinquishMagickMemory(events);
1350 if (clStatus != CL_SUCCESS)
1352 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"Reading output image from CL buffer failed.",
"'%s'",
".");
1357 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, histogramBuffer, histogram, 0, NULL, NULL);
1358 if (clStatus != CL_SUCCESS)
1360 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueUnmapMemObject failed.",
"'%s'",
".");
1369 white.z=MaxRange(QuantumRange);
1370 if ((channel & RedChannel) != 0)
1373 for (i=0; i <= (ssize_t) MaxMap; i++)
1375 intensity+=histogram[i].s[2];
1376 if (intensity > black_point)
1379 black.z=(MagickRealType) i;
1381 for (i=(ssize_t) MaxMap; i != 0; i--)
1383 intensity+=histogram[i].s[2];
1384 if (intensity > ((
double) image->columns*image->rows-white_point))
1387 white.z=(MagickRealType) i;
1390 white.y=MaxRange(QuantumRange);
1391 if ((channel & GreenChannel) != 0)
1394 for (i=0; i <= (ssize_t) MaxMap; i++)
1396 intensity+=histogram[i].s[2];
1397 if (intensity > black_point)
1400 black.y=(MagickRealType) i;
1402 for (i=(ssize_t) MaxMap; i != 0; i--)
1404 intensity+=histogram[i].s[2];
1405 if (intensity > ((
double) image->columns*image->rows-white_point))
1408 white.y=(MagickRealType) i;
1411 white.x=MaxRange(QuantumRange);
1412 if ((channel & BlueChannel) != 0)
1415 for (i=0; i <= (ssize_t) MaxMap; i++)
1417 intensity+=histogram[i].s[2];
1418 if (intensity > black_point)
1421 black.x=(MagickRealType) i;
1423 for (i=(ssize_t) MaxMap; i != 0; i--)
1425 intensity+=histogram[i].s[2];
1426 if (intensity > ((
double) image->columns*image->rows-white_point))
1429 white.x=(MagickRealType) i;
1432 white.w=MaxRange(QuantumRange);
1433 if ((channel & OpacityChannel) != 0)
1436 for (i=0; i <= (ssize_t) MaxMap; i++)
1438 intensity+=histogram[i].s[2];
1439 if (intensity > black_point)
1442 black.w=(MagickRealType) i;
1444 for (i=(ssize_t) MaxMap; i != 0; i--)
1446 intensity+=histogram[i].s[2];
1447 if (intensity > ((
double) image->columns*image->rows-white_point))
1450 white.w=(MagickRealType) i;
1477 stretch_map=(
PixelPacket *) AcquireQuantumMemory(length,
1478 sizeof(*stretch_map));
1481 ThrowBinaryException(ResourceLimitError,
"MemoryAllocationFailed",
1487 (void) memset(stretch_map,0,length*
sizeof(*stretch_map));
1488 for (i=0; i <= (ssize_t) MaxMap; i++)
1490 if ((channel & RedChannel) != 0)
1492 if (i < (ssize_t) black.z)
1493 stretch_map[i].red=(Quantum) 0;
1495 if (i > (ssize_t) white.z)
1496 stretch_map[i].red=QuantumRange;
1498 if (black.z != white.z)
1499 stretch_map[i].red=ScaleMapToQuantum((MagickRealType) (MaxMap*
1500 (i-black.z)/(white.z-black.z)));
1502 if ((channel & GreenChannel) != 0)
1504 if (i < (ssize_t) black.y)
1505 stretch_map[i].green=0;
1507 if (i > (ssize_t) white.y)
1508 stretch_map[i].green=QuantumRange;
1510 if (black.y != white.y)
1511 stretch_map[i].green=ScaleMapToQuantum((MagickRealType) (MaxMap*
1512 (i-black.y)/(white.y-black.y)));
1514 if ((channel & BlueChannel) != 0)
1516 if (i < (ssize_t) black.x)
1517 stretch_map[i].blue=0;
1519 if (i > (ssize_t) white.x)
1520 stretch_map[i].blue= QuantumRange;
1522 if (black.x != white.x)
1523 stretch_map[i].blue=ScaleMapToQuantum((MagickRealType) (MaxMap*
1524 (i-black.x)/(white.x-black.x)));
1526 if ((channel & OpacityChannel) != 0)
1528 if (i < (ssize_t) black.w)
1529 stretch_map[i].opacity=0;
1531 if (i > (ssize_t) white.w)
1532 stretch_map[i].opacity=QuantumRange;
1534 if (black.w != white.w)
1535 stretch_map[i].opacity=ScaleMapToQuantum((MagickRealType) (MaxMap*
1536 (i-black.w)/(white.w-black.w)));
1558 if (((channel & OpacityChannel) != 0) || (((channel & IndexChannel) != 0) &&
1559 (image->colorspace == CMYKColorspace)))
1560 image->storage_class=DirectClass;
1561 if (image->storage_class == PseudoClass)
1566 for (i=0; i < (ssize_t) image->colors; i++)
1568 if ((channel & RedChannel) != 0)
1570 if (black.z != white.z)
1571 image->colormap[i].red=stretch_map[
1572 ScaleQuantumToMap(image->colormap[i].red)].red;
1574 if ((channel & GreenChannel) != 0)
1576 if (black.y != white.y)
1577 image->colormap[i].green=stretch_map[
1578 ScaleQuantumToMap(image->colormap[i].green)].green;
1580 if ((channel & BlueChannel) != 0)
1582 if (black.x != white.x)
1583 image->colormap[i].blue=stretch_map[
1584 ScaleQuantumToMap(image->colormap[i].blue)].blue;
1586 if ((channel & OpacityChannel) != 0)
1588 if (black.w != white.w)
1589 image->colormap[i].opacity=stretch_map[
1590 ScaleQuantumToMap(image->colormap[i].opacity)].opacity;
1597 stretchMapBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR, length, stretch_map, &clStatus);
1598 if (clStatus != CL_SUCCESS)
1600 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
1605 stretchKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"ContrastStretch");
1606 if (stretchKernel == NULL)
1608 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
1614 clStatus=clEnv->library->clSetKernelArg(stretchKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
1615 clStatus|=clEnv->library->clSetKernelArg(stretchKernel,i++,
sizeof(ChannelType),&channel);
1616 clStatus|=clEnv->library->clSetKernelArg(stretchKernel,i++,
sizeof(cl_mem),(
void *)&stretchMapBuffer);
1617 clStatus|=clEnv->library->clSetKernelArg(stretchKernel,i++,
sizeof(cl_float4),&white);
1618 clStatus|=clEnv->library->clSetKernelArg(stretchKernel,i++,
sizeof(cl_float4),&black);
1619 if (clStatus != CL_SUCCESS)
1621 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
1626 global_work_size[0] = image->columns;
1627 global_work_size[1] = image->rows;
1629 events=GetOpenCLEvents(image,&event_count);
1630 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, stretchKernel, 2, NULL, global_work_size, NULL, event_count, events, &event);
1631 events=(cl_event *) RelinquishMagickMemory(events);
1633 if (clStatus != CL_SUCCESS)
1635 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
1639 if (RecordProfileData(clEnv,ContrastStretchKernel,event) == MagickFalse)
1640 AddOpenCLEvent(image, event);
1641 clEnv->library->clReleaseEvent(event);
1643 outputReady=MagickTrue;
1646 OpenCLLogException(__FUNCTION__,__LINE__,exception);
1648 if (imageBuffer != (cl_mem) NULL)
1649 clEnv->library->clReleaseMemObject(imageBuffer);
1651 if (stretchMapBuffer!=NULL)
1652 clEnv->library->clReleaseMemObject(stretchMapBuffer);
1653 if (stretch_map!=NULL)
1654 stretch_map=(
PixelPacket *) RelinquishMagickMemory(stretch_map);
1657 if (histogramBuffer!=NULL)
1658 clEnv->library->clReleaseMemObject(histogramBuffer);
1659 if (histogram!=NULL)
1660 histogram=(cl_uint4 *) RelinquishMagickMemory(histogram);
1663 if (histogramKernel!=NULL)
1664 RelinquishOpenCLKernel(clEnv, histogramKernel);
1665 if (stretchKernel!=NULL)
1666 RelinquishOpenCLKernel(clEnv, stretchKernel);
1669 RelinquishOpenCLCommandQueue(clEnv, queue);
1671 return(outputReady);
1674MagickPrivate MagickBooleanType AccelerateContrastStretchImageChannel(
1675 Image *image,
const ChannelType channel,
const double black_point,
1681 assert(image != NULL);
1684 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
1685 (checkAccelerateCondition(image, channel) == MagickFalse) ||
1686 (checkHistogramCondition(image, channel) == MagickFalse))
1687 return(MagickFalse);
1689 status=ComputeContrastStretchImageChannel(image,channel, black_point, white_point, exception);
1705static Image *ComputeConvolveImage(
const Image* image,
1725 filteredImageBuffer,
1732 deviceLocalMemorySize;
1750 global_work_size[3],
1752 localMemoryRequirement;
1768 filteredImageBuffer = NULL;
1769 convolutionKernel = NULL;
1773 filteredImage = NULL;
1774 outputReady = MagickFalse;
1776 clEnv = GetDefaultOpenCLEnv();
1778 context = GetOpenCLContext(clEnv);
1780 filteredImage = CloneImage(image,0,0,MagickTrue,exception);
1781 if (filteredImage == (
Image *) NULL)
1784 imageBuffer = GetAuthenticOpenCLBuffer(image,exception);
1785 if (imageBuffer == (cl_mem) NULL)
1787 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
1788 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
1791 filteredImageBuffer=GetAuthenticOpenCLBuffer(filteredImage,exception);
1792 if (filteredImageBuffer == (cl_mem) NULL)
1794 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
1795 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
1799 kernelSize = (
unsigned int) (kernel->width * kernel->height);
1800 convolutionKernel = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, kernelSize *
sizeof(
float), NULL, &clStatus);
1801 if (clStatus != CL_SUCCESS)
1803 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
1807 queue = AcquireOpenCLCommandQueue(clEnv);
1809 kernelBufferPtr = (
float*)clEnv->library->clEnqueueMapBuffer(queue, convolutionKernel, CL_TRUE, CL_MAP_WRITE, 0, kernelSize *
sizeof(
float)
1810 , 0, NULL, NULL, &clStatus);
1811 if (clStatus != CL_SUCCESS)
1813 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueMapBuffer failed.",
".");
1816 for (i = 0; i < kernelSize; i++)
1818 kernelBufferPtr[i] = (float) kernel->values[i];
1820 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, convolutionKernel, kernelBufferPtr, 0, NULL, NULL);
1821 if (clStatus != CL_SUCCESS)
1823 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueUnmapMemObject failed.",
"'%s'",
".");
1827 deviceLocalMemorySize = GetOpenCLDeviceLocalMemorySize(clEnv);
1831 localGroupSize[0] = 16;
1832 localGroupSize[1] = 16;
1833 localMemoryRequirement = (localGroupSize[0]+kernel->width-1) * (localGroupSize[1]+kernel->height-1) *
sizeof(CLPixelPacket)
1834 + kernel->width*kernel->height*
sizeof(
float);
1836 if (localMemoryRequirement > deviceLocalMemorySize)
1838 localGroupSize[0] = 8;
1839 localGroupSize[1] = 8;
1840 localMemoryRequirement = (localGroupSize[0]+kernel->width-1) * (localGroupSize[1]+kernel->height-1) *
sizeof(CLPixelPacket)
1841 + kernel->width*kernel->height*
sizeof(
float);
1843 if (localMemoryRequirement <= deviceLocalMemorySize)
1846 clkernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"ConvolveOptimized");
1847 if (clkernel == NULL)
1849 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
1855 clStatus =clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
1856 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(cl_mem),(
void *)&filteredImageBuffer);
1857 imageWidth = (
unsigned int) image->columns;
1858 imageHeight = (
unsigned int) image->rows;
1859 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&imageWidth);
1860 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&imageHeight);
1861 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(cl_mem),(
void *)&convolutionKernel);
1862 filterWidth = (
unsigned int) kernel->width;
1863 filterHeight = (
unsigned int) kernel->height;
1864 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&filterWidth);
1865 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&filterHeight);
1866 matte = (image->matte==MagickTrue)?1:0;
1867 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&matte);
1868 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(ChannelType),(
void *)&channel);
1869 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++, (localGroupSize[0] + kernel->width-1)*(localGroupSize[1] + kernel->height-1)*
sizeof(CLPixelPacket),NULL);
1870 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++, kernel->width*kernel->height*
sizeof(
float),NULL);
1871 if (clStatus != CL_SUCCESS)
1873 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
1878 global_work_size[0] = ((image->columns + localGroupSize[0] - 1)/localGroupSize[0] ) * localGroupSize[0] ;
1879 global_work_size[1] = ((image->rows + localGroupSize[1] - 1)/localGroupSize[1]) * localGroupSize[1];
1882 events = GetOpenCLEvents(image, &event_count);
1883 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, clkernel, 2, NULL, global_work_size, localGroupSize, event_count, events, &event);
1884 events=(cl_event *) RelinquishMagickMemory(events);
1885 if (clStatus != CL_SUCCESS)
1887 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
1890 if (RecordProfileData(clEnv,ConvolveKernel,event) == MagickFalse)
1892 AddOpenCLEvent(image, event);
1893 AddOpenCLEvent(filteredImage, event);
1895 clEnv->library->clReleaseEvent(event);
1900 clkernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"Convolve");
1901 if (clkernel == NULL)
1903 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
1909 clStatus =clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
1910 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(cl_mem),(
void *)&filteredImageBuffer);
1911 imageWidth = (
unsigned int) image->columns;
1912 imageHeight = (
unsigned int) image->rows;
1913 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&imageWidth);
1914 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&imageHeight);
1915 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(cl_mem),(
void *)&convolutionKernel);
1916 filterWidth = (
unsigned int) kernel->width;
1917 filterHeight = (
unsigned int) kernel->height;
1918 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&filterWidth);
1919 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&filterHeight);
1920 matte = (image->matte==MagickTrue)?1:0;
1921 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&matte);
1922 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(ChannelType),(
void *)&channel);
1923 if (clStatus != CL_SUCCESS)
1925 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
1929 localGroupSize[0] = 8;
1930 localGroupSize[1] = 8;
1931 global_work_size[0] = (image->columns + (localGroupSize[0]-1))/localGroupSize[0] * localGroupSize[0];
1932 global_work_size[1] = (image->rows + (localGroupSize[1]-1))/localGroupSize[1] * localGroupSize[1];
1933 events=GetOpenCLEvents(image,&event_count);
1934 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, clkernel, 2, NULL, global_work_size, localGroupSize, event_count, events, &event);
1935 events=(cl_event *) RelinquishMagickMemory(events);
1937 if (clStatus != CL_SUCCESS)
1939 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
1942 if (RecordProfileData(clEnv,ConvolveKernel,event) == MagickFalse)
1944 AddOpenCLEvent(image,event);
1945 AddOpenCLEvent(filteredImage,event);
1947 clEnv->library->clReleaseEvent(event);
1950 outputReady = MagickTrue;
1953 OpenCLLogException(__FUNCTION__,__LINE__,exception);
1955 if (imageBuffer != (cl_mem) NULL)
1956 clEnv->library->clReleaseMemObject(imageBuffer);
1958 if (filteredImageBuffer != (cl_mem) NULL)
1959 clEnv->library->clReleaseMemObject(filteredImageBuffer);
1961 if (convolutionKernel != NULL)
1962 clEnv->library->clReleaseMemObject(convolutionKernel);
1964 if (clkernel != NULL)
1965 RelinquishOpenCLKernel(clEnv, clkernel);
1968 RelinquishOpenCLCommandQueue(clEnv, queue);
1970 if ((outputReady == MagickFalse) && (filteredImage != NULL))
1971 filteredImage=(
Image *) DestroyImage(filteredImage);
1973 return(filteredImage);
1976MagickPrivate
Image *AccelerateConvolveImageChannel(
const Image *image,
1982 assert(image != NULL);
1986 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
1987 (checkAccelerateCondition(image, channel) == MagickFalse))
1990 filteredImage=ComputeConvolveImage(image, channel, kernel, exception);
1991 return(filteredImage);
2006static Image *ComputeDespeckleImage(
const Image *image,
2010 X[4] = {0, 1, 1,-1},
2011 Y[4] = {1, 0, 1, 1};
2030 filteredImageBuffer,
2054 global_work_size[2];
2060 outputReady = MagickFalse;
2062 filteredImage = NULL;
2065 filteredImageBuffer = NULL;
2069 tempImageBuffer[0] = tempImageBuffer[1] = NULL;
2070 clEnv = GetDefaultOpenCLEnv();
2071 context = GetOpenCLContext(clEnv);
2072 queue = AcquireOpenCLCommandQueue(clEnv);
2075 filteredImage = CloneImage(image,0,0,MagickTrue,exception);
2076 if (filteredImage == (
Image *) NULL)
2079 imageBuffer = GetAuthenticOpenCLBuffer(image, exception);
2080 if (imageBuffer == (cl_mem) NULL)
2082 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
2083 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
2086 filteredImageBuffer = GetAuthenticOpenCLBuffer(filteredImage, exception);
2087 if (filteredImageBuffer == (cl_mem) NULL)
2089 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
2090 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
2094 hullPass1 = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"HullPass1");
2095 hullPass2 = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"HullPass2");
2097 clStatus =clEnv->library->clSetKernelArg(hullPass1,0,
sizeof(cl_mem),(
void *)&imageBuffer);
2098 clStatus |=clEnv->library->clSetKernelArg(hullPass1,1,
sizeof(cl_mem),(
void *)(tempImageBuffer+1));
2099 imageWidth = (
unsigned int) image->columns;
2100 clStatus |=clEnv->library->clSetKernelArg(hullPass1,2,
sizeof(
unsigned int),(
void *)&imageWidth);
2101 imageHeight = (
unsigned int) image->rows;
2102 clStatus |=clEnv->library->clSetKernelArg(hullPass1,3,
sizeof(
unsigned int),(
void *)&imageHeight);
2103 matte = (image->matte==MagickFalse)?0:1;
2104 clStatus |=clEnv->library->clSetKernelArg(hullPass1,6,
sizeof(
int),(
void *)&matte);
2105 if (clStatus != CL_SUCCESS)
2107 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
2111 clStatus = clEnv->library->clSetKernelArg(hullPass2,0,
sizeof(cl_mem),(
void *)(tempImageBuffer+1));
2112 clStatus |=clEnv->library->clSetKernelArg(hullPass2,1,
sizeof(cl_mem),(
void *)tempImageBuffer);
2113 imageWidth = (
unsigned int) image->columns;
2114 clStatus |=clEnv->library->clSetKernelArg(hullPass2,2,
sizeof(
unsigned int),(
void *)&imageWidth);
2115 imageHeight = (
unsigned int) image->rows;
2116 clStatus |=clEnv->library->clSetKernelArg(hullPass2,3,
sizeof(
unsigned int),(
void *)&imageHeight);
2117 matte = (image->matte==MagickFalse)?0:1;
2118 clStatus |=clEnv->library->clSetKernelArg(hullPass2,6,
sizeof(
int),(
void *)&matte);
2119 if (clStatus != CL_SUCCESS)
2121 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
2126 global_work_size[0] = image->columns;
2127 global_work_size[1] = image->rows;
2129 events=GetOpenCLEvents(image,&event_count);
2130 for (k = 0; k < 4; k++)
2139 clStatus = clEnv->library->clSetKernelArg(hullPass1,4,
sizeof(cl_int2),(
void *)&offset);
2140 clStatus|= clEnv->library->clSetKernelArg(hullPass1,5,
sizeof(
int),(
void *)&polarity);
2141 clStatus|=clEnv->library->clSetKernelArg(hullPass2,4,
sizeof(cl_int2),(
void *)&offset);
2142 clStatus|=clEnv->library->clSetKernelArg(hullPass2,5,
sizeof(
int),(
void *)&polarity);
2143 if (clStatus != CL_SUCCESS)
2145 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
2149 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass1, 2, NULL, global_work_size, NULL, event_count, events, &event);
2150 if (clStatus != CL_SUCCESS)
2152 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2155 RecordProfileData(clEnv,HullPass1Kernel,event);
2156 clEnv->library->clReleaseEvent(event);
2158 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass2, 2, NULL, global_work_size, NULL, event_count, events, &event);
2159 if (clStatus != CL_SUCCESS)
2161 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2164 RecordProfileData(clEnv,HullPass2Kernel,event);
2165 clEnv->library->clReleaseEvent(event);
2169 clStatus =clEnv->library->clSetKernelArg(hullPass1,0,
sizeof(cl_mem),(
void *)(tempImageBuffer));
2170 offset.s[0] = -X[k];
2171 offset.s[1] = -Y[k];
2173 clStatus = clEnv->library->clSetKernelArg(hullPass1,4,
sizeof(cl_int2),(
void *)&offset);
2174 clStatus|= clEnv->library->clSetKernelArg(hullPass1,5,
sizeof(
int),(
void *)&polarity);
2175 clStatus|=clEnv->library->clSetKernelArg(hullPass2,4,
sizeof(cl_int2),(
void *)&offset);
2176 clStatus|=clEnv->library->clSetKernelArg(hullPass2,5,
sizeof(
int),(
void *)&polarity);
2177 if (clStatus != CL_SUCCESS)
2179 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
2183 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass1, 2, NULL, global_work_size, NULL, event_count, events, &event);
2184 if (clStatus != CL_SUCCESS)
2186 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2189 RecordProfileData(clEnv,HullPass1Kernel,event);
2190 clEnv->library->clReleaseEvent(event);
2192 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass2, 2, NULL, global_work_size, NULL, event_count, events, &event);
2193 if (clStatus != CL_SUCCESS)
2195 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2198 RecordProfileData(clEnv,HullPass2Kernel,event);
2199 clEnv->library->clReleaseEvent(event);
2201 offset.s[0] = -X[k];
2202 offset.s[1] = -Y[k];
2204 clStatus = clEnv->library->clSetKernelArg(hullPass1,4,
sizeof(cl_int2),(
void *)&offset);
2205 clStatus|= clEnv->library->clSetKernelArg(hullPass1,5,
sizeof(
int),(
void *)&polarity);
2206 clStatus|=clEnv->library->clSetKernelArg(hullPass2,4,
sizeof(cl_int2),(
void *)&offset);
2207 clStatus|=clEnv->library->clSetKernelArg(hullPass2,5,
sizeof(
int),(
void *)&polarity);
2208 if (clStatus != CL_SUCCESS)
2210 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
2214 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass1, 2, NULL, global_work_size, NULL, event_count, events, &event);
2215 if (clStatus != CL_SUCCESS)
2217 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2220 RecordProfileData(clEnv,HullPass1Kernel,event);
2221 clEnv->library->clReleaseEvent(event);
2223 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass2, 2, NULL, global_work_size, NULL, event_count, events, &event);
2224 if (clStatus != CL_SUCCESS)
2226 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2229 RecordProfileData(clEnv,HullPass2Kernel,event);
2230 clEnv->library->clReleaseEvent(event);
2235 clStatus = clEnv->library->clSetKernelArg(hullPass1,4,
sizeof(cl_int2),(
void *)&offset);
2236 clStatus|= clEnv->library->clSetKernelArg(hullPass1,5,
sizeof(
int),(
void *)&polarity);
2237 clStatus|=clEnv->library->clSetKernelArg(hullPass2,4,
sizeof(cl_int2),(
void *)&offset);
2238 clStatus|=clEnv->library->clSetKernelArg(hullPass2,5,
sizeof(
int),(
void *)&polarity);
2241 clStatus |=clEnv->library->clSetKernelArg(hullPass2,1,
sizeof(cl_mem),(
void *)&filteredImageBuffer);
2243 if (clStatus != CL_SUCCESS)
2245 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
2249 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass1, 2, NULL, global_work_size, NULL, event_count, events, &event);
2250 if (clStatus != CL_SUCCESS)
2252 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2255 RecordProfileData(clEnv,HullPass1Kernel,event);
2256 clEnv->library->clReleaseEvent(event);
2258 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass2, 2, NULL, global_work_size, NULL, event_count, events, &event);
2259 if (clStatus != CL_SUCCESS)
2261 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2264 if ((k == 3) && (RecordProfileData(clEnv,HullPass2Kernel,event) == MagickFalse))
2266 AddOpenCLEvent(image,event);
2267 AddOpenCLEvent(filteredImage,event);
2269 clEnv->library->clReleaseEvent(event);
2272 outputReady=MagickTrue;
2275 OpenCLLogException(__FUNCTION__,__LINE__,exception);
2277 if (imageBuffer != (cl_mem) NULL)
2278 clEnv->library->clReleaseMemObject(imageBuffer);
2279 if (filteredImageBuffer != (cl_mem) NULL)
2280 clEnv->library->clReleaseMemObject(filteredImageBuffer);
2281 events=(cl_event *) RelinquishMagickMemory(events);
2282 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
2283 for (k = 0; k < 2; k++)
2285 if (tempImageBuffer[k]!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer[k]);
2287 if (hullPass1!=NULL) RelinquishOpenCLKernel(clEnv, hullPass1);
2288 if (hullPass2!=NULL) RelinquishOpenCLKernel(clEnv, hullPass2);
2289 if ((outputReady == MagickFalse) && (filteredImage != NULL))
2290 filteredImage=(
Image *) DestroyImage(filteredImage);
2291 return(filteredImage);
2294MagickPrivate
Image *AccelerateDespeckleImage(
const Image* image,
2300 assert(image != NULL);
2303 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
2304 (checkAccelerateCondition(image, AllChannels) == MagickFalse))
2307 filteredImage=ComputeDespeckleImage(image,exception);
2308 return(filteredImage);
2323MagickPrivate MagickBooleanType ComputeEqualizeImage(
Image *image,
2326#define EqualizeImageTag "Equalize/Image"
2381 global_work_size[2];
2387 histogramBuffer = NULL;
2388 equalizeMapBuffer = NULL;
2389 histogramKernel = NULL;
2390 equalizeKernel = NULL;
2393 outputReady = MagickFalse;
2395 assert(image != (
Image *) NULL);
2396 assert(image->signature == MagickCoreSignature);
2397 if (IsEventLogging() != MagickFalse)
2398 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2403 clEnv = GetDefaultOpenCLEnv();
2404 context = GetOpenCLContext(clEnv);
2405 queue = AcquireOpenCLCommandQueue(clEnv);
2411 histogram=(cl_uint4 *) AcquireQuantumMemory(length,
sizeof(*histogram));
2412 if (histogram == (cl_uint4 *) NULL)
2413 ThrowBinaryException(ResourceLimitWarning,
"MemoryAllocationFailed", image->filename);
2416 (void) memset(histogram,0,length*
sizeof(*histogram));
2418 imageBuffer = GetAuthenticOpenCLBuffer(image, exception);
2419 if (imageBuffer == (cl_mem) NULL)
2421 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
2422 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
2427 histogramBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, length *
sizeof(cl_uint4), histogram, &clStatus);
2428 if (clStatus != CL_SUCCESS)
2430 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
2434 status = LaunchHistogramKernel(clEnv, queue, imageBuffer, histogramBuffer, image, channel, exception);
2435 if (status == MagickFalse)
2439 events=GetOpenCLEvents(image,&event_count);
2440 clEnv->library->clEnqueueMapBuffer(queue, histogramBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length *
sizeof(cl_uint4), event_count, events, NULL, &clStatus);
2441 events=(cl_event *) RelinquishMagickMemory(events);
2442 if (clStatus != CL_SUCCESS)
2444 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"Reading output image from CL buffer failed.",
"'%s'",
".");
2449 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, histogramBuffer, histogram, 0, NULL, NULL);
2450 if (clStatus != CL_SUCCESS)
2452 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueUnmapMemObject failed.",
"'%s'",
".");
2457 equalize_map=(
PixelPacket *) AcquireQuantumMemory(length,
sizeof(*equalize_map));
2459 ThrowBinaryException(ResourceLimitWarning,
"MemoryAllocationFailed", image->filename);
2461 map=(cl_float4 *) AcquireQuantumMemory(length,
sizeof(*map));
2462 if (map == (cl_float4 *) NULL)
2463 ThrowBinaryException(ResourceLimitWarning,
"MemoryAllocationFailed", image->filename);
2468 (void) memset(&intensity,0,
sizeof(intensity));
2469 for (i=0; i <= (ssize_t) MaxMap; i++)
2471 if ((channel & SyncChannels) != 0)
2473 intensity.z+=histogram[i].s[2];
2477 if ((channel & RedChannel) != 0)
2478 intensity.z+=histogram[i].s[2];
2479 if ((channel & GreenChannel) != 0)
2480 intensity.y+=histogram[i].s[1];
2481 if ((channel & BlueChannel) != 0)
2482 intensity.x+=histogram[i].s[0];
2483 if ((channel & OpacityChannel) != 0)
2484 intensity.w+=histogram[i].s[3];
2495 white=map[(int) MaxMap];
2496 (void) memset(equalize_map,0,length*
sizeof(*equalize_map));
2497 for (i=0; i <= (ssize_t) MaxMap; i++)
2499 if ((channel & SyncChannels) != 0)
2501 if (white.z != black.z)
2502 equalize_map[i].red=ScaleMapToQuantum((MagickRealType) ((MaxMap*
2503 (map[i].z-black.z))/(white.z-black.z)));
2506 if (((channel & RedChannel) != 0) && (white.z != black.z))
2507 equalize_map[i].red=ScaleMapToQuantum((MagickRealType) ((MaxMap*
2508 (map[i].z-black.z))/(white.z-black.z)));
2509 if (((channel & GreenChannel) != 0) && (white.y != black.y))
2510 equalize_map[i].green=ScaleMapToQuantum((MagickRealType) ((MaxMap*
2511 (map[i].y-black.y))/(white.y-black.y)));
2512 if (((channel & BlueChannel) != 0) && (white.x != black.x))
2513 equalize_map[i].blue=ScaleMapToQuantum((MagickRealType) ((MaxMap*
2514 (map[i].x-black.x))/(white.x-black.x)));
2515 if (((channel & OpacityChannel) != 0) && (white.w != black.w))
2516 equalize_map[i].opacity=ScaleMapToQuantum((MagickRealType) ((MaxMap*
2517 (map[i].w-black.w))/(white.w-black.w)));
2527 if (image->storage_class == PseudoClass)
2532 for (i=0; i < (ssize_t) image->colors; i++)
2534 if ((channel & SyncChannels) != 0)
2536 if (white.z != black.z)
2538 image->colormap[i].red=equalize_map[
2539 ScaleQuantumToMap(image->colormap[i].red)].red;
2540 image->colormap[i].green=equalize_map[
2541 ScaleQuantumToMap(image->colormap[i].green)].red;
2542 image->colormap[i].blue=equalize_map[
2543 ScaleQuantumToMap(image->colormap[i].blue)].red;
2544 image->colormap[i].opacity=equalize_map[
2545 ScaleQuantumToMap(image->colormap[i].opacity)].red;
2549 if (((channel & RedChannel) != 0) && (white.z != black.z))
2550 image->colormap[i].red=equalize_map[
2551 ScaleQuantumToMap(image->colormap[i].red)].red;
2552 if (((channel & GreenChannel) != 0) && (white.y != black.y))
2553 image->colormap[i].green=equalize_map[
2554 ScaleQuantumToMap(image->colormap[i].green)].green;
2555 if (((channel & BlueChannel) != 0) && (white.x != black.x))
2556 image->colormap[i].blue=equalize_map[
2557 ScaleQuantumToMap(image->colormap[i].blue)].blue;
2558 if (((channel & OpacityChannel) != 0) &&
2559 (white.w != black.w))
2560 image->colormap[i].opacity=equalize_map[
2561 ScaleQuantumToMap(image->colormap[i].opacity)].opacity;
2566 equalizeMapBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, length *
sizeof(
PixelPacket), equalize_map, &clStatus);
2567 if (clStatus != CL_SUCCESS)
2569 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
2574 equalizeKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"Equalize");
2575 if (equalizeKernel == NULL)
2577 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
2583 clStatus=clEnv->library->clSetKernelArg(equalizeKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
2584 clStatus|=clEnv->library->clSetKernelArg(equalizeKernel,i++,
sizeof(ChannelType),&channel);
2585 clStatus|=clEnv->library->clSetKernelArg(equalizeKernel,i++,
sizeof(cl_mem),(
void *)&equalizeMapBuffer);
2586 clStatus|=clEnv->library->clSetKernelArg(equalizeKernel,i++,
sizeof(cl_float4),&white);
2587 clStatus|=clEnv->library->clSetKernelArg(equalizeKernel,i++,
sizeof(cl_float4),&black);
2588 if (clStatus != CL_SUCCESS)
2590 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
2595 global_work_size[0] = image->columns;
2596 global_work_size[1] = image->rows;
2598 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, equalizeKernel, 2, NULL, global_work_size, NULL, 0, NULL, &event);
2600 if (clStatus != CL_SUCCESS)
2602 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2605 if (RecordProfileData(clEnv,EqualizeKernel,event) == MagickFalse)
2606 AddOpenCLEvent(image,event);
2607 clEnv->library->clReleaseEvent(event);
2610 OpenCLLogException(__FUNCTION__,__LINE__,exception);
2612 if (imageBuffer != (cl_mem) NULL)
2613 clEnv->library->clReleaseMemObject(imageBuffer);
2616 map=(cl_float4 *) RelinquishMagickMemory(map);
2618 if (equalizeMapBuffer!=NULL)
2619 clEnv->library->clReleaseMemObject(equalizeMapBuffer);
2620 if (equalize_map!=NULL)
2621 equalize_map=(
PixelPacket *) RelinquishMagickMemory(equalize_map);
2623 if (histogramBuffer!=NULL)
2624 clEnv->library->clReleaseMemObject(histogramBuffer);
2625 if (histogram!=NULL)
2626 histogram=(cl_uint4 *) RelinquishMagickMemory(histogram);
2628 if (histogramKernel!=NULL)
2629 RelinquishOpenCLKernel(clEnv, histogramKernel);
2630 if (equalizeKernel!=NULL)
2631 RelinquishOpenCLKernel(clEnv, equalizeKernel);
2634 RelinquishOpenCLCommandQueue(clEnv, queue);
2636 return(outputReady);
2639MagickPrivate MagickBooleanType AccelerateEqualizeImage(
Image *image,
2645 assert(image != NULL);
2648 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
2649 (checkAccelerateCondition(image, channel) == MagickFalse) ||
2650 (checkHistogramCondition(image, channel) == MagickFalse))
2651 return(MagickFalse);
2653 status=ComputeEqualizeImage(image,channel,exception);
2669static MagickBooleanType ComputeFunctionImage(
Image *image,
2670 const ChannelType channel,
const MagickFunction function,
2671 const size_t number_parameters,
const double *parameters,
2697 *parametersBufferPtr;
2712 status = MagickFalse;
2718 parametersBuffer = NULL;
2720 clEnv = GetDefaultOpenCLEnv();
2721 context = GetOpenCLContext(clEnv);
2723 queue = AcquireOpenCLCommandQueue(clEnv);
2725 imageBuffer = GetAuthenticOpenCLBuffer(image,exception);
2726 if (imageBuffer == (cl_mem) NULL)
2728 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
2729 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
2735 parametersBufferPtr = (
float*)AcquireMagickMemory(number_parameters *
sizeof(
float));
2737 for (i = 0; i < number_parameters; i++)
2738 parametersBufferPtr[i] = (
float)parameters[i];
2740 parametersBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, number_parameters *
sizeof(
float), parametersBufferPtr, &clStatus);
2741 parametersBufferPtr=(
float *) RelinquishMagickMemory(parametersBufferPtr);
2744 clkernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"ComputeFunction");
2745 if (clkernel == NULL)
2747 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
2753 clStatus =clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
2754 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(ChannelType),(
void *)&channel);
2755 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(MagickFunction),(
void *)&function);
2756 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(
unsigned int),(
void *)&number_parameters);
2757 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,
sizeof(cl_mem),(
void *)¶metersBuffer);
2758 if (clStatus != CL_SUCCESS)
2760 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
2764 globalWorkSize[0] = image->columns;
2765 globalWorkSize[1] = image->rows;
2767 events=GetOpenCLEvents(image,&event_count);
2768 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, clkernel, 2, NULL, globalWorkSize, NULL, event_count, events, &event);
2769 events=(cl_event *) RelinquishMagickMemory(events);
2770 if (clStatus != CL_SUCCESS)
2772 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2775 if (RecordProfileData(clEnv,ComputeFunctionKernel,event) == MagickFalse)
2776 AddOpenCLEvent(image,event);
2777 clEnv->library->clReleaseEvent(event);
2778 status = MagickTrue;
2781 OpenCLLogException(__FUNCTION__,__LINE__,exception);
2783 if (imageBuffer != (cl_mem) NULL)
2784 clEnv->library->clReleaseMemObject(imageBuffer);
2785 if (clkernel != NULL) RelinquishOpenCLKernel(clEnv, clkernel);
2786 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
2787 if (parametersBuffer != NULL) clEnv->library->clReleaseMemObject(parametersBuffer);
2792MagickPrivate MagickBooleanType AccelerateFunctionImage(
Image *image,
2793 const ChannelType channel,
const MagickFunction function,
2794 const size_t number_parameters,
const double *parameters,
2800 assert(image != NULL);
2803 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
2804 (checkAccelerateCondition(image, channel) == MagickFalse))
2805 return(MagickFalse);
2807 status=ComputeFunctionImage(image, channel, function, number_parameters, parameters, exception);
2823MagickBooleanType ComputeGrayscaleImage(
Image *image,
2864 grayscaleKernel = NULL;
2866 assert(image != (
Image *) NULL);
2867 assert(image->signature == MagickCoreSignature);
2868 if (IsEventLogging() != MagickFalse)
2869 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",image->filename);
2874 clEnv = GetDefaultOpenCLEnv();
2875 context = GetOpenCLContext(clEnv);
2876 queue = AcquireOpenCLCommandQueue(clEnv);
2878 outputReady = MagickFalse;
2880 imageBuffer = GetAuthenticOpenCLBuffer(image, exception);
2881 if (imageBuffer == (cl_mem) NULL)
2883 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
2884 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
2888 intensityMethod = method;
2889 colorspace = image->colorspace;
2891 grayscaleKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"Grayscale");
2892 if (grayscaleKernel == NULL)
2894 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
2899 clStatus=clEnv->library->clSetKernelArg(grayscaleKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
2900 clStatus|=clEnv->library->clSetKernelArg(grayscaleKernel,i++,
sizeof(cl_int),&intensityMethod);
2901 clStatus|=clEnv->library->clSetKernelArg(grayscaleKernel,i++,
sizeof(cl_int),&colorspace);
2902 if (clStatus != CL_SUCCESS)
2904 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
2905 printf(
"no kernel\n");
2910 size_t global_work_size[2];
2911 global_work_size[0] = image->columns;
2912 global_work_size[1] = image->rows;
2914 events=GetOpenCLEvents(image,&event_count);
2915 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, grayscaleKernel, 2, NULL, global_work_size, NULL, event_count, events, &event);
2916 events=(cl_event *) RelinquishMagickMemory(events);
2917 if (clStatus != CL_SUCCESS)
2919 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
2922 if (RecordProfileData(clEnv,GrayScaleKernel,event) == MagickFalse)
2923 AddOpenCLEvent(image,event);
2924 clEnv->library->clReleaseEvent(event);
2927 outputReady=MagickTrue;
2930 OpenCLLogException(__FUNCTION__,__LINE__,exception);
2932 if (imageBuffer != (cl_mem) NULL)
2933 clEnv->library->clReleaseMemObject(imageBuffer);
2934 if (grayscaleKernel!=NULL)
2935 RelinquishOpenCLKernel(clEnv, grayscaleKernel);
2937 RelinquishOpenCLCommandQueue(clEnv, queue);
2939 return(outputReady);
2942MagickPrivate MagickBooleanType AccelerateGrayscaleImage(
Image* image,
2948 assert(image != NULL);
2951 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
2952 (checkAccelerateCondition(image, AllChannels) == MagickFalse))
2953 return(MagickFalse);
2955 if (method == Rec601LuminancePixelIntensityMethod || method == Rec709LuminancePixelIntensityMethod)
2956 return(MagickFalse);
2958 if (image->colorspace != sRGBColorspace)
2959 return(MagickFalse);
2961 status=ComputeGrayscaleImage(image,method,exception);
2977static Image *ComputeLocalContrastImage(
const Image *image,
2978 const double radius,
const double strength,
ExceptionInfo *exception)
2998 filteredImageBuffer,
3025 filteredImage = NULL;
3028 filteredImageBuffer = NULL;
3029 tempImageBuffer = NULL;
3030 blurRowKernel = NULL;
3031 blurColumnKernel = NULL;
3033 outputReady = MagickFalse;
3035 clEnv = GetDefaultOpenCLEnv();
3036 context = GetOpenCLContext(clEnv);
3037 queue = AcquireOpenCLCommandQueue(clEnv);
3039 filteredImage = CloneImage(image,0,0,MagickTrue,exception);
3040 if (filteredImage == (
Image *) NULL)
3043 imageBuffer = GetAuthenticOpenCLBuffer(image,exception);
3044 if (imageBuffer == (cl_mem) NULL)
3046 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
3047 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
3050 filteredImageBuffer = GetAuthenticOpenCLBuffer(filteredImage,exception);
3051 if (filteredImageBuffer == (cl_mem) NULL)
3053 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
3054 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
3061 length = image->columns * image->rows;
3062 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length *
sizeof(
float), NULL, &clStatus);
3063 if (clStatus != CL_SUCCESS)
3065 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
3072 blurRowKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"LocalContrastBlurRow");
3073 if (blurRowKernel == NULL)
3075 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
3079 blurColumnKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"LocalContrastBlurApplyColumn");
3080 if (blurColumnKernel == NULL)
3082 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
3088 imageColumns = (
unsigned int) image->columns;
3089 imageRows = (
unsigned int) image->rows;
3090 iRadius = (cl_int) (image->rows > image->columns ? image->rows : image->columns) * 0.002f * fabs(radius);
3092 passes = (((1.0f * imageRows) * imageColumns * iRadius) + 3999999999) / 4000000000.0f;
3093 passes = (passes < 1) ? 1: passes;
3097 clStatus=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
3098 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(cl_mem),(
void *)&filteredImageBuffer);
3099 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(cl_mem),(
void *)&tempImageBuffer);
3100 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(cl_int),(
void *)&iRadius);
3101 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(
unsigned int),(
void *)&imageColumns);
3102 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(
unsigned int),(
void *)&imageRows);
3104 if (clStatus != CL_SUCCESS)
3106 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
3114 for (x = 0; x < passes; ++x) {
3120 gsize[1] = (image->rows + passes - 1) / passes;
3124 goffset[1] = x * gsize[1];
3126 events=GetOpenCLEvents(image,&event_count);
3127 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurRowKernel, 2, goffset, gsize, wsize, event_count, events, &event);
3128 events=(cl_event *) RelinquishMagickMemory(events);
3129 if (clStatus != CL_SUCCESS)
3131 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
3134 clEnv->library->clFlush(queue);
3135 if (RecordProfileData(clEnv,LocalContrastBlurRowKernel,event) == MagickFalse)
3137 AddOpenCLEvent(image,event);
3138 AddOpenCLEvent(filteredImage, event);
3140 clEnv->library->clReleaseEvent(event);
3145 cl_float FStrength = strength;
3147 clStatus=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
3148 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(cl_mem),(
void *)&filteredImageBuffer);
3149 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(cl_mem),(
void *)&tempImageBuffer);
3150 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(
unsigned int),(
void *)&iRadius);
3151 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(cl_float),(
void *)&FStrength);
3152 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(
unsigned int),(
void *)&imageColumns);
3153 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,
sizeof(
unsigned int),(
void *)&imageRows);
3155 if (clStatus != CL_SUCCESS)
3157 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
3165 for (x = 0; x < passes; ++x) {
3170 gsize[0] = ((image->columns + 3) / 4) * 4;
3171 gsize[1] = ((((image->rows + 63) / 64) + (passes + 1)) / passes) * 64;
3175 goffset[1] = x * gsize[1];
3177 events=GetOpenCLEvents(image,&event_count);
3178 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurColumnKernel, 2, goffset, gsize, wsize, event_count, events, &event);
3179 events=(cl_event *) RelinquishMagickMemory(events);
3180 if (clStatus != CL_SUCCESS)
3182 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
3185 clEnv->library->clFlush(queue);
3186 if (RecordProfileData(clEnv, LocalContrastBlurApplyColumnKernel, event) == MagickFalse)
3188 AddOpenCLEvent(image,event);
3189 AddOpenCLEvent(filteredImage,event);
3191 clEnv->library->clReleaseEvent(event);
3196 outputReady = MagickTrue;
3200 OpenCLLogException(__FUNCTION__,__LINE__,exception);
3202 if (imageBuffer != (cl_mem) NULL)
3203 clEnv->library->clReleaseMemObject(imageBuffer);
3204 if (filteredImageBuffer != (cl_mem) NULL)
3205 clEnv->library->clReleaseMemObject(filteredImageBuffer);
3206 if (tempImageBuffer!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer);
3207 if (blurRowKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurRowKernel);
3208 if (blurColumnKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurColumnKernel);
3209 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
3210 if ((outputReady == MagickFalse) && (filteredImage != NULL))
3211 filteredImage=(
Image *) DestroyImage(filteredImage);
3212 return(filteredImage);
3215MagickPrivate
Image *AccelerateLocalContrastImage(
const Image *image,
3216 const double radius,
const double strength,
ExceptionInfo *exception)
3221 assert(image != NULL);
3224 if ((checkOpenCLEnvironment(exception) == MagickFalse))
3227 filteredImage=ComputeLocalContrastImage(image,radius,strength,exception);
3229 return(filteredImage);
3244MagickBooleanType ComputeModulateImage(
Image *image,
3245 double percent_brightness,
double percent_hue,
double percent_saturation,
3288 modulateKernel = NULL;
3291 assert(image != (
Image *)NULL);
3292 assert(image->signature == MagickCoreSignature);
3293 if (IsEventLogging() != MagickFalse)
3294 (void) LogMagickEvent(TraceEvent, GetMagickModule(),
"%s", image->filename);
3299 clEnv = GetDefaultOpenCLEnv();
3300 context = GetOpenCLContext(clEnv);
3301 queue = AcquireOpenCLCommandQueue(clEnv);
3303 outputReady = MagickFalse;
3305 imageBuffer = GetAuthenticOpenCLBuffer(image,exception);
3306 if (imageBuffer == (cl_mem) NULL)
3308 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
3309 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
3313 modulateKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"Modulate");
3314 if (modulateKernel == NULL)
3316 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
3320 bright = percent_brightness;
3322 saturation = percent_saturation;
3326 clStatus = clEnv->library->clSetKernelArg(modulateKernel, i++,
sizeof(cl_mem), (
void *)&imageBuffer);
3327 clStatus |= clEnv->library->clSetKernelArg(modulateKernel, i++,
sizeof(cl_float), &bright);
3328 clStatus |= clEnv->library->clSetKernelArg(modulateKernel, i++,
sizeof(cl_float), &hue);
3329 clStatus |= clEnv->library->clSetKernelArg(modulateKernel, i++,
sizeof(cl_float), &saturation);
3330 clStatus |= clEnv->library->clSetKernelArg(modulateKernel, i++,
sizeof(cl_float), &color);
3331 if (clStatus != CL_SUCCESS)
3333 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
3334 printf(
"no kernel\n");
3339 size_t global_work_size[2];
3340 global_work_size[0] = image->columns;
3341 global_work_size[1] = image->rows;
3343 events=GetOpenCLEvents(image,&event_count);
3344 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, modulateKernel, 2, NULL, global_work_size, NULL, event_count, events, &event);
3345 events=(cl_event *) RelinquishMagickMemory(events);
3346 if (clStatus != CL_SUCCESS)
3348 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
3351 if (RecordProfileData(clEnv, ModulateKernel, event) == MagickFalse)
3352 AddOpenCLEvent(image,event);
3353 clEnv->library->clReleaseEvent(event);
3356 outputReady=MagickTrue;
3359 OpenCLLogException(__FUNCTION__, __LINE__, exception);
3361 if (imageBuffer != (cl_mem) NULL)
3362 clEnv->library->clReleaseMemObject(imageBuffer);
3363 if (modulateKernel != NULL)
3364 RelinquishOpenCLKernel(clEnv, modulateKernel);
3366 RelinquishOpenCLCommandQueue(clEnv, queue);
3368 return(outputReady);
3371MagickPrivate MagickBooleanType AccelerateModulateImage(
Image *image,
3372 double percent_brightness,
double percent_hue,
double percent_saturation,
3378 assert(image != NULL);
3381 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
3382 (checkAccelerateCondition(image, AllChannels) == MagickFalse))
3383 return(MagickFalse);
3385 if ((colorspace != HSLColorspace && colorspace != UndefinedColorspace))
3386 return(MagickFalse);
3388 status = ComputeModulateImage(image, percent_brightness, percent_hue, percent_saturation, colorspace, exception);
3404static Image* ComputeMotionBlurImage(
const Image *image,
3405 const ChannelType channel,
const double *kernel,
const size_t width,
3427 filteredImageBuffer,
3457 global_work_size[2],
3466 outputReady = MagickFalse;
3468 filteredImage = NULL;
3470 filteredImageBuffer = NULL;
3471 imageKernelBuffer = NULL;
3472 motionBlurKernel = NULL;
3475 clEnv = GetDefaultOpenCLEnv();
3476 context = GetOpenCLContext(clEnv);
3478 filteredImage = CloneImage(image,0,0,MagickTrue,exception);
3479 if (filteredImage == (
Image *) NULL)
3482 imageBuffer = GetAuthenticOpenCLBuffer(image, exception);
3483 if (imageBuffer == (cl_mem) NULL)
3485 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
3486 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
3489 filteredImageBuffer = GetAuthenticOpenCLBuffer(filteredImage, exception);
3490 if (filteredImageBuffer == (cl_mem) NULL)
3492 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
3493 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
3497 imageKernelBuffer = clEnv->library->clCreateBuffer(context,
3498 CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, width *
sizeof(
float), NULL,
3500 if (clStatus != CL_SUCCESS)
3502 (void) ThrowMagickException(exception, GetMagickModule(),
3503 ResourceLimitError,
"clEnv->library->clCreateBuffer failed.",
".");
3507 queue = AcquireOpenCLCommandQueue(clEnv);
3508 events=GetOpenCLEvents(image,&event_count);
3510 kernelBufferPtr = (
float*)clEnv->library->clEnqueueMapBuffer(queue, imageKernelBuffer,
3511 CL_TRUE, CL_MAP_WRITE, 0, width *
sizeof(
float), event_count, events, NULL, &clStatus);
3512 events=(cl_event *) RelinquishMagickMemory(events);
3513 if (clStatus != CL_SUCCESS)
3515 (void) ThrowMagickException(exception, GetMagickModule(),
3516 ResourceLimitError,
"clEnv->library->clEnqueueMapBuffer failed.",
".");
3519 for (i = 0; i < width; i++)
3521 kernelBufferPtr[i] = (float) kernel[i];
3523 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, imageKernelBuffer, kernelBufferPtr,
3525 if (clStatus != CL_SUCCESS)
3527 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError,
3528 "clEnv->library->clEnqueueUnmapMemObject failed.",
"'%s'",
".");
3532 offsetBuffer = clEnv->library->clCreateBuffer(context,
3533 CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, width *
sizeof(cl_int2), NULL,
3535 if (clStatus != CL_SUCCESS)
3537 (void) ThrowMagickException(exception, GetMagickModule(),
3538 ResourceLimitError,
"clEnv->library->clCreateBuffer failed.",
".");
3542 offsetBufferPtr = (
int*)clEnv->library->clEnqueueMapBuffer(queue, offsetBuffer, CL_TRUE,
3543 CL_MAP_WRITE, 0, width *
sizeof(cl_int2), 0, NULL, NULL, &clStatus);
3544 if (clStatus != CL_SUCCESS)
3546 (void) ThrowMagickException(exception, GetMagickModule(),
3547 ResourceLimitError,
"clEnv->library->clEnqueueMapBuffer failed.",
".");
3550 for (i = 0; i < width; i++)
3552 offsetBufferPtr[2*i] = (int)offset[i].x;
3553 offsetBufferPtr[2*i+1] = (int)offset[i].y;
3555 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, offsetBuffer, offsetBufferPtr, 0,
3557 if (clStatus != CL_SUCCESS)
3559 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError,
3560 "clEnv->library->clEnqueueUnmapMemObject failed.",
"'%s'",
".");
3568 motionBlurKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
3570 if (motionBlurKernel == NULL)
3572 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError,
3573 "AcquireOpenCLKernel failed.",
"'%s'",
".");
3581 clStatus=clEnv->library->clSetKernelArg(motionBlurKernel,i++,
sizeof(cl_mem),
3582 (
void *)&imageBuffer);
3583 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,
sizeof(cl_mem),
3584 (
void *)&filteredImageBuffer);
3585 imageWidth = (
unsigned int) image->columns;
3586 imageHeight = (
unsigned int) image->rows;
3587 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,
sizeof(
unsigned int),
3589 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,
sizeof(
unsigned int),
3591 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,
sizeof(cl_mem),
3592 (
void *)&imageKernelBuffer);
3593 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,
sizeof(
unsigned int),
3595 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,
sizeof(cl_mem),
3596 (
void *)&offsetBuffer);
3598 GetMagickPixelPacket(image,&bias);
3599 biasPixel.s[0] = bias.red;
3600 biasPixel.s[1] = bias.green;
3601 biasPixel.s[2] = bias.blue;
3602 biasPixel.s[3] = bias.opacity;
3603 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,
sizeof(cl_float4), &biasPixel);
3605 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,
sizeof(ChannelType), &channel);
3606 matte = (image->matte != MagickFalse)?1:0;
3607 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,
sizeof(
unsigned int), &matte);
3608 if (clStatus != CL_SUCCESS)
3610 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError,
3611 "clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
3618 local_work_size[0] = 16;
3619 local_work_size[1] = 16;
3620 global_work_size[0] = (size_t)padGlobalWorkgroupSizeToLocalWorkgroupSize(
3621 (
unsigned int) image->columns,(
unsigned int) local_work_size[0]);
3622 global_work_size[1] = (size_t)padGlobalWorkgroupSizeToLocalWorkgroupSize(
3623 (
unsigned int) image->rows,(
unsigned int) local_work_size[1]);
3624 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, motionBlurKernel, 2, NULL,
3625 global_work_size, local_work_size, 0, NULL, &event);
3627 if (clStatus != CL_SUCCESS)
3629 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError,
3630 "clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
3633 if (RecordProfileData(clEnv,MotionBlurKernel,event) == MagickFalse)
3635 AddOpenCLEvent(image, event);
3636 AddOpenCLEvent(filteredImage, event);
3638 clEnv->library->clReleaseEvent(event);
3640 outputReady = MagickTrue;
3644 if (imageBuffer != (cl_mem) NULL)
3645 clEnv->library->clReleaseMemObject(imageBuffer);
3646 if (filteredImageBuffer != (cl_mem) NULL)
3647 clEnv->library->clReleaseMemObject(filteredImageBuffer);
3648 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer);
3649 if (motionBlurKernel!=NULL) RelinquishOpenCLKernel(clEnv, motionBlurKernel);
3650 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
3651 if ((outputReady == MagickFalse) && (filteredImage != NULL))
3652 filteredImage=(
Image *) DestroyImage(filteredImage);
3654 return(filteredImage);
3657MagickPrivate
Image *AccelerateMotionBlurImage(
const Image *image,
3658 const ChannelType channel,
const double* kernel,
const size_t width,
3664 assert(image != NULL);
3665 assert(kernel != (
double *) NULL);
3669 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
3670 (checkAccelerateCondition(image, channel) == MagickFalse))
3673 filteredImage=ComputeMotionBlurImage(image, channel, kernel, width,
3675 return(filteredImage);
3690static Image *ComputeRadialBlurImage(
const Image *image,
3691 const ChannelType channel,
const double angle,
ExceptionInfo *exception)
3710 filteredImageBuffer,
3746 global_work_size[2];
3753 outputReady = MagickFalse;
3755 filteredImage = NULL;
3757 filteredImageBuffer = NULL;
3758 sinThetaBuffer = NULL;
3759 cosThetaBuffer = NULL;
3761 radialBlurKernel = NULL;
3764 clEnv = GetDefaultOpenCLEnv();
3765 context = GetOpenCLContext(clEnv);
3767 filteredImage = CloneImage(image,0,0,MagickTrue,exception);
3768 if (filteredImage == (
Image *) NULL)
3771 imageBuffer = GetAuthenticOpenCLBuffer(image, exception);
3772 if (imageBuffer == (cl_mem) NULL)
3774 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
3775 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
3778 filteredImageBuffer = GetAuthenticOpenCLBuffer(filteredImage, exception);
3779 if (filteredImageBuffer == (cl_mem) NULL)
3781 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
3782 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
3786 blurCenter.s[0] = (float) (image->columns-1)/2.0;
3787 blurCenter.s[1] = (float) (image->rows-1)/2.0;
3788 blurRadius=hypot(blurCenter.s[0],blurCenter.s[1]);
3789 cossin_theta_size=(
unsigned int) fabs(4.0*DegreesToRadians(angle)*sqrt((
double)blurRadius)+2UL);
3792 sinThetaBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, cossin_theta_size *
sizeof(
float), NULL, &clStatus);
3793 if (clStatus != CL_SUCCESS)
3795 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
3798 cosThetaBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, cossin_theta_size *
sizeof(
float), NULL, &clStatus);
3799 if (clStatus != CL_SUCCESS)
3801 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
3805 queue = AcquireOpenCLCommandQueue(clEnv);
3806 events=GetOpenCLEvents(image,&event_count);
3808 sinThetaPtr = (
float*) clEnv->library->clEnqueueMapBuffer(queue, sinThetaBuffer, CL_TRUE, CL_MAP_WRITE, 0, cossin_theta_size*
sizeof(
float), event_count, events, NULL, &clStatus);
3809 events=(cl_event *) RelinquishMagickMemory(events);
3810 if (clStatus != CL_SUCCESS)
3812 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnqueuemapBuffer failed.",
".");
3816 cosThetaPtr = (
float*) clEnv->library->clEnqueueMapBuffer(queue, cosThetaBuffer, CL_TRUE, CL_MAP_WRITE, 0, cossin_theta_size*
sizeof(
float), 0, NULL, NULL, &clStatus);
3817 if (clStatus != CL_SUCCESS)
3819 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnqueuemapBuffer failed.",
".");
3823 theta=DegreesToRadians(angle)/(MagickRealType) (cossin_theta_size-1);
3824 offset=theta*(MagickRealType) (cossin_theta_size-1)/2.0;
3825 for (i=0; i < (ssize_t) cossin_theta_size; i++)
3827 cosThetaPtr[i]=(float)cos((
double) (theta*i-offset));
3828 sinThetaPtr[i]=(float)sin((
double) (theta*i-offset));
3831 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, sinThetaBuffer, sinThetaPtr, 0, NULL, NULL);
3832 clStatus |= clEnv->library->clEnqueueUnmapMemObject(queue, cosThetaBuffer, cosThetaPtr, 0, NULL, NULL);
3833 if (clStatus != CL_SUCCESS)
3835 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueUnmapMemObject failed.",
"'%s'",
".");
3840 radialBlurKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"RadialBlur");
3841 if (radialBlurKernel == NULL)
3843 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
3850 clStatus=clEnv->library->clSetKernelArg(radialBlurKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
3851 clStatus|=clEnv->library->clSetKernelArg(radialBlurKernel,i++,
sizeof(cl_mem),(
void *)&filteredImageBuffer);
3853 GetMagickPixelPacket(image,&bias);
3854 biasPixel.s[0] = bias.red;
3855 biasPixel.s[1] = bias.green;
3856 biasPixel.s[2] = bias.blue;
3857 biasPixel.s[3] = bias.opacity;
3858 clStatus|=clEnv->library->clSetKernelArg(radialBlurKernel,i++,
sizeof(cl_float4), &biasPixel);
3859 clStatus|=clEnv->library->clSetKernelArg(radialBlurKernel,i++,
sizeof(ChannelType), &channel);
3861 matte = (image->matte != MagickFalse)?1:0;
3862 clStatus|=clEnv->library->clSetKernelArg(radialBlurKernel,i++,
sizeof(
unsigned int), &matte);
3864 clStatus=clEnv->library->clSetKernelArg(radialBlurKernel,i++,
sizeof(cl_float2), &blurCenter);
3866 clStatus|=clEnv->library->clSetKernelArg(radialBlurKernel,i++,
sizeof(cl_mem),(
void *)&cosThetaBuffer);
3867 clStatus|=clEnv->library->clSetKernelArg(radialBlurKernel,i++,
sizeof(cl_mem),(
void *)&sinThetaBuffer);
3868 clStatus|=clEnv->library->clSetKernelArg(radialBlurKernel,i++,
sizeof(
unsigned int), &cossin_theta_size);
3869 if (clStatus != CL_SUCCESS)
3871 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
3876 global_work_size[0] = image->columns;
3877 global_work_size[1] = image->rows;
3879 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, radialBlurKernel, 2, NULL, global_work_size, NULL, 0, NULL, &event);
3880 if (clStatus != CL_SUCCESS)
3882 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
3885 if (RecordProfileData(clEnv,RadialBlurKernel,event) == MagickFalse)
3887 AddOpenCLEvent(image,event);
3888 AddOpenCLEvent(filteredImage,event);
3890 clEnv->library->clReleaseEvent(event);
3892 outputReady = MagickTrue;
3895 OpenCLLogException(__FUNCTION__,__LINE__,exception);
3897 if (imageBuffer != (cl_mem) NULL)
3898 clEnv->library->clReleaseMemObject(imageBuffer);
3899 if (filteredImageBuffer != (cl_mem) NULL)
3900 clEnv->library->clReleaseMemObject(filteredImageBuffer);
3901 if (sinThetaBuffer!=NULL) clEnv->library->clReleaseMemObject(sinThetaBuffer);
3902 if (cosThetaBuffer!=NULL) clEnv->library->clReleaseMemObject(cosThetaBuffer);
3903 if (radialBlurKernel!=NULL) RelinquishOpenCLKernel(clEnv, radialBlurKernel);
3904 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
3905 if ((outputReady == MagickFalse) && (filteredImage != NULL))
3906 filteredImage=(
Image *) DestroyImage(filteredImage);
3907 return filteredImage;
3910MagickPrivate
Image *AccelerateRadialBlurImage(
const Image *image,
3911 const ChannelType channel,
const double angle,
ExceptionInfo *exception)
3916 assert(image != NULL);
3919 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
3920 (checkAccelerateCondition(image, channel) == MagickFalse))
3923 filteredImage=ComputeRadialBlurImage(image, channel, angle, exception);
3924 return filteredImage;
3939static MagickBooleanType resizeHorizontalFilter(
const Image *image,
3940 const Image *filteredImage,cl_mem imageBuffer,
const unsigned int imageColumns,
3941 const unsigned int imageRows,
const unsigned int matte,cl_mem resizedImage,
3942 const unsigned int resizedColumns,
const unsigned int resizedRows,
3943 const ResizeFilter *resizeFilter,cl_mem resizeFilterCubicCoefficients,
3944 const float xFactor,
MagickCLEnv clEnv,cl_command_queue queue,
3963 workgroupSize = 256;
3967 resizeFilterSupport,
3968 resizeFilterWindowSupport,
3981 status = MagickFalse;
3984 deviceLocalMemorySize,
3985 gammaAccumulatorLocalMemorySize,
3986 global_work_size[2],
3987 imageCacheLocalMemorySize,
3988 pixelAccumulatorLocalMemorySize,
3990 totalLocalMemorySize,
3991 weightAccumulatorLocalMemorySize;
3998 horizontalKernel = NULL;
3999 status = MagickFalse;
4004 scale=MAGICK_MAX(1.0/xFactor+MagickEpsilon,1.0);
4005 support=scale*GetResizeFilterSupport(resizeFilter);
4012 support=(MagickRealType) 0.5;
4015 scale=PerceptibleReciprocal(scale);
4017 if (resizedColumns < workgroupSize)
4020 pixelPerWorkgroup = 32;
4024 chunkSize = workgroupSize;
4025 pixelPerWorkgroup = workgroupSize;
4029 deviceLocalMemorySize = GetOpenCLDeviceLocalMemorySize(clEnv);
4031DisableMSCWarning(4127)
4036 cacheRangeStart = (int) (((0 + 0.5)/xFactor+MagickEpsilon)-support+0.5);
4037 cacheRangeEnd = (int) ((((pixelPerWorkgroup-1) + 0.5)/xFactor+MagickEpsilon)+support+0.5);
4038 numCachedPixels = cacheRangeEnd - cacheRangeStart + 1;
4039 imageCacheLocalMemorySize = numCachedPixels *
sizeof(CLPixelPacket);
4040 totalLocalMemorySize = imageCacheLocalMemorySize;
4043 pixelAccumulatorLocalMemorySize = chunkSize *
sizeof(cl_float4);
4044 totalLocalMemorySize+=pixelAccumulatorLocalMemorySize;
4047 weightAccumulatorLocalMemorySize = chunkSize *
sizeof(float);
4048 totalLocalMemorySize+=weightAccumulatorLocalMemorySize;
4052 gammaAccumulatorLocalMemorySize =
sizeof(
float);
4054 gammaAccumulatorLocalMemorySize = chunkSize *
sizeof(float);
4055 totalLocalMemorySize+=gammaAccumulatorLocalMemorySize;
4057 if (totalLocalMemorySize <= deviceLocalMemorySize)
4061 pixelPerWorkgroup = pixelPerWorkgroup/2;
4062 chunkSize = chunkSize/2;
4063 if (pixelPerWorkgroup == 0
4072 resizeFilterType = (int)GetResizeFilterWeightingType(resizeFilter);
4073 resizeWindowType = (int)GetResizeFilterWindowWeightingType(resizeFilter);
4075 horizontalKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"ResizeHorizontalFilter");
4076 if (horizontalKernel == NULL)
4078 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
4083 clStatus = clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(cl_mem), (
void*)&imageBuffer);
4084 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), (
void*)&imageColumns);
4085 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), (
void*)&imageRows);
4086 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), (
void*)&matte);
4087 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
float), (
void*)&xFactor);
4088 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(cl_mem), (
void*)&resizedImage);
4090 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), (
void*)&resizedColumns);
4091 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), (
void*)&resizedRows);
4093 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
int), (
void*)&resizeFilterType);
4094 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
int), (
void*)&resizeWindowType);
4095 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(cl_mem), (
void*)&resizeFilterCubicCoefficients);
4097 resizeFilterScale = (float) GetResizeFilterScale(resizeFilter);
4098 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
float), (
void*)&resizeFilterScale);
4100 resizeFilterSupport = (float) GetResizeFilterSupport(resizeFilter);
4101 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
float), (
void*)&resizeFilterSupport);
4103 resizeFilterWindowSupport = (float) GetResizeFilterWindowSupport(resizeFilter);
4104 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
float), (
void*)&resizeFilterWindowSupport);
4106 resizeFilterBlur = (float) GetResizeFilterBlur(resizeFilter);
4107 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
float), (
void*)&resizeFilterBlur);
4110 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, imageCacheLocalMemorySize, NULL);
4111 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
int), &numCachedPixels);
4112 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), &pixelPerWorkgroup);
4113 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), &chunkSize);
4116 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, pixelAccumulatorLocalMemorySize, NULL);
4117 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, weightAccumulatorLocalMemorySize, NULL);
4118 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, gammaAccumulatorLocalMemorySize, NULL);
4120 if (clStatus != CL_SUCCESS)
4122 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
4126 global_work_size[0] = (resizedColumns+pixelPerWorkgroup-1)/pixelPerWorkgroup*workgroupSize;
4127 global_work_size[1] = resizedRows;
4129 local_work_size[0] = workgroupSize;
4130 local_work_size[1] = 1;
4131 events=GetOpenCLEvents(image,&event_count);
4132 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, horizontalKernel, 2, NULL, global_work_size, local_work_size, event_count, events, &event);
4133 events=(cl_event *) RelinquishMagickMemory(events);
4134 if (clStatus != CL_SUCCESS)
4136 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
4139 if (RecordProfileData(clEnv,ResizeHorizontalKernel,event) == MagickFalse)
4141 AddOpenCLEvent(image,event);
4142 AddOpenCLEvent(filteredImage,event);
4144 clEnv->library->clReleaseEvent(event);
4145 status = MagickTrue;
4149 OpenCLLogException(__FUNCTION__,__LINE__,exception);
4151 if (horizontalKernel != NULL) RelinquishOpenCLKernel(clEnv, horizontalKernel);
4156static MagickBooleanType resizeVerticalFilter(
const Image *image,
4157 const Image *filteredImage,cl_mem imageBuffer,
const unsigned int imageColumns,
4158 const unsigned int imageRows,
const unsigned int matte,cl_mem resizedImage,
4159 const unsigned int resizedColumns,
const unsigned int resizedRows,
4160 const ResizeFilter *resizeFilter,cl_mem resizeFilterCubicCoefficients,
4161 const float yFactor,
MagickCLEnv clEnv,cl_command_queue queue,
4180 workgroupSize = 256;
4184 resizeFilterSupport,
4185 resizeFilterWindowSupport,
4198 status = MagickFalse;
4201 deviceLocalMemorySize,
4202 gammaAccumulatorLocalMemorySize,
4203 global_work_size[2],
4204 imageCacheLocalMemorySize,
4205 pixelAccumulatorLocalMemorySize,
4207 totalLocalMemorySize,
4208 weightAccumulatorLocalMemorySize;
4215 horizontalKernel = NULL;
4216 status = MagickFalse;
4221 scale=MAGICK_MAX(1.0/yFactor+MagickEpsilon,1.0);
4222 support=scale*GetResizeFilterSupport(resizeFilter);
4229 support=(MagickRealType) 0.5;
4232 scale=PerceptibleReciprocal(scale);
4234 if (resizedRows < workgroupSize)
4237 pixelPerWorkgroup = 32;
4241 chunkSize = workgroupSize;
4242 pixelPerWorkgroup = workgroupSize;
4246 deviceLocalMemorySize = GetOpenCLDeviceLocalMemorySize(clEnv);
4248DisableMSCWarning(4127)
4253 cacheRangeStart = (int) (((0 + 0.5)/yFactor+MagickEpsilon)-support+0.5);
4254 cacheRangeEnd = (int) ((((pixelPerWorkgroup-1) + 0.5)/yFactor+MagickEpsilon)+support+0.5);
4255 numCachedPixels = cacheRangeEnd - cacheRangeStart + 1;
4256 imageCacheLocalMemorySize = numCachedPixels *
sizeof(CLPixelPacket);
4257 totalLocalMemorySize = imageCacheLocalMemorySize;
4260 pixelAccumulatorLocalMemorySize = chunkSize *
sizeof(cl_float4);
4261 totalLocalMemorySize+=pixelAccumulatorLocalMemorySize;
4264 weightAccumulatorLocalMemorySize = chunkSize *
sizeof(float);
4265 totalLocalMemorySize+=weightAccumulatorLocalMemorySize;
4269 gammaAccumulatorLocalMemorySize =
sizeof(
float);
4271 gammaAccumulatorLocalMemorySize = chunkSize *
sizeof(float);
4272 totalLocalMemorySize+=gammaAccumulatorLocalMemorySize;
4274 if (totalLocalMemorySize <= deviceLocalMemorySize)
4278 pixelPerWorkgroup = pixelPerWorkgroup/2;
4279 chunkSize = chunkSize/2;
4280 if (pixelPerWorkgroup == 0
4289 resizeFilterType = (int)GetResizeFilterWeightingType(resizeFilter);
4290 resizeWindowType = (int)GetResizeFilterWindowWeightingType(resizeFilter);
4292 horizontalKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"ResizeVerticalFilter");
4293 if (horizontalKernel == NULL)
4295 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
4300 clStatus = clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(cl_mem), (
void*)&imageBuffer);
4301 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), (
void*)&imageColumns);
4302 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), (
void*)&imageRows);
4303 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), (
void*)&matte);
4304 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
float), (
void*)&yFactor);
4305 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(cl_mem), (
void*)&resizedImage);
4307 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), (
void*)&resizedColumns);
4308 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), (
void*)&resizedRows);
4310 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
int), (
void*)&resizeFilterType);
4311 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
int), (
void*)&resizeWindowType);
4312 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(cl_mem), (
void*)&resizeFilterCubicCoefficients);
4314 resizeFilterScale = (float) GetResizeFilterScale(resizeFilter);
4315 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
float), (
void*)&resizeFilterScale);
4317 resizeFilterSupport = (float) GetResizeFilterSupport(resizeFilter);
4318 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
float), (
void*)&resizeFilterSupport);
4320 resizeFilterWindowSupport = (float) GetResizeFilterWindowSupport(resizeFilter);
4321 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
float), (
void*)&resizeFilterWindowSupport);
4323 resizeFilterBlur = (float) GetResizeFilterBlur(resizeFilter);
4324 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
float), (
void*)&resizeFilterBlur);
4327 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, imageCacheLocalMemorySize, NULL);
4328 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
int), &numCachedPixels);
4329 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), &pixelPerWorkgroup);
4330 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++,
sizeof(
unsigned int), &chunkSize);
4333 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, pixelAccumulatorLocalMemorySize, NULL);
4334 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, weightAccumulatorLocalMemorySize, NULL);
4335 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, gammaAccumulatorLocalMemorySize, NULL);
4337 if (clStatus != CL_SUCCESS)
4339 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
4343 global_work_size[0] = resizedColumns;
4344 global_work_size[1] = (resizedRows+pixelPerWorkgroup-1)/pixelPerWorkgroup*workgroupSize;
4346 local_work_size[0] = 1;
4347 local_work_size[1] = workgroupSize;
4348 events=GetOpenCLEvents(image,&event_count);
4349 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, horizontalKernel, 2, NULL, global_work_size, local_work_size, event_count, events, &event);
4350 events=(cl_event *) RelinquishMagickMemory(events);
4351 if (clStatus != CL_SUCCESS)
4353 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
4356 if (RecordProfileData(clEnv,ResizeVerticalKernel,event) == MagickFalse)
4358 AddOpenCLEvent(image,event);
4359 AddOpenCLEvent(filteredImage,event);
4361 clEnv->library->clReleaseEvent(event);
4362 status = MagickTrue;
4366 OpenCLLogException(__FUNCTION__,__LINE__,exception);
4368 if (horizontalKernel != NULL) RelinquishOpenCLKernel(clEnv, horizontalKernel);
4373static Image *ComputeResizeImage(
const Image* image,
4374 const size_t resizedColumns,
const size_t resizedRows,
4387 cubicCoefficientsBuffer,
4388 filteredImageBuffer,
4392 const MagickRealType
4393 *resizeFilterCoefficient;
4396 coefficientBuffer[7],
4416 outputReady = MagickFalse;
4417 filteredImage = NULL;
4421 tempImageBuffer = NULL;
4422 filteredImageBuffer = NULL;
4423 cubicCoefficientsBuffer = NULL;
4426 clEnv = GetDefaultOpenCLEnv();
4427 context = GetOpenCLContext(clEnv);
4428 queue = AcquireOpenCLCommandQueue(clEnv);
4430 filteredImage=CloneImage(image,resizedColumns,resizedRows,MagickTrue,exception);
4431 if (filteredImage == (
Image *) NULL)
4434 imageBuffer=GetAuthenticOpenCLBuffer(image,exception);
4435 if (imageBuffer == (cl_mem) NULL)
4437 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
4438 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
4441 filteredImageBuffer=GetAuthenticOpenCLBuffer(filteredImage,exception);
4442 if (filteredImageBuffer == (cl_mem) NULL)
4444 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
4445 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
4449 resizeFilterCoefficient=GetResizeFilterCoefficient(resizeFilter);
4450 for (i = 0; i < 7; i++)
4451 coefficientBuffer[i]=(
float) resizeFilterCoefficient[i];
4453 cubicCoefficientsBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(coefficientBuffer), coefficientBuffer, &clStatus);
4454 if (clStatus != CL_SUCCESS)
4456 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
4460 xFactor=(float) resizedColumns/(
float) image->columns;
4461 yFactor=(float) resizedRows/(
float) image->rows;
4462 if (xFactor > yFactor)
4465 length = resizedColumns*image->rows;
4466 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length*
sizeof(CLPixelPacket), NULL, &clStatus);
4467 if (clStatus != CL_SUCCESS)
4469 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
4473 status = resizeHorizontalFilter(image,filteredImage,imageBuffer, (
unsigned int) image->columns, (
unsigned int) image->rows, (image->matte != MagickFalse)?1:0
4474 , tempImageBuffer, (
unsigned int) resizedColumns, (
unsigned int) image->rows
4475 , resizeFilter, cubicCoefficientsBuffer
4476 , xFactor, clEnv, queue, exception);
4477 if (status != MagickTrue)
4480 status = resizeVerticalFilter(image,filteredImage,tempImageBuffer, (
unsigned int) resizedColumns, (
unsigned int) image->rows, (image->matte != MagickFalse)?1:0
4481 , filteredImageBuffer, (
unsigned int) resizedColumns, (
unsigned int) resizedRows
4482 , resizeFilter, cubicCoefficientsBuffer
4483 , yFactor, clEnv, queue, exception);
4484 if (status != MagickTrue)
4489 length = image->columns*resizedRows;
4490 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length*
sizeof(CLPixelPacket), NULL, &clStatus);
4491 if (clStatus != CL_SUCCESS)
4493 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
4497 status = resizeVerticalFilter(image,filteredImage,imageBuffer, (
unsigned int) image->columns, (
unsigned int) image->rows, (image->matte != MagickFalse)?1:0
4498 , tempImageBuffer, (
unsigned int) image->columns, (
unsigned int) resizedRows
4499 , resizeFilter, cubicCoefficientsBuffer
4500 , yFactor, clEnv, queue, exception);
4501 if (status != MagickTrue)
4504 status = resizeHorizontalFilter(image,filteredImage,tempImageBuffer, (
unsigned int) image->columns, (
unsigned int) resizedRows, (image->matte != MagickFalse)?1:0
4505 , filteredImageBuffer, (
unsigned int) resizedColumns, (
unsigned int) resizedRows
4506 , resizeFilter, cubicCoefficientsBuffer
4507 , xFactor, clEnv, queue, exception);
4508 if (status != MagickTrue)
4511 outputReady=MagickTrue;
4514 OpenCLLogException(__FUNCTION__,__LINE__,exception);
4516 if (imageBuffer != (cl_mem) NULL)
4517 clEnv->library->clReleaseMemObject(imageBuffer);
4518 if (filteredImageBuffer != (cl_mem) NULL)
4519 clEnv->library->clReleaseMemObject(filteredImageBuffer);
4520 if (tempImageBuffer!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer);
4521 if (cubicCoefficientsBuffer!=NULL) clEnv->library->clReleaseMemObject(cubicCoefficientsBuffer);
4522 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
4523 if ((outputReady == MagickFalse) && (filteredImage != NULL))
4524 filteredImage=(
Image *) DestroyImage(filteredImage);
4525 return(filteredImage);
4528static MagickBooleanType gpuSupportedResizeWeighting(
4529 ResizeWeightingFunctionType f)
4536 if (supportedResizeWeighting[i] == LastWeightingFunction)
4538 if (supportedResizeWeighting[i] == f)
4541 return(MagickFalse);
4544MagickPrivate
Image *AccelerateResizeImage(
const Image *image,
4545 const size_t resizedColumns,
const size_t resizedRows,
4551 assert(image != NULL);
4554 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
4555 (checkAccelerateCondition(image, AllChannels) == MagickFalse))
4558 if (gpuSupportedResizeWeighting(GetResizeFilterWeightingType(resizeFilter)) == MagickFalse ||
4559 gpuSupportedResizeWeighting(GetResizeFilterWindowWeightingType(resizeFilter)) == MagickFalse)
4562 filteredImage=ComputeResizeImage(image,resizedColumns,resizedRows,resizeFilter,exception);
4563 return(filteredImage);
4578static Image *ComputeUnsharpMaskImage(
const Image *image,
4579 const ChannelType channel,
const double radius,
const double sigma,
4580 const double gain,
const double threshold,
ExceptionInfo *exception)
4583 geometry[MaxTextExtent];
4599 unsharpMaskBlurColumnKernel;
4602 filteredImageBuffer,
4645 filteredImage = NULL;
4649 filteredImageBuffer = NULL;
4650 tempImageBuffer = NULL;
4651 imageKernelBuffer = NULL;
4652 blurRowKernel = NULL;
4653 unsharpMaskBlurColumnKernel = NULL;
4655 outputReady = MagickFalse;
4657 clEnv = GetDefaultOpenCLEnv();
4658 context = GetOpenCLContext(clEnv);
4659 queue = AcquireOpenCLCommandQueue(clEnv);
4661 filteredImage = CloneImage(image,0,0,MagickTrue,exception);
4662 if (filteredImage == (
Image *) NULL)
4665 imageBuffer=GetAuthenticOpenCLBuffer(image,exception);
4666 if (imageBuffer == (cl_mem) NULL)
4668 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
4669 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
4672 filteredImageBuffer=GetAuthenticOpenCLBuffer(filteredImage,exception);
4673 if (filteredImageBuffer == (cl_mem) NULL)
4675 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
4676 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
4682 (void) FormatLocaleString(geometry,MaxTextExtent,
"blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma);
4683 kernel=AcquireKernelInfo(geometry);
4686 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireKernelInfo failed.",
".");
4690 kernelBufferPtr=(
float *) AcquireQuantumMemory(kernel->width,
sizeof(
float));
4691 if (kernelBufferPtr == (
float *) NULL)
4693 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"Memory allocation failed.",
".");
4696 for (i = 0; i < kernel->width; i++)
4697 kernelBufferPtr[i]=(
float) kernel->values[i];
4699 imageKernelBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, kernel->width *
sizeof(
float), kernelBufferPtr, &clStatus);
4700 kernelBufferPtr=(
float *) RelinquishMagickMemory(kernelBufferPtr);
4701 if (clStatus != CL_SUCCESS)
4703 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
4711 length = image->columns * image->rows;
4712 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length * 4 *
sizeof(
float), NULL, &clStatus);
4713 if (clStatus != CL_SUCCESS)
4715 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
4722 blurRowKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"BlurRow");
4723 if (blurRowKernel == NULL)
4725 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
4729 unsharpMaskBlurColumnKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"UnsharpMaskBlurColumn");
4730 if (unsharpMaskBlurColumnKernel == NULL)
4732 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
4740 imageColumns = (
unsigned int) image->columns;
4741 imageRows = (
unsigned int) image->rows;
4743 kernelWidth = (
unsigned int) kernel->width;
4747 clStatus=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
4748 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(cl_mem),(
void *)&tempImageBuffer);
4749 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(ChannelType),&channel);
4750 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(cl_mem),(
void *)&imageKernelBuffer);
4751 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(
unsigned int),(
void *)&kernelWidth);
4752 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(
unsigned int),(
void *)&imageColumns);
4753 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(
unsigned int),(
void *)&imageRows);
4754 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,
sizeof(CLPixelPacket)*(chunkSize+kernel->width),(
void *) NULL);
4755 if (clStatus != CL_SUCCESS)
4757 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
4767 gsize[0] = chunkSize*((image->columns+chunkSize-1)/chunkSize);
4768 gsize[1] = image->rows;
4769 wsize[0] = chunkSize;
4772 events=GetOpenCLEvents(image,&event_count);
4773 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurRowKernel, 2, NULL, gsize, wsize, event_count, events, NULL);
4774 events=(cl_event *) RelinquishMagickMemory(events);
4775 if (clStatus != CL_SUCCESS)
4777 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
4785 imageColumns = (
unsigned int) image->columns;
4786 imageRows = (
unsigned int) image->rows;
4787 kernelWidth = (
unsigned int) kernel->width;
4788 fGain = (float) gain;
4789 fThreshold = (float) threshold;
4792 clStatus=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
4793 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,
sizeof(cl_mem),(
void *)&tempImageBuffer);
4794 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,
sizeof(cl_mem),(
void *)&filteredImageBuffer);
4795 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,
sizeof(
unsigned int),(
void *)&imageColumns);
4796 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,
sizeof(
unsigned int),(
void *)&imageRows);
4797 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++, (chunkSize+kernelWidth-1)*
sizeof(cl_float4),NULL);
4798 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++, kernelWidth*
sizeof(
float),NULL);
4799 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,
sizeof(ChannelType),&channel);
4800 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,
sizeof(cl_mem),(
void *)&imageKernelBuffer);
4801 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,
sizeof(
unsigned int),(
void *)&kernelWidth);
4802 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,
sizeof(
float),(
void *)&fGain);
4803 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,
sizeof(
float),(
void *)&fThreshold);
4805 if (clStatus != CL_SUCCESS)
4807 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
4817 gsize[0] = image->columns;
4818 gsize[1] = chunkSize*((image->rows+chunkSize-1)/chunkSize);
4820 wsize[1] = chunkSize;
4822 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, unsharpMaskBlurColumnKernel, 2, NULL, gsize, wsize, event_count, events, &event);
4823 if (clStatus != CL_SUCCESS)
4825 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
4828 if (RecordProfileData(clEnv,UnsharpMaskBlurColumnKernel,event) == MagickFalse)
4830 AddOpenCLEvent(image,event);
4831 AddOpenCLEvent(filteredImage,event);
4833 clEnv->library->clReleaseEvent(event);
4838 outputReady=MagickTrue;
4841 OpenCLLogException(__FUNCTION__,__LINE__,exception);
4843 if (imageBuffer != (cl_mem) NULL)
4844 clEnv->library->clReleaseMemObject(imageBuffer);
4845 if (filteredImageBuffer != (cl_mem) NULL)
4846 clEnv->library->clReleaseMemObject(filteredImageBuffer);
4847 if (kernel != NULL) kernel=DestroyKernelInfo(kernel);
4848 if (tempImageBuffer!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer);
4849 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer);
4850 if (blurRowKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurRowKernel);
4851 if (unsharpMaskBlurColumnKernel!=NULL) RelinquishOpenCLKernel(clEnv, unsharpMaskBlurColumnKernel);
4852 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
4853 if ((outputReady == MagickFalse) && (filteredImage != NULL))
4854 filteredImage=(
Image *) DestroyImage(filteredImage);
4855 return(filteredImage);
4858static Image *ComputeUnsharpMaskImageSingle(
const Image *image,
4859 const double radius,
const double sigma,
const double gain,
4860 const double threshold,
int blurOnly,
ExceptionInfo *exception)
4863 geometry[MaxTextExtent];
4882 filteredImageBuffer,
4913 filteredImage = NULL;
4917 filteredImageBuffer = NULL;
4918 imageKernelBuffer = NULL;
4919 unsharpMaskKernel = NULL;
4921 outputReady = MagickFalse;
4923 clEnv = GetDefaultOpenCLEnv();
4924 context = GetOpenCLContext(clEnv);
4925 queue = AcquireOpenCLCommandQueue(clEnv);
4927 filteredImage = CloneImage(image,0,0,MagickTrue,exception);
4928 if (filteredImage == (
Image *) NULL)
4931 imageBuffer = GetAuthenticOpenCLBuffer(image,exception);
4932 if (imageBuffer == (cl_mem) NULL)
4934 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
4935 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
4938 filteredImageBuffer = GetAuthenticOpenCLBuffer(filteredImage,exception);
4939 if (filteredImageBuffer == (cl_mem) NULL)
4941 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
4942 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
4948 (void) FormatLocaleString(geometry,MaxTextExtent,
"blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma);
4949 kernel=AcquireKernelInfo(geometry);
4952 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireKernelInfo failed.",
".");
4957 float *kernelBufferPtr = (
float *) AcquireQuantumMemory(kernel->width,
sizeof(
float));
4958 for (i = 0; i < kernel->width; i++)
4959 kernelBufferPtr[i] = (
float)kernel->values[i];
4961 imageKernelBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, kernel->width *
sizeof(
float), kernelBufferPtr, &clStatus);
4962 RelinquishMagickMemory(kernelBufferPtr);
4963 if (clStatus != CL_SUCCESS)
4965 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clCreateBuffer failed.",
".");
4974 unsharpMaskKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"UnsharpMask");
4975 if (unsharpMaskKernel == NULL)
4977 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
4983 imageColumns = (
unsigned int) image->columns;
4984 imageRows = (
unsigned int) image->rows;
4985 kernelWidth = (
unsigned int) kernel->width;
4986 fGain = (float) gain;
4987 fThreshold = (float) threshold;
4988 justBlur = blurOnly;
4992 clStatus=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,
sizeof(cl_mem),(
void *)&imageBuffer);
4993 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,
sizeof(cl_mem),(
void *)&filteredImageBuffer);
4994 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,
sizeof(cl_mem),(
void *)&imageKernelBuffer);
4995 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,
sizeof(
unsigned int),(
void *)&kernelWidth);
4996 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,
sizeof(
unsigned int),(
void *)&imageColumns);
4997 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,
sizeof(
unsigned int),(
void *)&imageRows);
4998 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,
sizeof(cl_float4)*(8 * (32 + kernel->width)),(
void *) NULL);
4999 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,
sizeof(
float),(
void *)&fGain);
5000 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,
sizeof(
float),(
void *)&fThreshold);
5001 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,
sizeof(cl_uint),(
void *)&justBlur);
5002 if (clStatus != CL_SUCCESS)
5004 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clSetKernelArg failed.",
"'%s'",
".");
5014 gsize[0] = ((image->columns + 7) / 8) * 8;
5015 gsize[1] = ((image->rows + 31) / 32) * 32;
5019 events=GetOpenCLEvents(image,&event_count);
5020 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, unsharpMaskKernel, 2, NULL, gsize, wsize, event_count, events, &event);
5021 events=(cl_event *) RelinquishMagickMemory(events);
5022 if (clStatus != CL_SUCCESS)
5024 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
5027 if (RecordProfileData(clEnv,UnsharpMaskKernel,event) == MagickFalse)
5029 AddOpenCLEvent(image,event);
5030 AddOpenCLEvent(filteredImage, event);
5032 clEnv->library->clReleaseEvent(event);
5036 outputReady=MagickTrue;
5039 OpenCLLogException(__FUNCTION__,__LINE__,exception);
5041 if (imageBuffer != (cl_mem) NULL)
5042 clEnv->library->clReleaseMemObject(imageBuffer);
5043 if (filteredImageBuffer != (cl_mem) NULL)
5044 clEnv->library->clReleaseMemObject(filteredImageBuffer);
5045 if (kernel != NULL) kernel=DestroyKernelInfo(kernel);
5046 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer);
5047 if (unsharpMaskKernel!=NULL) RelinquishOpenCLKernel(clEnv, unsharpMaskKernel);
5048 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue);
5049 if ((outputReady == MagickFalse) && (filteredImage != NULL))
5050 filteredImage=(
Image *) DestroyImage(filteredImage);
5051 return(filteredImage);
5054MagickPrivate
Image *AccelerateUnsharpMaskImage(
const Image *image,
5055 const ChannelType channel,
const double radius,
const double sigma,
5056 const double gain,
const double threshold,
ExceptionInfo *exception)
5061 assert(image != NULL);
5064 if ((checkOpenCLEnvironment(exception) == MagickFalse) ||
5065 (checkAccelerateCondition(image, channel) == MagickFalse))
5069 filteredImage = ComputeUnsharpMaskImageSingle(image,radius,sigma,gain,threshold, 0, exception);
5071 filteredImage = ComputeUnsharpMaskImage(image,channel,radius,sigma,gain,threshold,exception);
5073 return(filteredImage);
5076static Image *ComputeWaveletDenoiseImage(
const Image *image,
5095 filteredImageBuffer,
5116 filteredImage = NULL;
5119 filteredImageBuffer = NULL;
5120 denoiseKernel = NULL;
5122 outputReady = MagickFalse;
5124 clEnv = GetDefaultOpenCLEnv();
5127 if (paramMatchesValue(clEnv,MAGICK_OPENCL_ENV_PARAM_DEVICE_NAME,
5128 "Intel(R) HD Graphics",exception) != MagickFalse)
5131 context = GetOpenCLContext(clEnv);
5132 queue = AcquireOpenCLCommandQueue(clEnv);
5134 filteredImage = CloneImage(image,0,0,MagickTrue, exception);
5135 if (filteredImage == (
Image *) NULL)
5138 imageBuffer = GetAuthenticOpenCLBuffer(image,exception);
5139 if (imageBuffer == (cl_mem) NULL)
5141 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
5142 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
5145 filteredImageBuffer = GetAuthenticOpenCLBuffer(filteredImage,exception);
5146 if (filteredImageBuffer == (cl_mem) NULL)
5148 (void) OpenCLThrowMagickException(exception,GetMagickModule(),
5149 ResourceLimitWarning,
"GetAuthenticOpenCLBuffer failed.",
".");
5154 denoiseKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE,
"WaveletDenoise");
5155 if (denoiseKernel == NULL)
5157 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"AcquireOpenCLKernel failed.",
"'%s'",
".");
5166 const int PASSES = 5;
5167 cl_int width = (cl_int)image->columns;
5168 cl_int height = (cl_int)image->rows;
5169 cl_float thresh = threshold;
5171 passes = (((1.0f * image->columns) * image->rows) + 1999999.0f) / 2000000.0f;
5172 passes = (passes < 1) ? 1 : passes;
5176 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++,
sizeof(cl_mem), (
void *)&imageBuffer);
5177 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++,
sizeof(cl_mem), (
void *)&filteredImageBuffer);
5178 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++,
sizeof(cl_float), (
void *)&thresh);
5179 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++,
sizeof(cl_int), (
void *)&PASSES);
5180 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++,
sizeof(cl_int), (
void *)&width);
5181 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++,
sizeof(cl_int), (
void *)&height);
5183 for (x = 0; x < passes; ++x)
5185 const int TILESIZE = 64;
5186 const int PAD = 1 << (PASSES - 1);
5187 const int SIZE = TILESIZE - 2 * PAD;
5193 gsize[0] = ((width + (SIZE - 1)) / SIZE) * TILESIZE;
5194 gsize[1] = ((((height + (SIZE - 1)) / SIZE) + passes - 1) / passes) * 4;
5195 wsize[0] = TILESIZE;
5198 goffset[1] = x * gsize[1];
5200 events=GetOpenCLEvents(image,&event_count);
5201 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, denoiseKernel, 2, goffset, gsize, wsize, event_count, events, &event);
5202 events=(cl_event *) RelinquishMagickMemory(events);
5203 if (clStatus != CL_SUCCESS)
5205 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning,
"clEnv->library->clEnqueueNDRangeKernel failed.",
"'%s'",
".");
5208 clEnv->library->clFlush(queue);
5209 if (RecordProfileData(clEnv, WaveletDenoiseKernel, event) == MagickFalse)
5211 AddOpenCLEvent(image, event);
5212 AddOpenCLEvent(filteredImage, event);
5214 clEnv->library->clReleaseEvent(event);
5218 outputReady=MagickTrue;
5221 OpenCLLogException(__FUNCTION__, __LINE__, exception);
5223 if (imageBuffer != (cl_mem) NULL)
5224 clEnv->library->clReleaseMemObject(imageBuffer);
5225 if (filteredImageBuffer != (cl_mem) NULL)
5226 clEnv->library->clReleaseMemObject(filteredImageBuffer);
5227 if (denoiseKernel != NULL)
5228 RelinquishOpenCLKernel(clEnv, denoiseKernel);
5230 RelinquishOpenCLCommandQueue(clEnv, queue);
5231 if ((outputReady == MagickFalse) && (filteredImage != NULL))
5232 filteredImage=(
Image *) DestroyImage(filteredImage);
5233 return(filteredImage);
5236MagickPrivate
Image *AccelerateWaveletDenoiseImage(
const Image *image,
5242 assert(image != NULL);
5245 if ((checkAccelerateCondition(image,DefaultChannels) == MagickFalse) ||
5246 (checkOpenCLEnvironment(exception) == MagickFalse))
5247 return (
Image *) NULL;
5249 filteredImage=ComputeWaveletDenoiseImage(image,threshold,exception);
5251 return(filteredImage);