accelerate.c revision a1022602c912967848f91930b2e3e209df631b84
1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% AAA CCCC CCCC EEEEE L EEEEE RRRR AAA TTTTT EEEEE % 7% A A C C E L E R R A A T E % 8% AAAAA C C EEE L EEE RRRR AAAAA T EEE % 9% A A C C E L E R R A A T E % 10% A A CCCC CCCC EEEEE LLLLL EEEEE R R A A T EEEEE % 11% % 12% % 13% MagickCore Acceleration Methods % 14% % 15% Software Design % 16% Cristy % 17% SiuChi Chan % 18% Guansong Zhang % 19% January 2010 % 20% % 21% % 22% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 23% dedicated to making software imaging solutions freely available. % 24% % 25% You may not use this file except in compliance with the License. You may % 26% obtain a copy of the License at % 27% % 28% http://www.imagemagick.org/script/license.php % 29% % 30% Unless required by applicable law or agreed to in writing, software % 31% distributed under the License is distributed on an "AS IS" BASIS, % 32% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 33% See the License for the specific language governing permissions and % 34% limitations under the License. % 35% % 36%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37*/ 38 39/* 40Include declarations. 41*/ 42#include "MagickCore/studio.h" 43#include "MagickCore/accelerate.h" 44#include "MagickCore/accelerate-private.h" 45#include "MagickCore/artifact.h" 46#include "MagickCore/cache.h" 47#include "MagickCore/cache-private.h" 48#include "MagickCore/cache-view.h" 49#include "MagickCore/color-private.h" 50#include "MagickCore/delegate-private.h" 51#include "MagickCore/enhance.h" 52#include "MagickCore/exception.h" 53#include "MagickCore/exception-private.h" 54#include "MagickCore/gem.h" 55#include "MagickCore/image.h" 56#include "MagickCore/image-private.h" 57#include "MagickCore/linked-list.h" 58#include "MagickCore/list.h" 59#include "MagickCore/memory_.h" 60#include "MagickCore/monitor-private.h" 61#include "MagickCore/accelerate.h" 62#include "MagickCore/opencl.h" 63#include "MagickCore/opencl-private.h" 64#include "MagickCore/option.h" 65#include "MagickCore/pixel-accessor.h" 66#include "MagickCore/pixel-private.h" 67#include "MagickCore/prepress.h" 68#include "MagickCore/quantize.h" 69#include "MagickCore/quantum-private.h" 70#include "MagickCore/random_.h" 71#include "MagickCore/random-private.h" 72#include "MagickCore/registry.h" 73#include "MagickCore/resize.h" 74#include "MagickCore/resize-private.h" 75#include "MagickCore/semaphore.h" 76#include "MagickCore/splay-tree.h" 77#include "MagickCore/statistic.h" 78#include "MagickCore/string_.h" 79#include "MagickCore/string-private.h" 80#include "MagickCore/token.h" 81 82#ifdef MAGICKCORE_CLPERFMARKER 83#include "CLPerfMarker.h" 84#endif 85 86#define MAGICK_MAX(x,y) (((x) >= (y))?(x):(y)) 87#define MAGICK_MIN(x,y) (((x) <= (y))?(x):(y)) 88 89#if defined(MAGICKCORE_OPENCL_SUPPORT) 90 91/* 92 Define declarations. 93*/ 94#define ALIGNED(pointer,type) ((((size_t)(pointer)) & (sizeof(type)-1)) == 0) 95 96/* 97 Static declarations. 98*/ 99static const ResizeWeightingFunctionType supportedResizeWeighting[] = 100{ 101 BoxWeightingFunction, 102 TriangleWeightingFunction, 103 HannWeightingFunction, 104 HammingWeightingFunction, 105 BlackmanWeightingFunction, 106 CubicBCWeightingFunction, 107 SincWeightingFunction, 108 SincFastWeightingFunction, 109 LastWeightingFunction 110}; 111 112/* 113 Forward declarations. 114*/ 115static Image *ComputeUnsharpMaskImageSingle(const Image *image, 116 const double radius,const double sigma,const double gain, 117 const double threshold,int blurOnly,ExceptionInfo *exception); 118 119/* 120 Helper functions. 121*/ 122static MagickBooleanType checkAccelerateCondition(const Image* image) 123{ 124 /* check if the image's colorspace is supported */ 125 if (image->colorspace != RGBColorspace && 126 image->colorspace != sRGBColorspace && 127 image->colorspace != GRAYColorspace) 128 return(MagickFalse); 129 130 /* check if the virtual pixel method is compatible with the OpenCL implementation */ 131 if ((GetImageVirtualPixelMethod(image) != UndefinedVirtualPixelMethod) && 132 (GetImageVirtualPixelMethod(image) != EdgeVirtualPixelMethod)) 133 return(MagickFalse); 134 135 /* check if the image has read / write mask */ 136 if (image->read_mask != MagickFalse || image->write_mask != MagickFalse) 137 return(MagickFalse); 138 139 if (image->number_channels > 4) 140 return(MagickFalse); 141 142 /* check if pixel order is R */ 143 if ((GetPixelChannelOffset(image,RedPixelChannel) != 0) || 144 (GetPixelRedTraits(image) == UndefinedPixelTrait)) 145 return(MagickFalse); 146 147 if (image->number_channels == 1) 148 return(MagickTrue); 149 150 /* check if pixel order is RA */ 151 if ((image->number_channels == 2) && 152 (GetPixelChannelOffset(image,AlphaPixelChannel) == 1) && 153 (GetPixelAlphaTraits(image) != UndefinedPixelTrait)) 154 return(MagickTrue); 155 156 if (image->number_channels == 2) 157 return(MagickFalse); 158 159 /* check if pixel order is RGB */ 160 if ((GetPixelChannelOffset(image,GreenPixelChannel) != 1) || 161 (GetPixelGreenTraits(image) == UndefinedPixelTrait) || 162 (GetPixelChannelOffset(image,BluePixelChannel) != 2) || 163 (GetPixelBlueTraits(image) == UndefinedPixelTrait)) 164 return(MagickFalse); 165 166 if (image->number_channels == 3) 167 return(MagickTrue); 168 169 /* check if pixel order is RGBA */ 170 if ((GetPixelChannelOffset(image,AlphaPixelChannel) != 3) || 171 (GetPixelAlphaTraits(image) == UndefinedPixelTrait)) 172 return(MagickFalse); 173 174 return(MagickTrue); 175} 176 177static MagickBooleanType checkAccelerateConditionRGBA(const Image* image) 178{ 179 if (checkAccelerateCondition(image) == MagickFalse) 180 return(MagickFalse); 181 182 /* the order will be RGBA if the image has 4 channels */ 183 if (image->number_channels == 4) 184 return(MagickTrue); 185 186 return(MagickFalse); 187} 188 189static MagickBooleanType checkHistogramCondition(Image *image) 190{ 191 /* ensure this is the only pass get in for now. */ 192 if ((image->channel_mask & SyncChannels) == 0) 193 return MagickFalse; 194 195 if (image->intensity == Rec601LuminancePixelIntensityMethod || 196 image->intensity == Rec709LuminancePixelIntensityMethod) 197 return MagickFalse; 198 199 if (image->colorspace != sRGBColorspace) 200 return MagickFalse; 201 202 return MagickTrue; 203} 204 205static MagickBooleanType checkOpenCLEnvironment(ExceptionInfo* exception) 206{ 207 MagickBooleanType 208 flag; 209 210 MagickCLEnv 211 clEnv; 212 213 clEnv=GetDefaultOpenCLEnv(); 214 215 GetMagickOpenCLEnvParam(clEnv,MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED, 216 sizeof(MagickBooleanType),&flag,exception); 217 if (flag != MagickFalse) 218 return(MagickFalse); 219 220 GetMagickOpenCLEnvParam(clEnv,MAGICK_OPENCL_ENV_PARAM_OPENCL_INITIALIZED, 221 sizeof(MagickBooleanType),&flag,exception); 222 if (flag == MagickFalse) 223 { 224 if (InitOpenCLEnv(clEnv,exception) == MagickFalse) 225 return(MagickFalse); 226 227 GetMagickOpenCLEnvParam(clEnv,MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED, 228 sizeof(MagickBooleanType),&flag,exception); 229 if (flag != MagickFalse) 230 return(MagickFalse); 231 } 232 233 return(MagickTrue); 234} 235 236/* pad the global workgroup size to the next multiple of 237 the local workgroup size */ 238inline static unsigned int padGlobalWorkgroupSizeToLocalWorkgroupSize( 239 const unsigned int orgGlobalSize,const unsigned int localGroupSize) 240{ 241 return ((orgGlobalSize+(localGroupSize-1))/localGroupSize*localGroupSize); 242} 243 244static MagickBooleanType splitImage(const Image* image) 245{ 246 MagickBooleanType 247 split; 248 249 MagickCLEnv 250 clEnv; 251 252 unsigned long 253 allocSize, 254 tempSize; 255 256 clEnv=GetDefaultOpenCLEnv(); 257 258 allocSize=GetOpenCLDeviceMaxMemAllocSize(clEnv); 259 tempSize=(unsigned long) (image->columns * image->rows * 4 * 4); 260 261 split = ((tempSize > allocSize) ? MagickTrue : MagickFalse); 262 return(split); 263} 264 265/* 266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 267% % 268% % 269% % 270% A c c e l e r a t e A d d N o i s e I m a g e % 271% % 272% % 273% % 274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 275*/ 276 277static Image *ComputeAddNoiseImage(const Image *image, 278 const NoiseType noise_type,ExceptionInfo *exception) 279{ 280 CacheView 281 *filteredImage_view, 282 *image_view; 283 284 cl_command_queue 285 queue; 286 287 cl_context 288 context; 289 290 cl_int 291 inputPixelCount, 292 pixelsPerWorkitem, 293 clStatus; 294 295 cl_uint 296 seed0, 297 seed1; 298 299 cl_kernel 300 addNoiseKernel; 301 302 cl_event 303 event; 304 305 cl_mem_flags 306 mem_flags; 307 308 cl_mem 309 filteredImageBuffer, 310 imageBuffer; 311 312 const char 313 *option; 314 315 const void 316 *inputPixels; 317 318 float 319 attenuate; 320 321 MagickBooleanType 322 outputReady; 323 324 MagickCLEnv 325 clEnv; 326 327 MagickSizeType 328 length; 329 330 Image 331 *filteredImage; 332 333 RandomInfo 334 **magick_restrict random_info; 335 336 size_t 337 global_work_size[1], 338 local_work_size[1]; 339 340 unsigned int 341 k, 342 numRandomNumberPerPixel; 343 344#if defined(MAGICKCORE_OPENMP_SUPPORT) 345 unsigned long 346 key; 347#endif 348 349 void 350 *filteredPixels, 351 *hostPtr; 352 353 outputReady = MagickFalse; 354 clEnv = NULL; 355 inputPixels = NULL; 356 filteredImage = NULL; 357 filteredImage_view = NULL; 358 filteredPixels = NULL; 359 context = NULL; 360 imageBuffer = NULL; 361 filteredImageBuffer = NULL; 362 queue = NULL; 363 addNoiseKernel = NULL; 364 365 clEnv = GetDefaultOpenCLEnv(); 366 context = GetOpenCLContext(clEnv); 367 queue = AcquireOpenCLCommandQueue(clEnv); 368 369 image_view=AcquireVirtualCacheView(image,exception); 370 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 371 if (inputPixels == (void *) NULL) 372 { 373 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 374 goto cleanup; 375 } 376 377 if (ALIGNED(inputPixels,CLPixelPacket)) 378 { 379 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 380 } 381 else 382 { 383 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 384 } 385 /* create a CL buffer from image pixel buffer */ 386 length = image->columns * image->rows; 387 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 388 if (clStatus != CL_SUCCESS) 389 { 390 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 391 goto cleanup; 392 } 393 394 395 filteredImage = CloneImage(image,image->columns,image->rows,MagickTrue,exception); 396 assert(filteredImage != NULL); 397 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 398 { 399 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 400 goto cleanup; 401 } 402 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 403 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 404 if (filteredPixels == (void *) NULL) 405 { 406 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 407 goto cleanup; 408 } 409 410 if (ALIGNED(filteredPixels,CLPixelPacket)) 411 { 412 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 413 hostPtr = filteredPixels; 414 } 415 else 416 { 417 mem_flags = CL_MEM_WRITE_ONLY; 418 hostPtr = NULL; 419 } 420 /* create a CL buffer from image pixel buffer */ 421 length = image->columns * image->rows; 422 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 423 if (clStatus != CL_SUCCESS) 424 { 425 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 426 goto cleanup; 427 } 428 429 /* find out how many random numbers needed by pixel */ 430 numRandomNumberPerPixel = 0; 431 { 432 unsigned int numRandPerChannel = 0; 433 switch (noise_type) 434 { 435 case UniformNoise: 436 case ImpulseNoise: 437 case LaplacianNoise: 438 case RandomNoise: 439 default: 440 numRandPerChannel = 1; 441 break; 442 case GaussianNoise: 443 case MultiplicativeGaussianNoise: 444 case PoissonNoise: 445 numRandPerChannel = 2; 446 break; 447 }; 448 449 if ((image->channel_mask & RedChannel) != 0) 450 numRandomNumberPerPixel+=numRandPerChannel; 451 if ((image->channel_mask & GreenChannel) != 0) 452 numRandomNumberPerPixel+=numRandPerChannel; 453 if ((image->channel_mask & BlueChannel) != 0) 454 numRandomNumberPerPixel+=numRandPerChannel; 455 if ((image->channel_mask & AlphaChannel) != 0) 456 numRandomNumberPerPixel+=numRandPerChannel; 457 } 458 459 /* set up the random number generators */ 460 attenuate=1.0; 461 option=GetImageArtifact(image,"attenuate"); 462 if (option != (char *) NULL) 463 attenuate=StringToDouble(option,(char **) NULL); 464 random_info=AcquireRandomInfoThreadSet(); 465#if defined(MAGICKCORE_OPENMP_SUPPORT) 466 key=GetRandomSecretKey(random_info[0]); 467 (void) key; 468#endif 469 470 addNoiseKernel = AcquireOpenCLKernel(clEnv,MAGICK_OPENCL_ACCELERATE,"AddNoise"); 471 472 { 473 cl_uint computeUnitCount; 474 cl_uint workItemCount; 475 clEnv->library->clGetDeviceInfo(clEnv->device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &computeUnitCount, NULL); 476 workItemCount = computeUnitCount * 2 * 256; // 256 work items per group, 2 groups per CU 477 inputPixelCount = (cl_int) (image->columns * image->rows); 478 pixelsPerWorkitem = (inputPixelCount + workItemCount - 1) / workItemCount; 479 pixelsPerWorkitem = ((pixelsPerWorkitem + 3) / 4) * 4; 480 481 local_work_size[0] = 256; 482 global_work_size[0] = workItemCount; 483 } 484 { 485 RandomInfo* randomInfo = AcquireRandomInfo(); 486 const unsigned long* s = GetRandomInfoSeed(randomInfo); 487 seed0 = s[0]; 488 GetPseudoRandomValue(randomInfo); 489 seed1 = s[0]; 490 randomInfo = DestroyRandomInfo(randomInfo); 491 } 492 493 k = 0; 494 clEnv->library->clSetKernelArg(addNoiseKernel,k++,sizeof(cl_mem),(void *)&imageBuffer); 495 clEnv->library->clSetKernelArg(addNoiseKernel,k++,sizeof(cl_mem),(void *)&filteredImageBuffer); 496 clEnv->library->clSetKernelArg(addNoiseKernel,k++,sizeof(cl_uint),(void *)&inputPixelCount); 497 clEnv->library->clSetKernelArg(addNoiseKernel,k++,sizeof(cl_uint),(void *)&pixelsPerWorkitem); 498 clEnv->library->clSetKernelArg(addNoiseKernel,k++,sizeof(ChannelType),(void *)&image->channel_mask); 499 clEnv->library->clSetKernelArg(addNoiseKernel,k++,sizeof(NoiseType),(void *)&noise_type); 500 attenuate=1.0f; 501 option=GetImageArtifact(image,"attenuate"); 502 if (option != (char *) NULL) 503 attenuate=(float)StringToDouble(option,(char **) NULL); 504 clEnv->library->clSetKernelArg(addNoiseKernel,k++,sizeof(float),(void *)&attenuate); 505 clEnv->library->clSetKernelArg(addNoiseKernel,k++,sizeof(cl_uint),(void *)&seed0); 506 clEnv->library->clSetKernelArg(addNoiseKernel,k++,sizeof(cl_uint),(void *)&seed1); 507 clEnv->library->clSetKernelArg(addNoiseKernel,k++,sizeof(unsigned int),(void *)&numRandomNumberPerPixel); 508 509 clEnv->library->clEnqueueNDRangeKernel(queue,addNoiseKernel,1,NULL,global_work_size,NULL,0,NULL,&event); 510 511 RecordProfileData(clEnv,AddNoiseKernel,event); 512 clEnv->library->clReleaseEvent(event); 513 514 if (ALIGNED(filteredPixels,CLPixelPacket)) 515 { 516 length = image->columns * image->rows; 517 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 518 } 519 else 520 { 521 length = image->columns * image->rows; 522 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 523 } 524 if (clStatus != CL_SUCCESS) 525 { 526 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 527 goto cleanup; 528 } 529 530 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 531 532cleanup: 533 OpenCLLogException(__FUNCTION__,__LINE__,exception); 534 535 image_view=DestroyCacheView(image_view); 536 if (filteredImage_view != NULL) 537 filteredImage_view=DestroyCacheView(filteredImage_view); 538 539 if (queue!=NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 540 if (addNoiseKernel!=NULL) RelinquishOpenCLKernel(clEnv, addNoiseKernel); 541 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 542 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 543 if (outputReady == MagickFalse && filteredImage != NULL) 544 filteredImage=DestroyImage(filteredImage); 545 546 return(filteredImage); 547} 548 549MagickExport Image *AccelerateAddNoiseImage(const Image *image, 550 const NoiseType noise_type,ExceptionInfo *exception) 551{ 552 Image 553 *filteredImage; 554 555 assert(image != NULL); 556 assert(exception != (ExceptionInfo *) NULL); 557 558 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 559 (checkOpenCLEnvironment(exception) == MagickFalse)) 560 return NULL; 561 562 filteredImage=ComputeAddNoiseImage(image,noise_type,exception); 563 return(filteredImage); 564} 565 566/* 567%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 568% % 569% % 570% % 571% A c c e l e r a t e B l u r I m a g e % 572% % 573% % 574% % 575%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 576*/ 577 578static Image *ComputeBlurImage(const Image* image,const double radius, 579 const double sigma,ExceptionInfo *exception) 580{ 581 CacheView 582 *filteredImage_view, 583 *image_view; 584 585 char 586 geometry[MagickPathExtent]; 587 588 cl_command_queue 589 queue; 590 591 cl_context 592 context; 593 594 cl_int 595 clStatus; 596 597 cl_kernel 598 blurColumnKernel, 599 blurRowKernel; 600 601 cl_event 602 event; 603 604 cl_mem 605 filteredImageBuffer, 606 imageBuffer, 607 imageKernelBuffer, 608 tempImageBuffer; 609 610 cl_mem_flags 611 mem_flags; 612 613 const void 614 *inputPixels; 615 616 float 617 *kernelBufferPtr; 618 619 Image 620 *filteredImage; 621 622 MagickBooleanType 623 outputReady; 624 625 MagickCLEnv 626 clEnv; 627 628 MagickSizeType 629 length; 630 631 KernelInfo 632 *kernel; 633 634 unsigned int 635 i, 636 imageColumns, 637 imageRows, 638 kernelWidth; 639 640 void 641 *filteredPixels, 642 *hostPtr; 643 644 context = NULL; 645 filteredImage = NULL; 646 filteredImage_view = NULL; 647 imageBuffer = NULL; 648 tempImageBuffer = NULL; 649 filteredImageBuffer = NULL; 650 imageKernelBuffer = NULL; 651 blurRowKernel = NULL; 652 blurColumnKernel = NULL; 653 queue = NULL; 654 kernel = NULL; 655 656 outputReady = MagickFalse; 657 658 clEnv = GetDefaultOpenCLEnv(); 659 context = GetOpenCLContext(clEnv); 660 queue = AcquireOpenCLCommandQueue(clEnv); 661 662 /* Create and initialize OpenCL buffers. */ 663 { 664 image_view=AcquireVirtualCacheView(image,exception); 665 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 666 if (inputPixels == (const void *) NULL) 667 { 668 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 669 goto cleanup; 670 } 671 /* If the host pointer is aligned to the size of CLPixelPacket, 672 then use the host buffer directly from the GPU; otherwise, 673 create a buffer on the GPU and copy the data over */ 674 if (ALIGNED(inputPixels,CLPixelPacket)) 675 { 676 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 677 } 678 else 679 { 680 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 681 } 682 /* create a CL buffer from image pixel buffer */ 683 length = image->columns * image->rows; 684 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 685 if (clStatus != CL_SUCCESS) 686 { 687 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 688 goto cleanup; 689 } 690 } 691 692 /* create output */ 693 { 694 filteredImage = CloneImage(image,image->columns,image->rows,MagickTrue,exception); 695 assert(filteredImage != NULL); 696 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 697 { 698 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 699 goto cleanup; 700 } 701 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 702 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 703 if (filteredPixels == (void *) NULL) 704 { 705 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 706 goto cleanup; 707 } 708 709 if (ALIGNED(filteredPixels,CLPixelPacket)) 710 { 711 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 712 hostPtr = filteredPixels; 713 } 714 else 715 { 716 mem_flags = CL_MEM_WRITE_ONLY; 717 hostPtr = NULL; 718 } 719 /* create a CL buffer from image pixel buffer */ 720 length = image->columns * image->rows; 721 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 722 if (clStatus != CL_SUCCESS) 723 { 724 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 725 goto cleanup; 726 } 727 } 728 729 /* create processing kernel */ 730 { 731 (void) FormatLocaleString(geometry,MagickPathExtent,"blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma); 732 kernel=AcquireKernelInfo(geometry,exception); 733 if (kernel == (KernelInfo *) NULL) 734 { 735 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "MemoryAllocationFailed.","."); 736 goto cleanup; 737 } 738 739 imageKernelBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, kernel->width * sizeof(float), NULL, &clStatus); 740 if (clStatus != CL_SUCCESS) 741 { 742 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 743 goto cleanup; 744 } 745 kernelBufferPtr = (float*)clEnv->library->clEnqueueMapBuffer(queue, imageKernelBuffer, CL_TRUE, CL_MAP_WRITE, 0, kernel->width * sizeof(float), 0, NULL, NULL, &clStatus); 746 if (clStatus != CL_SUCCESS) 747 { 748 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueMapBuffer failed.","."); 749 goto cleanup; 750 } 751 752 for (i = 0; i < kernel->width; i++) 753 { 754 kernelBufferPtr[i] = (float) kernel->values[i]; 755 } 756 757 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, imageKernelBuffer, kernelBufferPtr, 0, NULL, NULL); 758 if (clStatus != CL_SUCCESS) 759 { 760 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 761 goto cleanup; 762 } 763 } 764 765 { 766 767 /* create temp buffer */ 768 { 769 length = image->columns * image->rows; 770 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length * 4 * sizeof(float), NULL, &clStatus); 771 if (clStatus != CL_SUCCESS) 772 { 773 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 774 goto cleanup; 775 } 776 } 777 778 /* get the OpenCL kernels */ 779 { 780 blurRowKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "BlurRow"); 781 if (blurRowKernel == NULL) 782 { 783 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 784 goto cleanup; 785 }; 786 787 blurColumnKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "BlurColumn"); 788 if (blurColumnKernel == NULL) 789 { 790 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 791 goto cleanup; 792 }; 793 } 794 795 { 796 /* need logic to decide this value */ 797 int chunkSize = 256; 798 799 { 800 imageColumns = (unsigned int) image->columns; 801 imageRows = (unsigned int) image->rows; 802 803 /* set the kernel arguments */ 804 i = 0; 805 clStatus=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 806 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&tempImageBuffer); 807 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(ChannelType),&image->channel_mask); 808 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&imageKernelBuffer); 809 kernelWidth = (unsigned int) kernel->width; 810 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&kernelWidth); 811 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 812 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&imageRows); 813 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(CLPixelPacket)*(chunkSize+kernel->width),(void *) NULL); 814 if (clStatus != CL_SUCCESS) 815 { 816 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 817 goto cleanup; 818 } 819 } 820 821 /* launch the kernel */ 822 { 823 size_t gsize[2]; 824 size_t wsize[2]; 825 826 gsize[0] = chunkSize*((image->columns+chunkSize-1)/chunkSize); 827 gsize[1] = image->rows; 828 wsize[0] = chunkSize; 829 wsize[1] = 1; 830 831 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurRowKernel, 2, NULL, gsize, wsize, 0, NULL, &event); 832 if (clStatus != CL_SUCCESS) 833 { 834 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 835 goto cleanup; 836 } 837 clEnv->library->clFlush(queue); 838 RecordProfileData(clEnv,BlurRowKernel,event); 839 clEnv->library->clReleaseEvent(event); 840 } 841 } 842 843 { 844 /* need logic to decide this value */ 845 int chunkSize = 256; 846 847 { 848 imageColumns = (unsigned int) image->columns; 849 imageRows = (unsigned int) image->rows; 850 851 /* set the kernel arguments */ 852 i = 0; 853 clStatus=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_mem),(void *)&tempImageBuffer); 854 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_mem),(void *)&filteredImageBuffer); 855 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(ChannelType),&image->channel_mask); 856 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_mem),(void *)&imageKernelBuffer); 857 kernelWidth = (unsigned int) kernel->width; 858 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&kernelWidth); 859 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 860 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&imageRows); 861 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_float4)*(chunkSize+kernel->width),(void *) NULL); 862 if (clStatus != CL_SUCCESS) 863 { 864 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 865 goto cleanup; 866 } 867 } 868 869 /* launch the kernel */ 870 { 871 size_t gsize[2]; 872 size_t wsize[2]; 873 874 gsize[0] = image->columns; 875 gsize[1] = chunkSize*((image->rows+chunkSize-1)/chunkSize); 876 wsize[0] = 1; 877 wsize[1] = chunkSize; 878 879 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurColumnKernel, 2, NULL, gsize, wsize, 0, NULL, &event); 880 if (clStatus != CL_SUCCESS) 881 { 882 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 883 goto cleanup; 884 } 885 clEnv->library->clFlush(queue); 886 RecordProfileData(clEnv,BlurColumnKernel,event); 887 clEnv->library->clReleaseEvent(event); 888 } 889 } 890 891 } 892 893 /* get result */ 894 if (ALIGNED(filteredPixels,CLPixelPacket)) 895 { 896 length = image->columns * image->rows; 897 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 898 } 899 else 900 { 901 length = image->columns * image->rows; 902 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 903 } 904 if (clStatus != CL_SUCCESS) 905 { 906 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 907 goto cleanup; 908 } 909 910 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 911 912cleanup: 913 OpenCLLogException(__FUNCTION__,__LINE__,exception); 914 915 image_view=DestroyCacheView(image_view); 916 if (filteredImage_view != NULL) 917 filteredImage_view=DestroyCacheView(filteredImage_view); 918 919 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 920 if (tempImageBuffer!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer); 921 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 922 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer); 923 if (blurRowKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurRowKernel); 924 if (blurColumnKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurColumnKernel); 925 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 926 if (kernel!=NULL) DestroyKernelInfo(kernel); 927 if (outputReady == MagickFalse && filteredImage != NULL) 928 filteredImage=DestroyImage(filteredImage); 929 return(filteredImage); 930} 931 932static Image* ComputeBlurImageSection(const Image* image, 933 const double radius,const double sigma,ExceptionInfo *exception) 934{ 935 CacheView 936 *filteredImage_view, 937 *image_view; 938 939 char 940 geometry[MagickPathExtent]; 941 942 cl_command_queue 943 queue; 944 945 cl_int 946 clStatus; 947 948 cl_kernel 949 blurColumnKernel, 950 blurRowKernel; 951 952 cl_event 953 event; 954 955 cl_mem 956 imageBuffer, 957 tempImageBuffer, 958 filteredImageBuffer, 959 imageKernelBuffer; 960 961 cl_mem_flags 962 mem_flags; 963 964 cl_context 965 context; 966 967 const void 968 *inputPixels; 969 970 float 971 *kernelBufferPtr; 972 973 Image 974 *filteredImage; 975 976 KernelInfo 977 *kernel; 978 979 MagickBooleanType 980 outputReady; 981 982 MagickCLEnv 983 clEnv; 984 985 MagickSizeType 986 length; 987 988 unsigned int 989 i, 990 imageColumns, 991 imageRows, 992 kernelWidth; 993 994 void 995 *filteredPixels, 996 *hostPtr; 997 998 context = NULL; 999 filteredImage = NULL; 1000 filteredImage_view = NULL; 1001 imageBuffer = NULL; 1002 tempImageBuffer = NULL; 1003 filteredImageBuffer = NULL; 1004 imageKernelBuffer = NULL; 1005 blurRowKernel = NULL; 1006 blurColumnKernel = NULL; 1007 queue = NULL; 1008 kernel = NULL; 1009 1010 outputReady = MagickFalse; 1011 1012 clEnv = GetDefaultOpenCLEnv(); 1013 context = GetOpenCLContext(clEnv); 1014 queue = AcquireOpenCLCommandQueue(clEnv); 1015 1016 /* Create and initialize OpenCL buffers. */ 1017 { 1018 image_view=AcquireVirtualCacheView(image,exception); 1019 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 1020 if (inputPixels == (const void *) NULL) 1021 { 1022 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 1023 goto cleanup; 1024 } 1025 /* If the host pointer is aligned to the size of CLPixelPacket, 1026 then use the host buffer directly from the GPU; otherwise, 1027 create a buffer on the GPU and copy the data over */ 1028 if (ALIGNED(inputPixels,CLPixelPacket)) 1029 { 1030 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 1031 } 1032 else 1033 { 1034 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 1035 } 1036 /* create a CL buffer from image pixel buffer */ 1037 length = image->columns * image->rows; 1038 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 1039 if (clStatus != CL_SUCCESS) 1040 { 1041 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 1042 goto cleanup; 1043 } 1044 } 1045 1046 /* create output */ 1047 { 1048 filteredImage = CloneImage(image,image->columns,image->rows,MagickTrue,exception); 1049 assert(filteredImage != NULL); 1050 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 1051 { 1052 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 1053 goto cleanup; 1054 } 1055 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 1056 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 1057 if (filteredPixels == (void *) NULL) 1058 { 1059 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 1060 goto cleanup; 1061 } 1062 1063 if (ALIGNED(filteredPixels,CLPixelPacket)) 1064 { 1065 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 1066 hostPtr = filteredPixels; 1067 } 1068 else 1069 { 1070 mem_flags = CL_MEM_WRITE_ONLY; 1071 hostPtr = NULL; 1072 } 1073 /* create a CL buffer from image pixel buffer */ 1074 length = image->columns * image->rows; 1075 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 1076 if (clStatus != CL_SUCCESS) 1077 { 1078 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 1079 goto cleanup; 1080 } 1081 } 1082 1083 /* create processing kernel */ 1084 { 1085 (void) FormatLocaleString(geometry,MagickPathExtent,"blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma); 1086 kernel=AcquireKernelInfo(geometry,exception); 1087 if (kernel == (KernelInfo *) NULL) 1088 { 1089 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "MemoryAllocationFailed.","."); 1090 goto cleanup; 1091 } 1092 1093 imageKernelBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, kernel->width * sizeof(float), NULL, &clStatus); 1094 if (clStatus != CL_SUCCESS) 1095 { 1096 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 1097 goto cleanup; 1098 } 1099 kernelBufferPtr = (float*)clEnv->library->clEnqueueMapBuffer(queue, imageKernelBuffer, CL_TRUE, CL_MAP_WRITE, 0, kernel->width * sizeof(float), 0, NULL, NULL, &clStatus); 1100 if (clStatus != CL_SUCCESS) 1101 { 1102 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueMapBuffer failed.","."); 1103 goto cleanup; 1104 } 1105 1106 for (i = 0; i < kernel->width; i++) 1107 { 1108 kernelBufferPtr[i] = (float) kernel->values[i]; 1109 } 1110 1111 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, imageKernelBuffer, kernelBufferPtr, 0, NULL, NULL); 1112 if (clStatus != CL_SUCCESS) 1113 { 1114 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 1115 goto cleanup; 1116 } 1117 } 1118 1119 { 1120 unsigned int offsetRows; 1121 unsigned int sec; 1122 1123 /* create temp buffer */ 1124 { 1125 length = image->columns * (image->rows / 2 + 1 + (kernel->width-1) / 2); 1126 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length * 4 * sizeof(float), NULL, &clStatus); 1127 if (clStatus != CL_SUCCESS) 1128 { 1129 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 1130 goto cleanup; 1131 } 1132 } 1133 1134 /* get the OpenCL kernels */ 1135 { 1136 blurRowKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "BlurSectionRow"); 1137 if (blurRowKernel == NULL) 1138 { 1139 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 1140 goto cleanup; 1141 }; 1142 1143 blurColumnKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "BlurSectionColumn"); 1144 if (blurColumnKernel == NULL) 1145 { 1146 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 1147 goto cleanup; 1148 }; 1149 } 1150 1151 for (sec = 0; sec < 2; sec++) 1152 { 1153 { 1154 /* need logic to decide this value */ 1155 int chunkSize = 256; 1156 1157 { 1158 imageColumns = (unsigned int) image->columns; 1159 if (sec == 0) 1160 imageRows = (unsigned int) (image->rows / 2 + (kernel->width-1) / 2); 1161 else 1162 imageRows = (unsigned int) ((image->rows - image->rows / 2) + (kernel->width-1) / 2); 1163 1164 offsetRows = (unsigned int) (sec * image->rows / 2); 1165 1166 kernelWidth = (unsigned int) kernel->width; 1167 1168 /* set the kernel arguments */ 1169 i = 0; 1170 clStatus=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 1171 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&tempImageBuffer); 1172 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(ChannelType),&image->channel_mask); 1173 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&imageKernelBuffer); 1174 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&kernelWidth); 1175 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 1176 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&imageRows); 1177 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(CLPixelPacket)*(chunkSize+kernel->width),(void *) NULL); 1178 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&offsetRows); 1179 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&sec); 1180 if (clStatus != CL_SUCCESS) 1181 { 1182 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 1183 goto cleanup; 1184 } 1185 } 1186 1187 /* launch the kernel */ 1188 { 1189 size_t gsize[2]; 1190 size_t wsize[2]; 1191 1192 gsize[0] = chunkSize*((imageColumns+chunkSize-1)/chunkSize); 1193 gsize[1] = imageRows; 1194 wsize[0] = chunkSize; 1195 wsize[1] = 1; 1196 1197 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurRowKernel, 2, NULL, gsize, wsize, 0, NULL, &event); 1198 if (clStatus != CL_SUCCESS) 1199 { 1200 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 1201 goto cleanup; 1202 } 1203 clEnv->library->clFlush(queue); 1204 RecordProfileData(clEnv,BlurRowKernel,event); 1205 clEnv->library->clReleaseEvent(event); 1206 } 1207 } 1208 1209 { 1210 /* need logic to decide this value */ 1211 int chunkSize = 256; 1212 1213 { 1214 imageColumns = (unsigned int) image->columns; 1215 if (sec == 0) 1216 imageRows = (unsigned int) (image->rows / 2); 1217 else 1218 imageRows = (unsigned int) ((image->rows - image->rows / 2)); 1219 1220 offsetRows = (unsigned int) (sec * image->rows / 2); 1221 1222 kernelWidth = (unsigned int) kernel->width; 1223 1224 /* set the kernel arguments */ 1225 i = 0; 1226 clStatus=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_mem),(void *)&tempImageBuffer); 1227 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_mem),(void *)&filteredImageBuffer); 1228 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(ChannelType),&image->channel_mask); 1229 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_mem),(void *)&imageKernelBuffer); 1230 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&kernelWidth); 1231 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 1232 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&imageRows); 1233 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_float4)*(chunkSize+kernel->width),(void *) NULL); 1234 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&offsetRows); 1235 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&sec); 1236 if (clStatus != CL_SUCCESS) 1237 { 1238 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 1239 goto cleanup; 1240 } 1241 } 1242 1243 /* launch the kernel */ 1244 { 1245 size_t gsize[2]; 1246 size_t wsize[2]; 1247 1248 gsize[0] = imageColumns; 1249 gsize[1] = chunkSize*((imageRows+chunkSize-1)/chunkSize); 1250 wsize[0] = 1; 1251 wsize[1] = chunkSize; 1252 1253 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurColumnKernel, 2, NULL, gsize, wsize, 0, NULL, &event); 1254 if (clStatus != CL_SUCCESS) 1255 { 1256 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 1257 goto cleanup; 1258 } 1259 clEnv->library->clFlush(queue); 1260 RecordProfileData(clEnv,BlurColumnKernel,event); 1261 clEnv->library->clReleaseEvent(event); 1262 } 1263 } 1264 } 1265 1266 } 1267 1268 /* get result */ 1269 if (ALIGNED(filteredPixels,CLPixelPacket)) 1270 { 1271 length = image->columns * image->rows; 1272 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 1273 } 1274 else 1275 { 1276 length = image->columns * image->rows; 1277 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 1278 } 1279 if (clStatus != CL_SUCCESS) 1280 { 1281 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 1282 goto cleanup; 1283 } 1284 1285 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 1286 1287cleanup: 1288 OpenCLLogException(__FUNCTION__,__LINE__,exception); 1289 1290 image_view=DestroyCacheView(image_view); 1291 if (filteredImage_view != NULL) 1292 filteredImage_view=DestroyCacheView(filteredImage_view); 1293 1294 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 1295 if (tempImageBuffer!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer); 1296 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 1297 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer); 1298 if (blurRowKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurRowKernel); 1299 if (blurColumnKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurColumnKernel); 1300 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 1301 if (kernel!=NULL) DestroyKernelInfo(kernel); 1302 if (outputReady == MagickFalse) 1303 { 1304 if (filteredImage != NULL) 1305 { 1306 DestroyImage(filteredImage); 1307 filteredImage = NULL; 1308 } 1309 } 1310 return filteredImage; 1311} 1312 1313static Image* ComputeBlurImageSingle(const Image* image, 1314 const double radius,const double sigma,ExceptionInfo *exception) 1315{ 1316 return ComputeUnsharpMaskImageSingle(image,radius,sigma,0.0,0.0,1,exception); 1317} 1318 1319MagickExport Image* AccelerateBlurImage(const Image *image, 1320 const double radius,const double sigma,ExceptionInfo *exception) 1321{ 1322 Image 1323 *filteredImage; 1324 1325 assert(image != NULL); 1326 assert(exception != (ExceptionInfo *) NULL); 1327 1328 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 1329 (checkOpenCLEnvironment(exception) == MagickFalse)) 1330 return NULL; 1331 1332 if (radius < 12.1) 1333 filteredImage=ComputeBlurImageSingle(image,radius,sigma,exception); 1334 else if (splitImage(image) && (image->rows / 2 > radius)) 1335 filteredImage=ComputeBlurImageSection(image,radius,sigma,exception); 1336 else 1337 filteredImage=ComputeBlurImage(image,radius,sigma,exception); 1338 return(filteredImage); 1339} 1340 1341/* 1342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1343% % 1344% % 1345% % 1346% A c c e l e r a t e C o m p o s i t e I m a g e % 1347% % 1348% % 1349% % 1350%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1351*/ 1352 1353static MagickBooleanType LaunchCompositeKernel(MagickCLEnv clEnv, 1354 cl_command_queue queue,cl_mem imageBuffer,const unsigned int inputWidth, 1355 const unsigned int inputHeight,const unsigned int matte, 1356 const ChannelType channel,const CompositeOperator compose, 1357 const cl_mem compositeImageBuffer,const unsigned int compositeWidth, 1358 const unsigned int compositeHeight,const float destination_dissolve, 1359 const float source_dissolve,ExceptionInfo *magick_unused(exception)) 1360{ 1361 cl_int 1362 clStatus; 1363 1364 cl_kernel 1365 compositeKernel; 1366 1367 cl_event 1368 event; 1369 1370 int 1371 k; 1372 1373 size_t 1374 global_work_size[2], 1375 local_work_size[2]; 1376 1377 unsigned int 1378 composeOp; 1379 1380 magick_unreferenced(exception); 1381 1382 compositeKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, 1383 "Composite"); 1384 1385 k = 0; 1386 clStatus=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(cl_mem),(void*)&imageBuffer); 1387 clStatus|=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(unsigned int),(void*)&inputWidth); 1388 clStatus|=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(unsigned int),(void*)&inputHeight); 1389 clStatus|=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(cl_mem),(void*)&compositeImageBuffer); 1390 clStatus|=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(unsigned int),(void*)&compositeWidth); 1391 clStatus|=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(unsigned int),(void*)&compositeHeight); 1392 composeOp = (unsigned int)compose; 1393 clStatus|=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(unsigned int),(void*)&composeOp); 1394 clStatus|=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(ChannelType),(void*)&channel); 1395 clStatus|=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(unsigned int),(void*)&matte); 1396 clStatus|=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(float),(void*)&destination_dissolve); 1397 clStatus|=clEnv->library->clSetKernelArg(compositeKernel,k++,sizeof(float),(void*)&source_dissolve); 1398 1399 if (clStatus!=CL_SUCCESS) 1400 return MagickFalse; 1401 1402 local_work_size[0] = 64; 1403 local_work_size[1] = 1; 1404 1405 global_work_size[0] = padGlobalWorkgroupSizeToLocalWorkgroupSize(inputWidth, 1406 (unsigned int) local_work_size[0]); 1407 global_work_size[1] = inputHeight; 1408 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, compositeKernel, 2, NULL, 1409 global_work_size, local_work_size, 0, NULL, &event); 1410 1411 RecordProfileData(clEnv,CompositeKernel,event); 1412 clEnv->library->clReleaseEvent(event); 1413 1414 RelinquishOpenCLKernel(clEnv, compositeKernel); 1415 1416 return((clStatus==CL_SUCCESS) ? MagickTrue : MagickFalse); 1417} 1418 1419static MagickBooleanType ComputeCompositeImage(Image *image, 1420 const CompositeOperator compose,const Image *compositeImage, 1421 const float destination_dissolve,const float source_dissolve,ExceptionInfo *exception) 1422{ 1423 CacheView 1424 *image_view; 1425 1426 cl_command_queue 1427 queue; 1428 1429 cl_context 1430 context; 1431 1432 cl_int 1433 clStatus; 1434 1435 cl_mem_flags 1436 mem_flags; 1437 1438 cl_mem 1439 compositeImageBuffer, 1440 imageBuffer; 1441 1442 const void 1443 *composePixels; 1444 1445 MagickBooleanType 1446 outputReady, 1447 status; 1448 1449 MagickCLEnv 1450 clEnv; 1451 1452 MagickSizeType 1453 length; 1454 1455 void 1456 *inputPixels; 1457 1458 status = MagickFalse; 1459 outputReady = MagickFalse; 1460 composePixels = NULL; 1461 imageBuffer = NULL; 1462 compositeImageBuffer = NULL; 1463 1464 clEnv = GetDefaultOpenCLEnv(); 1465 context = GetOpenCLContext(clEnv); 1466 queue = AcquireOpenCLCommandQueue(clEnv); 1467 1468 /* Create and initialize OpenCL buffers. */ 1469 image_view=AcquireAuthenticCacheView(image,exception); 1470 inputPixels=GetCacheViewAuthenticPixels(image_view,0,0,image->columns,image->rows,exception); 1471 if (inputPixels == (void *) NULL) 1472 { 1473 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, 1474 "UnableToReadPixelCache.","`%s'",image->filename); 1475 goto cleanup; 1476 } 1477 1478 /* If the host pointer is aligned to the size of CLPixelPacket, 1479 then use the host buffer directly from the GPU; otherwise, 1480 create a buffer on the GPU and copy the data over */ 1481 if (ALIGNED(inputPixels,CLPixelPacket)) 1482 { 1483 mem_flags = CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR; 1484 } 1485 else 1486 { 1487 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 1488 } 1489 /* create a CL buffer from image pixel buffer */ 1490 length = image->columns * image->rows; 1491 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, 1492 length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 1493 if (clStatus != CL_SUCCESS) 1494 { 1495 (void) OpenCLThrowMagickException(exception, GetMagickModule(), 1496 ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 1497 goto cleanup; 1498 } 1499 1500 1501 /* Create and initialize OpenCL buffers. */ 1502 composePixels = AcquirePixelCachePixels(compositeImage, &length, exception); 1503 if (composePixels == (void *) NULL) 1504 { 1505 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, 1506 "UnableToReadPixelCache.","`%s'",compositeImage->filename); 1507 goto cleanup; 1508 } 1509 1510 /* If the host pointer is aligned to the size of CLPixelPacket, 1511 then use the host buffer directly from the GPU; otherwise, 1512 create a buffer on the GPU and copy the data over */ 1513 if (ALIGNED(composePixels,CLPixelPacket)) 1514 { 1515 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 1516 } 1517 else 1518 { 1519 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 1520 } 1521 /* create a CL buffer from image pixel buffer */ 1522 length = compositeImage->columns * compositeImage->rows; 1523 compositeImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, 1524 length * sizeof(CLPixelPacket), (void*)composePixels, &clStatus); 1525 if (clStatus != CL_SUCCESS) 1526 { 1527 (void) OpenCLThrowMagickException(exception, GetMagickModule(), 1528 ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 1529 goto cleanup; 1530 } 1531 1532 status = LaunchCompositeKernel(clEnv,queue,imageBuffer, 1533 (unsigned int) image->columns, 1534 (unsigned int) image->rows, 1535 (unsigned int) (image->alpha_trait > CopyPixelTrait) ? 1 : 0, 1536 image->channel_mask, compose, compositeImageBuffer, 1537 (unsigned int) compositeImage->columns, 1538 (unsigned int) compositeImage->rows, 1539 destination_dissolve,source_dissolve, 1540 exception); 1541 1542 if (status==MagickFalse) 1543 goto cleanup; 1544 1545 length = image->columns * image->rows; 1546 if (ALIGNED(inputPixels,CLPixelPacket)) 1547 { 1548 clEnv->library->clEnqueueMapBuffer(queue, imageBuffer, CL_TRUE, 1549 CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, 1550 NULL, &clStatus); 1551 } 1552 else 1553 { 1554 clStatus = clEnv->library->clEnqueueReadBuffer(queue, imageBuffer, CL_TRUE, 0, 1555 length * sizeof(CLPixelPacket), inputPixels, 0, NULL, NULL); 1556 } 1557 if (clStatus==CL_SUCCESS) 1558 outputReady=SyncCacheViewAuthenticPixels(image_view,exception); 1559 1560cleanup: 1561 1562 image_view=DestroyCacheView(image_view); 1563 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 1564 if (compositeImageBuffer!=NULL) clEnv->library->clReleaseMemObject(compositeImageBuffer); 1565 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 1566 1567 return(outputReady); 1568} 1569 1570MagickExport MagickBooleanType AccelerateCompositeImage(Image *image, 1571 const CompositeOperator compose,const Image *composite, 1572 const float destination_dissolve,const float source_dissolve, 1573 ExceptionInfo *exception) 1574{ 1575 MagickBooleanType 1576 status; 1577 1578 assert(image != NULL); 1579 assert(exception != (ExceptionInfo *) NULL); 1580 1581 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 1582 (checkOpenCLEnvironment(exception) == MagickFalse)) 1583 return(MagickFalse); 1584 1585 /* only support images with the size for now */ 1586 if ((image->columns != composite->columns) || 1587 (image->rows != composite->rows)) 1588 return MagickFalse; 1589 1590 switch(compose) 1591 { 1592 case ColorDodgeCompositeOp: 1593 case BlendCompositeOp: 1594 break; 1595 default: 1596 // unsupported compose operator, quit 1597 return MagickFalse; 1598 }; 1599 1600 status=ComputeCompositeImage(image,compose,composite,destination_dissolve, 1601 source_dissolve,exception); 1602 return(status); 1603} 1604 1605/* 1606%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1607% % 1608% % 1609% % 1610% A c c e l e r a t e C o n t r a s t I m a g e % 1611% % 1612% % 1613% % 1614%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1615*/ 1616 1617static MagickBooleanType ComputeContrastImage(Image *image, 1618 const MagickBooleanType sharpen,ExceptionInfo *exception) 1619{ 1620 CacheView 1621 *image_view; 1622 1623 cl_command_queue 1624 queue; 1625 1626 cl_context 1627 context; 1628 1629 cl_int 1630 clStatus; 1631 1632 cl_kernel 1633 filterKernel; 1634 1635 cl_event 1636 event; 1637 1638 cl_mem 1639 imageBuffer; 1640 1641 cl_mem_flags 1642 mem_flags; 1643 1644 MagickBooleanType 1645 outputReady; 1646 1647 MagickCLEnv 1648 clEnv; 1649 1650 MagickSizeType 1651 length; 1652 1653 size_t 1654 global_work_size[2]; 1655 1656 unsigned int 1657 i, 1658 uSharpen; 1659 1660 void 1661 *inputPixels; 1662 1663 outputReady = MagickFalse; 1664 clEnv = NULL; 1665 inputPixels = NULL; 1666 context = NULL; 1667 imageBuffer = NULL; 1668 filterKernel = NULL; 1669 queue = NULL; 1670 1671 clEnv = GetDefaultOpenCLEnv(); 1672 context = GetOpenCLContext(clEnv); 1673 1674 /* Create and initialize OpenCL buffers. */ 1675 image_view=AcquireAuthenticCacheView(image,exception); 1676 inputPixels=GetCacheViewAuthenticPixels(image_view,0,0,image->columns,image->rows,exception); 1677 if (inputPixels == (void *) NULL) 1678 { 1679 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 1680 goto cleanup; 1681 } 1682 1683 /* If the host pointer is aligned to the size of CLPixelPacket, 1684 then use the host buffer directly from the GPU; otherwise, 1685 create a buffer on the GPU and copy the data over */ 1686 if (ALIGNED(inputPixels,CLPixelPacket)) 1687 { 1688 mem_flags = CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR; 1689 } 1690 else 1691 { 1692 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 1693 } 1694 /* create a CL buffer from image pixel buffer */ 1695 length = image->columns * image->rows; 1696 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 1697 if (clStatus != CL_SUCCESS) 1698 { 1699 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 1700 goto cleanup; 1701 } 1702 1703 filterKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "Contrast"); 1704 if (filterKernel == NULL) 1705 { 1706 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 1707 goto cleanup; 1708 } 1709 1710 i = 0; 1711 clStatus=clEnv->library->clSetKernelArg(filterKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 1712 1713 uSharpen = (sharpen == MagickFalse)?0:1; 1714 clStatus|=clEnv->library->clSetKernelArg(filterKernel,i++,sizeof(cl_uint),&uSharpen); 1715 if (clStatus != CL_SUCCESS) 1716 { 1717 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 1718 goto cleanup; 1719 } 1720 1721 global_work_size[0] = image->columns; 1722 global_work_size[1] = image->rows; 1723 /* launch the kernel */ 1724 queue = AcquireOpenCLCommandQueue(clEnv); 1725 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, filterKernel, 2, NULL, global_work_size, NULL, 0, NULL, &event); 1726 if (clStatus != CL_SUCCESS) 1727 { 1728 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 1729 goto cleanup; 1730 } 1731 clEnv->library->clFlush(queue); 1732 RecordProfileData(clEnv,ContrastKernel,event); 1733 clEnv->library->clReleaseEvent(event); 1734 1735 if (ALIGNED(inputPixels,CLPixelPacket)) 1736 { 1737 length = image->columns * image->rows; 1738 clEnv->library->clEnqueueMapBuffer(queue, imageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 1739 } 1740 else 1741 { 1742 length = image->columns * image->rows; 1743 clStatus = clEnv->library->clEnqueueReadBuffer(queue, imageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), inputPixels, 0, NULL, NULL); 1744 } 1745 if (clStatus != CL_SUCCESS) 1746 { 1747 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 1748 goto cleanup; 1749 } 1750 outputReady=SyncCacheViewAuthenticPixels(image_view,exception); 1751 1752cleanup: 1753 OpenCLLogException(__FUNCTION__,__LINE__,exception); 1754 1755 image_view=DestroyCacheView(image_view); 1756 1757 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 1758 if (filterKernel!=NULL) RelinquishOpenCLKernel(clEnv, filterKernel); 1759 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 1760 return(outputReady); 1761} 1762 1763MagickExport MagickBooleanType AccelerateContrastImage(Image *image, 1764 const MagickBooleanType sharpen,ExceptionInfo *exception) 1765{ 1766 MagickBooleanType 1767 status; 1768 1769 assert(image != NULL); 1770 assert(exception != (ExceptionInfo *) NULL); 1771 1772 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 1773 (checkOpenCLEnvironment(exception) == MagickFalse)) 1774 return(MagickFalse); 1775 1776 status=ComputeContrastImage(image,sharpen,exception); 1777 return(status); 1778} 1779 1780/* 1781%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1782% % 1783% % 1784% % 1785% A c c e l e r a t e C o n t r a s t S t r e t c h I m a g e % 1786% % 1787% % 1788% % 1789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1790*/ 1791 1792static MagickBooleanType LaunchHistogramKernel(MagickCLEnv clEnv, 1793 cl_command_queue queue,cl_mem imageBuffer,cl_mem histogramBuffer, 1794 Image *image,const ChannelType channel,ExceptionInfo *exception) 1795{ 1796 MagickBooleanType 1797 outputReady; 1798 1799 cl_int 1800 clStatus, 1801 colorspace, 1802 method; 1803 1804 cl_kernel 1805 histogramKernel; 1806 1807 cl_event 1808 event; 1809 1810 register ssize_t 1811 i; 1812 1813 size_t 1814 global_work_size[2]; 1815 1816 histogramKernel = NULL; 1817 1818 outputReady = MagickFalse; 1819 method = image->intensity; 1820 colorspace = image->colorspace; 1821 1822 /* get the OpenCL kernel */ 1823 histogramKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "Histogram"); 1824 if (histogramKernel == NULL) 1825 { 1826 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 1827 goto cleanup; 1828 } 1829 1830 /* set the kernel arguments */ 1831 i = 0; 1832 clStatus=clEnv->library->clSetKernelArg(histogramKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 1833 clStatus|=clEnv->library->clSetKernelArg(histogramKernel,i++,sizeof(ChannelType),&channel); 1834 clStatus|=clEnv->library->clSetKernelArg(histogramKernel,i++,sizeof(cl_int),&method); 1835 clStatus|=clEnv->library->clSetKernelArg(histogramKernel,i++,sizeof(cl_int),&colorspace); 1836 clStatus|=clEnv->library->clSetKernelArg(histogramKernel,i++,sizeof(cl_mem),(void *)&histogramBuffer); 1837 if (clStatus != CL_SUCCESS) 1838 { 1839 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 1840 goto cleanup; 1841 } 1842 1843 /* launch the kernel */ 1844 global_work_size[0] = image->columns; 1845 global_work_size[1] = image->rows; 1846 1847 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, histogramKernel, 2, NULL, global_work_size, NULL, 0, NULL, &event); 1848 1849 if (clStatus != CL_SUCCESS) 1850 { 1851 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 1852 goto cleanup; 1853 } 1854 clEnv->library->clFlush(queue); 1855 RecordProfileData(clEnv,HistogramKernel,event); 1856 clEnv->library->clReleaseEvent(event); 1857 1858 outputReady = MagickTrue; 1859 1860cleanup: 1861 OpenCLLogException(__FUNCTION__,__LINE__,exception); 1862 1863 if (histogramKernel!=NULL) 1864 RelinquishOpenCLKernel(clEnv, histogramKernel); 1865 1866 return(outputReady); 1867} 1868 1869static MagickBooleanType ComputeContrastStretchImage(Image *image, 1870 const double black_point,const double white_point,ExceptionInfo *exception) 1871{ 1872#define ContrastStretchImageTag "ContrastStretch/Image" 1873#define MaxRange(color) ((MagickRealType) ScaleQuantumToMap((Quantum) (color))) 1874 1875 CacheView 1876 *image_view; 1877 1878 cl_command_queue 1879 queue; 1880 1881 cl_context 1882 context; 1883 1884 cl_int 1885 clStatus; 1886 1887 cl_mem_flags 1888 mem_flags; 1889 1890 cl_mem 1891 histogramBuffer, 1892 imageBuffer, 1893 stretchMapBuffer; 1894 1895 cl_kernel 1896 histogramKernel, 1897 stretchKernel; 1898 1899 cl_event 1900 event; 1901 1902 cl_uint4 1903 *histogram; 1904 1905 double 1906 intensity; 1907 1908 FloatPixelPacket 1909 black, 1910 white; 1911 1912 MagickBooleanType 1913 outputReady, 1914 status; 1915 1916 MagickCLEnv 1917 clEnv; 1918 1919 MagickSizeType 1920 length; 1921 1922 PixelPacket 1923 *stretch_map; 1924 1925 register ssize_t 1926 i; 1927 1928 size_t 1929 global_work_size[2]; 1930 1931 void 1932 *hostPtr, 1933 *inputPixels; 1934 1935 histogram=NULL; 1936 stretch_map=NULL; 1937 inputPixels = NULL; 1938 imageBuffer = NULL; 1939 histogramBuffer = NULL; 1940 stretchMapBuffer = NULL; 1941 histogramKernel = NULL; 1942 stretchKernel = NULL; 1943 context = NULL; 1944 queue = NULL; 1945 outputReady = MagickFalse; 1946 1947 1948 assert(image != (Image *) NULL); 1949 assert(image->signature == MagickCoreSignature); 1950 if (image->debug != MagickFalse) 1951 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1952 1953 //exception=(&image->exception); 1954 1955 /* 1956 * initialize opencl env 1957 */ 1958 clEnv = GetDefaultOpenCLEnv(); 1959 context = GetOpenCLContext(clEnv); 1960 queue = AcquireOpenCLCommandQueue(clEnv); 1961 1962 /* 1963 Allocate and initialize histogram arrays. 1964 */ 1965 histogram=(cl_uint4 *) AcquireQuantumMemory(MaxMap+1UL, sizeof(*histogram)); 1966 1967 if (histogram == (cl_uint4 *) NULL) 1968 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); 1969 1970 /* reset histogram */ 1971 (void) ResetMagickMemory(histogram,0,(MaxMap+1)*sizeof(*histogram)); 1972 1973 /* 1974 if (IsGrayImage(image,exception) != MagickFalse) 1975 (void) SetImageColorspace(image,GRAYColorspace); 1976 */ 1977 1978 status=MagickTrue; 1979 1980 1981 /* 1982 Form histogram. 1983 */ 1984 /* Create and initialize OpenCL buffers. */ 1985 /* inputPixels = AcquirePixelCachePixels(image, &length, exception); */ 1986 /* assume this will get a writable image */ 1987 image_view=AcquireAuthenticCacheView(image,exception); 1988 inputPixels=GetCacheViewAuthenticPixels(image_view,0,0,image->columns,image->rows,exception); 1989 1990 if (inputPixels == (void *) NULL) 1991 { 1992 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 1993 goto cleanup; 1994 } 1995 /* If the host pointer is aligned to the size of CLPixelPacket, 1996 then use the host buffer directly from the GPU; otherwise, 1997 create a buffer on the GPU and copy the data over */ 1998 if (ALIGNED(inputPixels,CLPixelPacket)) 1999 { 2000 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 2001 } 2002 else 2003 { 2004 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 2005 } 2006 /* create a CL buffer from image pixel buffer */ 2007 length = image->columns * image->rows; 2008 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 2009 if (clStatus != CL_SUCCESS) 2010 { 2011 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 2012 goto cleanup; 2013 } 2014 2015 /* If the host pointer is aligned to the size of cl_uint, 2016 then use the host buffer directly from the GPU; otherwise, 2017 create a buffer on the GPU and copy the data over */ 2018 if (ALIGNED(histogram,cl_uint4)) 2019 { 2020 mem_flags = CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR; 2021 hostPtr = histogram; 2022 } 2023 else 2024 { 2025 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 2026 hostPtr = histogram; 2027 } 2028 /* create a CL buffer for histogram */ 2029 length = (MaxMap+1); 2030 histogramBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(cl_uint4), hostPtr, &clStatus); 2031 if (clStatus != CL_SUCCESS) 2032 { 2033 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 2034 goto cleanup; 2035 } 2036 2037 status = LaunchHistogramKernel(clEnv, queue, imageBuffer, histogramBuffer, image, image->channel_mask, exception); 2038 if (status == MagickFalse) 2039 goto cleanup; 2040 2041 /* read from the kenel output */ 2042 if (ALIGNED(histogram,cl_uint4)) 2043 { 2044 length = (MaxMap+1); 2045 clEnv->library->clEnqueueMapBuffer(queue, histogramBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(cl_uint4), 0, NULL, NULL, &clStatus); 2046 } 2047 else 2048 { 2049 length = (MaxMap+1); 2050 clStatus = clEnv->library->clEnqueueReadBuffer(queue, histogramBuffer, CL_TRUE, 0, length * sizeof(cl_uint4), histogram, 0, NULL, NULL); 2051 } 2052 if (clStatus != CL_SUCCESS) 2053 { 2054 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 2055 goto cleanup; 2056 } 2057 2058 /* unmap, don't block gpu to use this buffer again. */ 2059 if (ALIGNED(histogram,cl_uint4)) 2060 { 2061 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, histogramBuffer, histogram, 0, NULL, NULL); 2062 if (clStatus != CL_SUCCESS) 2063 { 2064 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 2065 goto cleanup; 2066 } 2067 } 2068 2069 /* recreate input buffer later, in case image updated */ 2070#ifdef RECREATEBUFFER 2071 if (imageBuffer!=NULL) 2072 clEnv->library->clReleaseMemObject(imageBuffer); 2073#endif 2074 2075 /* CPU stuff */ 2076 /* 2077 Find the histogram boundaries by locating the black/white levels. 2078 */ 2079 black.red=0.0; 2080 white.red=MaxRange(QuantumRange); 2081 if ((image->channel_mask & RedChannel) != 0) 2082 { 2083 intensity=0.0; 2084 for (i=0; i <= (ssize_t) MaxMap; i++) 2085 { 2086 intensity+=histogram[i].s[2]; 2087 if (intensity > black_point) 2088 break; 2089 } 2090 black.red=(MagickRealType) i; 2091 intensity=0.0; 2092 for (i=(ssize_t) MaxMap; i != 0; i--) 2093 { 2094 intensity+=histogram[i].s[2]; 2095 if (intensity > ((double) image->columns*image->rows-white_point)) 2096 break; 2097 } 2098 white.red=(MagickRealType) i; 2099 } 2100 black.green=0.0; 2101 white.green=MaxRange(QuantumRange); 2102 if ((image->channel_mask & GreenChannel) != 0) 2103 { 2104 intensity=0.0; 2105 for (i=0; i <= (ssize_t) MaxMap; i++) 2106 { 2107 intensity+=histogram[i].s[2]; 2108 if (intensity > black_point) 2109 break; 2110 } 2111 black.green=(MagickRealType) i; 2112 intensity=0.0; 2113 for (i=(ssize_t) MaxMap; i != 0; i--) 2114 { 2115 intensity+=histogram[i].s[2]; 2116 if (intensity > ((double) image->columns*image->rows-white_point)) 2117 break; 2118 } 2119 white.green=(MagickRealType) i; 2120 } 2121 black.blue=0.0; 2122 white.blue=MaxRange(QuantumRange); 2123 if ((image->channel_mask & BlueChannel) != 0) 2124 { 2125 intensity=0.0; 2126 for (i=0; i <= (ssize_t) MaxMap; i++) 2127 { 2128 intensity+=histogram[i].s[2]; 2129 if (intensity > black_point) 2130 break; 2131 } 2132 black.blue=(MagickRealType) i; 2133 intensity=0.0; 2134 for (i=(ssize_t) MaxMap; i != 0; i--) 2135 { 2136 intensity+=histogram[i].s[2]; 2137 if (intensity > ((double) image->columns*image->rows-white_point)) 2138 break; 2139 } 2140 white.blue=(MagickRealType) i; 2141 } 2142 black.alpha=0.0; 2143 white.alpha=MaxRange(QuantumRange); 2144 if ((image->channel_mask & AlphaChannel) != 0) 2145 { 2146 intensity=0.0; 2147 for (i=0; i <= (ssize_t) MaxMap; i++) 2148 { 2149 intensity+=histogram[i].s[2]; 2150 if (intensity > black_point) 2151 break; 2152 } 2153 black.alpha=(MagickRealType) i; 2154 intensity=0.0; 2155 for (i=(ssize_t) MaxMap; i != 0; i--) 2156 { 2157 intensity+=histogram[i].s[2]; 2158 if (intensity > ((double) image->columns*image->rows-white_point)) 2159 break; 2160 } 2161 white.alpha=(MagickRealType) i; 2162 } 2163 /* 2164 black.index=0.0; 2165 white.index=MaxRange(QuantumRange); 2166 if (((channel & IndexChannel) != 0) && (image->colorspace == CMYKColorspace)) 2167 { 2168 intensity=0.0; 2169 for (i=0; i <= (ssize_t) MaxMap; i++) 2170 { 2171 intensity+=histogram[i].index; 2172 if (intensity > black_point) 2173 break; 2174 } 2175 black.index=(MagickRealType) i; 2176 intensity=0.0; 2177 for (i=(ssize_t) MaxMap; i != 0; i--) 2178 { 2179 intensity+=histogram[i].index; 2180 if (intensity > ((double) image->columns*image->rows-white_point)) 2181 break; 2182 } 2183 white.index=(MagickRealType) i; 2184 } 2185 */ 2186 2187 2188 stretch_map=(PixelPacket *) AcquireQuantumMemory(MaxMap+1UL, 2189 sizeof(*stretch_map)); 2190 2191 if (stretch_map == (PixelPacket *) NULL) 2192 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 2193 image->filename); 2194 2195 /* 2196 Stretch the histogram to create the stretched image mapping. 2197 */ 2198 (void) ResetMagickMemory(stretch_map,0,(MaxMap+1)*sizeof(*stretch_map)); 2199 for (i=0; i <= (ssize_t) MaxMap; i++) 2200 { 2201 if ((image->channel_mask & RedChannel) != 0) 2202 { 2203 if (i < (ssize_t) black.red) 2204 stretch_map[i].red=(Quantum) 0; 2205 else 2206 if (i > (ssize_t) white.red) 2207 stretch_map[i].red=QuantumRange; 2208 else 2209 if (black.red != white.red) 2210 stretch_map[i].red=ScaleMapToQuantum((MagickRealType) (MaxMap* 2211 (i-black.red)/(white.red-black.red))); 2212 } 2213 if ((image->channel_mask & GreenChannel) != 0) 2214 { 2215 if (i < (ssize_t) black.green) 2216 stretch_map[i].green=0; 2217 else 2218 if (i > (ssize_t) white.green) 2219 stretch_map[i].green=QuantumRange; 2220 else 2221 if (black.green != white.green) 2222 stretch_map[i].green=ScaleMapToQuantum((MagickRealType) (MaxMap* 2223 (i-black.green)/(white.green-black.green))); 2224 } 2225 if ((image->channel_mask & BlueChannel) != 0) 2226 { 2227 if (i < (ssize_t) black.blue) 2228 stretch_map[i].blue=0; 2229 else 2230 if (i > (ssize_t) white.blue) 2231 stretch_map[i].blue= QuantumRange; 2232 else 2233 if (black.blue != white.blue) 2234 stretch_map[i].blue=ScaleMapToQuantum((MagickRealType) (MaxMap* 2235 (i-black.blue)/(white.blue-black.blue))); 2236 } 2237 if ((image->channel_mask & AlphaChannel) != 0) 2238 { 2239 if (i < (ssize_t) black.alpha) 2240 stretch_map[i].alpha=0; 2241 else 2242 if (i > (ssize_t) white.alpha) 2243 stretch_map[i].alpha=QuantumRange; 2244 else 2245 if (black.alpha != white.alpha) 2246 stretch_map[i].alpha=ScaleMapToQuantum((MagickRealType) (MaxMap* 2247 (i-black.alpha)/(white.alpha-black.alpha))); 2248 } 2249 /* 2250 if (((channel & IndexChannel) != 0) && 2251 (image->colorspace == CMYKColorspace)) 2252 { 2253 if (i < (ssize_t) black.index) 2254 stretch_map[i].index=0; 2255 else 2256 if (i > (ssize_t) white.index) 2257 stretch_map[i].index=QuantumRange; 2258 else 2259 if (black.index != white.index) 2260 stretch_map[i].index=ScaleMapToQuantum((MagickRealType) (MaxMap* 2261 (i-black.index)/(white.index-black.index))); 2262 } 2263 */ 2264 } 2265 2266 /* 2267 Stretch the image. 2268 */ 2269 if (((image->channel_mask & AlphaChannel) != 0) || (((image->channel_mask & IndexChannel) != 0) && 2270 (image->colorspace == CMYKColorspace))) 2271 image->storage_class=DirectClass; 2272 if (image->storage_class == PseudoClass) 2273 { 2274 /* 2275 Stretch colormap. 2276 */ 2277 for (i=0; i < (ssize_t) image->colors; i++) 2278 { 2279 if ((image->channel_mask & RedChannel) != 0) 2280 { 2281 if (black.red != white.red) 2282 image->colormap[i].red=stretch_map[ 2283 ScaleQuantumToMap(image->colormap[i].red)].red; 2284 } 2285 if ((image->channel_mask & GreenChannel) != 0) 2286 { 2287 if (black.green != white.green) 2288 image->colormap[i].green=stretch_map[ 2289 ScaleQuantumToMap(image->colormap[i].green)].green; 2290 } 2291 if ((image->channel_mask & BlueChannel) != 0) 2292 { 2293 if (black.blue != white.blue) 2294 image->colormap[i].blue=stretch_map[ 2295 ScaleQuantumToMap(image->colormap[i].blue)].blue; 2296 } 2297 if ((image->channel_mask & AlphaChannel) != 0) 2298 { 2299 if (black.alpha != white.alpha) 2300 image->colormap[i].alpha=stretch_map[ 2301 ScaleQuantumToMap(image->colormap[i].alpha)].alpha; 2302 } 2303 } 2304 } 2305 2306 /* 2307 Stretch image. 2308 */ 2309 2310 2311 /* GPU can work on this again, image and equalize map as input 2312 image: uchar4 (CLPixelPacket) 2313 stretch_map: uchar4 (PixelPacket) 2314 black, white: float4 (FloatPixelPacket) */ 2315 2316#ifdef RECREATEBUFFER 2317 /* If the host pointer is aligned to the size of CLPixelPacket, 2318 then use the host buffer directly from the GPU; otherwise, 2319 create a buffer on the GPU and copy the data over */ 2320 if (ALIGNED(inputPixels,CLPixelPacket)) 2321 { 2322 mem_flags = CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR; 2323 } 2324 else 2325 { 2326 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 2327 } 2328 /* create a CL buffer from image pixel buffer */ 2329 length = image->columns * image->rows; 2330 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 2331 if (clStatus != CL_SUCCESS) 2332 { 2333 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 2334 goto cleanup; 2335 } 2336#endif 2337 2338 /* Create and initialize OpenCL buffers. */ 2339 if (ALIGNED(stretch_map, PixelPacket)) 2340 { 2341 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 2342 hostPtr = stretch_map; 2343 } 2344 else 2345 { 2346 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 2347 hostPtr = stretch_map; 2348 } 2349 /* create a CL buffer for stretch_map */ 2350 length = (MaxMap+1); 2351 stretchMapBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(PixelPacket), hostPtr, &clStatus); 2352 if (clStatus != CL_SUCCESS) 2353 { 2354 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 2355 goto cleanup; 2356 } 2357 2358 /* get the OpenCL kernel */ 2359 stretchKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "ContrastStretch"); 2360 if (stretchKernel == NULL) 2361 { 2362 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 2363 goto cleanup; 2364 } 2365 2366 /* set the kernel arguments */ 2367 i = 0; 2368 clStatus=clEnv->library->clSetKernelArg(stretchKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 2369 clStatus|=clEnv->library->clSetKernelArg(stretchKernel,i++,sizeof(ChannelType),&image->channel_mask); 2370 clStatus|=clEnv->library->clSetKernelArg(stretchKernel,i++,sizeof(cl_mem),(void *)&stretchMapBuffer); 2371 clStatus|=clEnv->library->clSetKernelArg(stretchKernel,i++,sizeof(FloatPixelPacket),&white); 2372 clStatus|=clEnv->library->clSetKernelArg(stretchKernel,i++,sizeof(FloatPixelPacket),&black); 2373 if (clStatus != CL_SUCCESS) 2374 { 2375 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 2376 goto cleanup; 2377 } 2378 2379 /* launch the kernel */ 2380 global_work_size[0] = image->columns; 2381 global_work_size[1] = image->rows; 2382 2383 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, stretchKernel, 2, NULL, global_work_size, NULL, 0, NULL, &event); 2384 2385 if (clStatus != CL_SUCCESS) 2386 { 2387 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 2388 goto cleanup; 2389 } 2390 clEnv->library->clFlush(queue); 2391 2392 RecordProfileData(clEnv,ContrastStretchKernel,event); 2393 clEnv->library->clReleaseEvent(event); 2394 2395 /* read the data back */ 2396 if (ALIGNED(inputPixels,CLPixelPacket)) 2397 { 2398 length = image->columns * image->rows; 2399 clEnv->library->clEnqueueMapBuffer(queue, imageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 2400 } 2401 else 2402 { 2403 length = image->columns * image->rows; 2404 clStatus = clEnv->library->clEnqueueReadBuffer(queue, imageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), inputPixels, 0, NULL, NULL); 2405 } 2406 if (clStatus != CL_SUCCESS) 2407 { 2408 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 2409 goto cleanup; 2410 } 2411 2412 outputReady=SyncCacheViewAuthenticPixels(image_view,exception); 2413 2414cleanup: 2415 OpenCLLogException(__FUNCTION__,__LINE__,exception); 2416 2417 image_view=DestroyCacheView(image_view); 2418 2419 if (imageBuffer!=NULL) 2420 clEnv->library->clReleaseMemObject(imageBuffer); 2421 2422 if (stretchMapBuffer!=NULL) 2423 clEnv->library->clReleaseMemObject(stretchMapBuffer); 2424 if (stretch_map!=NULL) 2425 stretch_map=(PixelPacket *) RelinquishMagickMemory(stretch_map); 2426 2427 2428 if (histogramBuffer!=NULL) 2429 clEnv->library->clReleaseMemObject(histogramBuffer); 2430 if (histogram!=NULL) 2431 histogram=(cl_uint4 *) RelinquishMagickMemory(histogram); 2432 2433 2434 if (histogramKernel!=NULL) 2435 RelinquishOpenCLKernel(clEnv, histogramKernel); 2436 if (stretchKernel!=NULL) 2437 RelinquishOpenCLKernel(clEnv, stretchKernel); 2438 2439 if (queue != NULL) 2440 RelinquishOpenCLCommandQueue(clEnv, queue); 2441 2442 return(outputReady); 2443} 2444 2445MagickExport MagickBooleanType AccelerateContrastStretchImage( 2446 Image *image,const double black_point,const double white_point, 2447 ExceptionInfo *exception) 2448{ 2449 MagickBooleanType 2450 status; 2451 2452 assert(image != NULL); 2453 assert(exception != (ExceptionInfo *) NULL); 2454 2455 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 2456 (checkHistogramCondition(image) == MagickFalse) || 2457 (checkOpenCLEnvironment(exception) == MagickFalse)) 2458 return(MagickFalse); 2459 2460 status=ComputeContrastStretchImage(image,black_point,white_point,exception); 2461 return(status); 2462} 2463 2464/* 2465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2466% % 2467% % 2468% % 2469% A c c e l e r a t e C o n v o l v e I m a g e % 2470% % 2471% % 2472% % 2473%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2474*/ 2475 2476static Image *ComputeConvolveImage(const Image* image,const KernelInfo *kernel, 2477 ExceptionInfo *exception) 2478{ 2479 CacheView 2480 *filteredImage_view, 2481 *image_view; 2482 2483 cl_command_queue 2484 queue; 2485 2486 cl_context 2487 context; 2488 2489 cl_kernel 2490 clkernel; 2491 2492 cl_event 2493 event; 2494 2495 cl_int 2496 clStatus; 2497 2498 cl_mem 2499 convolutionKernel, 2500 filteredImageBuffer, 2501 imageBuffer; 2502 2503 cl_mem_flags 2504 mem_flags; 2505 2506 cl_ulong 2507 deviceLocalMemorySize; 2508 2509 const void 2510 *inputPixels; 2511 2512 float 2513 *kernelBufferPtr; 2514 2515 Image 2516 *filteredImage; 2517 2518 MagickBooleanType 2519 outputReady; 2520 2521 MagickCLEnv 2522 clEnv; 2523 2524 MagickSizeType 2525 length; 2526 2527 size_t 2528 global_work_size[3], 2529 localGroupSize[3], 2530 localMemoryRequirement; 2531 2532 unsigned 2533 kernelSize; 2534 2535 unsigned int 2536 filterHeight, 2537 filterWidth, 2538 i, 2539 imageHeight, 2540 imageWidth, 2541 matte; 2542 2543 void 2544 *filteredPixels, 2545 *hostPtr; 2546 2547 /* intialize all CL objects to NULL */ 2548 context = NULL; 2549 imageBuffer = NULL; 2550 filteredImageBuffer = NULL; 2551 convolutionKernel = NULL; 2552 clkernel = NULL; 2553 queue = NULL; 2554 2555 filteredImage = NULL; 2556 filteredImage_view = NULL; 2557 outputReady = MagickFalse; 2558 2559 clEnv = GetDefaultOpenCLEnv(); 2560 context = GetOpenCLContext(clEnv); 2561 2562 image_view=AcquireVirtualCacheView(image,exception); 2563 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 2564 if (inputPixels == (const void *) NULL) 2565 { 2566 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 2567 goto cleanup; 2568 } 2569 2570 /* Create and initialize OpenCL buffers. */ 2571 2572 /* If the host pointer is aligned to the size of CLPixelPacket, 2573 then use the host buffer directly from the GPU; otherwise, 2574 create a buffer on the GPU and copy the data over */ 2575 if (ALIGNED(inputPixels,CLPixelPacket)) 2576 { 2577 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 2578 } 2579 else 2580 { 2581 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 2582 } 2583 /* create a CL buffer from image pixel buffer */ 2584 length = image->columns * image->rows; 2585 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 2586 if (clStatus != CL_SUCCESS) 2587 { 2588 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 2589 goto cleanup; 2590 } 2591 2592 filteredImage = CloneImage(image,image->columns,image->rows,MagickTrue,exception); 2593 assert(filteredImage != NULL); 2594 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 2595 { 2596 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 2597 goto cleanup; 2598 } 2599 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 2600 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 2601 if (filteredPixels == (void *) NULL) 2602 { 2603 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 2604 goto cleanup; 2605 } 2606 2607 if (ALIGNED(filteredPixels,CLPixelPacket)) 2608 { 2609 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 2610 hostPtr = filteredPixels; 2611 } 2612 else 2613 { 2614 mem_flags = CL_MEM_WRITE_ONLY; 2615 hostPtr = NULL; 2616 } 2617 /* create a CL buffer from image pixel buffer */ 2618 length = image->columns * image->rows; 2619 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 2620 if (clStatus != CL_SUCCESS) 2621 { 2622 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 2623 goto cleanup; 2624 } 2625 2626 kernelSize = (unsigned int) (kernel->width * kernel->height); 2627 convolutionKernel = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, kernelSize * sizeof(float), NULL, &clStatus); 2628 if (clStatus != CL_SUCCESS) 2629 { 2630 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 2631 goto cleanup; 2632 } 2633 2634 queue = AcquireOpenCLCommandQueue(clEnv); 2635 2636 kernelBufferPtr = (float*)clEnv->library->clEnqueueMapBuffer(queue, convolutionKernel, CL_TRUE, CL_MAP_WRITE, 0, kernelSize * sizeof(float) 2637 , 0, NULL, NULL, &clStatus); 2638 if (clStatus != CL_SUCCESS) 2639 { 2640 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueMapBuffer failed.","."); 2641 goto cleanup; 2642 } 2643 for (i = 0; i < kernelSize; i++) 2644 { 2645 kernelBufferPtr[i] = (float) kernel->values[i]; 2646 } 2647 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, convolutionKernel, kernelBufferPtr, 0, NULL, NULL); 2648 if (clStatus != CL_SUCCESS) 2649 { 2650 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 2651 goto cleanup; 2652 } 2653 clEnv->library->clFlush(queue); 2654 2655 deviceLocalMemorySize = GetOpenCLDeviceLocalMemorySize(clEnv); 2656 2657 /* Compute the local memory requirement for a 16x16 workgroup. 2658 If it's larger than 16k, reduce the workgroup size to 8x8 */ 2659 localGroupSize[0] = 16; 2660 localGroupSize[1] = 16; 2661 localMemoryRequirement = (localGroupSize[0]+kernel->width-1) * (localGroupSize[1]+kernel->height-1) * sizeof(CLPixelPacket) 2662 + kernel->width*kernel->height*sizeof(float); 2663 2664 if (localMemoryRequirement > deviceLocalMemorySize) 2665 { 2666 localGroupSize[0] = 8; 2667 localGroupSize[1] = 8; 2668 localMemoryRequirement = (localGroupSize[0]+kernel->width-1) * (localGroupSize[1]+kernel->height-1) * sizeof(CLPixelPacket) 2669 + kernel->width*kernel->height*sizeof(float); 2670 } 2671 if (localMemoryRequirement <= deviceLocalMemorySize) 2672 { 2673 /* get the OpenCL kernel */ 2674 clkernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "ConvolveOptimized"); 2675 if (clkernel == NULL) 2676 { 2677 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 2678 goto cleanup; 2679 } 2680 2681 /* set the kernel arguments */ 2682 i = 0; 2683 clStatus =clEnv->library->clSetKernelArg(clkernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 2684 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(cl_mem),(void *)&filteredImageBuffer); 2685 imageWidth = (unsigned int) image->columns; 2686 imageHeight = (unsigned int) image->rows; 2687 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&imageWidth); 2688 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&imageHeight); 2689 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(cl_mem),(void *)&convolutionKernel); 2690 filterWidth = (unsigned int) kernel->width; 2691 filterHeight = (unsigned int) kernel->height; 2692 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&filterWidth); 2693 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&filterHeight); 2694 matte = (image->alpha_trait > CopyPixelTrait)?1:0; 2695 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&matte); 2696 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(ChannelType),(void *)&image->channel_mask); 2697 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++, (localGroupSize[0] + kernel->width-1)*(localGroupSize[1] + kernel->height-1)*sizeof(CLPixelPacket),NULL); 2698 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++, kernel->width*kernel->height*sizeof(float),NULL); 2699 if (clStatus != CL_SUCCESS) 2700 { 2701 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 2702 goto cleanup; 2703 } 2704 2705 /* pad the global size to a multiple of the local work size dimension */ 2706 global_work_size[0] = ((image->columns + localGroupSize[0] - 1)/localGroupSize[0] ) * localGroupSize[0] ; 2707 global_work_size[1] = ((image->rows + localGroupSize[1] - 1)/localGroupSize[1]) * localGroupSize[1]; 2708 2709 /* launch the kernel */ 2710 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, clkernel, 2, NULL, global_work_size, localGroupSize, 0, NULL, &event); 2711 if (clStatus != CL_SUCCESS) 2712 { 2713 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 2714 goto cleanup; 2715 } 2716 RecordProfileData(clEnv,ConvolveKernel,event); 2717 clEnv->library->clReleaseEvent(event); 2718 } 2719 else 2720 { 2721 /* get the OpenCL kernel */ 2722 clkernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "Convolve"); 2723 if (clkernel == NULL) 2724 { 2725 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 2726 goto cleanup; 2727 } 2728 2729 /* set the kernel arguments */ 2730 i = 0; 2731 clStatus =clEnv->library->clSetKernelArg(clkernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 2732 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(cl_mem),(void *)&filteredImageBuffer); 2733 imageWidth = (unsigned int) image->columns; 2734 imageHeight = (unsigned int) image->rows; 2735 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&imageWidth); 2736 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&imageHeight); 2737 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(cl_mem),(void *)&convolutionKernel); 2738 filterWidth = (unsigned int) kernel->width; 2739 filterHeight = (unsigned int) kernel->height; 2740 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&filterWidth); 2741 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&filterHeight); 2742 matte = (image->alpha_trait > CopyPixelTrait)?1:0; 2743 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&matte); 2744 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(ChannelType),(void *)&image->channel_mask); 2745 if (clStatus != CL_SUCCESS) 2746 { 2747 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 2748 goto cleanup; 2749 } 2750 2751 localGroupSize[0] = 8; 2752 localGroupSize[1] = 8; 2753 global_work_size[0] = (image->columns + (localGroupSize[0]-1))/localGroupSize[0] * localGroupSize[0]; 2754 global_work_size[1] = (image->rows + (localGroupSize[1]-1))/localGroupSize[1] * localGroupSize[1]; 2755 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, clkernel, 2, NULL, global_work_size, localGroupSize, 0, NULL, &event); 2756 2757 if (clStatus != CL_SUCCESS) 2758 { 2759 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 2760 goto cleanup; 2761 } 2762 } 2763 clEnv->library->clFlush(queue); 2764 RecordProfileData(clEnv,ConvolveKernel,event); 2765 clEnv->library->clReleaseEvent(event); 2766 2767 if (ALIGNED(filteredPixels,CLPixelPacket)) 2768 { 2769 length = image->columns * image->rows; 2770 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 2771 } 2772 else 2773 { 2774 length = image->columns * image->rows; 2775 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 2776 } 2777 if (clStatus != CL_SUCCESS) 2778 { 2779 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 2780 goto cleanup; 2781 } 2782 2783 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 2784 2785cleanup: 2786 OpenCLLogException(__FUNCTION__,__LINE__,exception); 2787 2788 image_view=DestroyCacheView(image_view); 2789 if (filteredImage_view != NULL) 2790 filteredImage_view=DestroyCacheView(filteredImage_view); 2791 2792 if (imageBuffer != NULL) 2793 clEnv->library->clReleaseMemObject(imageBuffer); 2794 2795 if (filteredImageBuffer != NULL) 2796 clEnv->library->clReleaseMemObject(filteredImageBuffer); 2797 2798 if (convolutionKernel != NULL) 2799 clEnv->library->clReleaseMemObject(convolutionKernel); 2800 2801 if (clkernel != NULL) 2802 RelinquishOpenCLKernel(clEnv, clkernel); 2803 2804 if (queue != NULL) 2805 RelinquishOpenCLCommandQueue(clEnv, queue); 2806 2807 if (outputReady == MagickFalse) 2808 { 2809 if (filteredImage != NULL) 2810 { 2811 DestroyImage(filteredImage); 2812 filteredImage = NULL; 2813 } 2814 } 2815 2816 return(filteredImage); 2817} 2818 2819MagickExport Image *AccelerateConvolveImage(const Image *image, 2820 const KernelInfo *kernel,ExceptionInfo *exception) 2821{ 2822 /* Temporary disabled due to access violation 2823 2824 Image 2825 *filteredImage; 2826 2827 assert(image != NULL); 2828 assert(kernel != (KernelInfo *) NULL); 2829 assert(exception != (ExceptionInfo *) NULL); 2830 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 2831 (checkOpenCLEnvironment(exception) == MagickFalse)) 2832 return((Image *) NULL); 2833 2834 filteredImage=ComputeConvolveImage(image,kernel,exception); 2835 return(filteredImage); 2836 */ 2837 magick_unreferenced(image); 2838 magick_unreferenced(kernel); 2839 magick_unreferenced(exception); 2840 return((Image *)NULL); 2841} 2842 2843/* 2844%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2845% % 2846% % 2847% % 2848% A c c e l e r a t e D e s p e c k l e I m a g e % 2849% % 2850% % 2851% % 2852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2853*/ 2854 2855static Image *ComputeDespeckleImage(const Image *image, 2856 ExceptionInfo*exception) 2857{ 2858 static const int 2859 X[4] = {0, 1, 1,-1}, 2860 Y[4] = {1, 0, 1, 1}; 2861 2862 CacheView 2863 *filteredImage_view, 2864 *image_view; 2865 2866 cl_command_queue 2867 queue; 2868 2869 cl_context 2870 context; 2871 2872 cl_int 2873 clStatus; 2874 2875 cl_kernel 2876 hullPass1, 2877 hullPass2; 2878 2879 cl_event 2880 event; 2881 2882 cl_mem_flags 2883 mem_flags; 2884 2885 cl_mem 2886 filteredImageBuffer, 2887 imageBuffer, 2888 tempImageBuffer[2]; 2889 2890 const void 2891 *inputPixels; 2892 2893 Image 2894 *filteredImage; 2895 2896 int 2897 k, 2898 matte; 2899 2900 MagickBooleanType 2901 outputReady; 2902 2903 MagickCLEnv 2904 clEnv; 2905 2906 MagickSizeType 2907 length; 2908 2909 size_t 2910 global_work_size[2]; 2911 2912 unsigned int 2913 imageHeight, 2914 imageWidth; 2915 2916 void 2917 *filteredPixels, 2918 *hostPtr; 2919 2920 outputReady = MagickFalse; 2921 clEnv = NULL; 2922 inputPixels = NULL; 2923 filteredImage = NULL; 2924 filteredImage_view = NULL; 2925 filteredPixels = NULL; 2926 context = NULL; 2927 imageBuffer = NULL; 2928 filteredImageBuffer = NULL; 2929 hullPass1 = NULL; 2930 hullPass2 = NULL; 2931 queue = NULL; 2932 tempImageBuffer[0] = tempImageBuffer[1] = NULL; 2933 clEnv = GetDefaultOpenCLEnv(); 2934 context = GetOpenCLContext(clEnv); 2935 queue = AcquireOpenCLCommandQueue(clEnv); 2936 2937 image_view=AcquireVirtualCacheView(image,exception); 2938 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 2939 if (inputPixels == (void *) NULL) 2940 { 2941 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 2942 goto cleanup; 2943 } 2944 2945 if (ALIGNED(inputPixels,CLPixelPacket)) 2946 { 2947 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 2948 } 2949 else 2950 { 2951 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 2952 } 2953 /* create a CL buffer from image pixel buffer */ 2954 length = image->columns * image->rows; 2955 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 2956 if (clStatus != CL_SUCCESS) 2957 { 2958 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 2959 goto cleanup; 2960 } 2961 2962 mem_flags = CL_MEM_READ_WRITE; 2963 length = image->columns * image->rows; 2964 for (k = 0; k < 2; k++) 2965 { 2966 tempImageBuffer[k] = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), NULL, &clStatus); 2967 if (clStatus != CL_SUCCESS) 2968 { 2969 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 2970 goto cleanup; 2971 } 2972 } 2973 2974 filteredImage = CloneImage(image,image->columns,image->rows,MagickTrue,exception); 2975 assert(filteredImage != NULL); 2976 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 2977 { 2978 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 2979 goto cleanup; 2980 } 2981 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 2982 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 2983 if (filteredPixels == (void *) NULL) 2984 { 2985 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 2986 goto cleanup; 2987 } 2988 2989 if (ALIGNED(filteredPixels,CLPixelPacket)) 2990 { 2991 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 2992 hostPtr = filteredPixels; 2993 } 2994 else 2995 { 2996 mem_flags = CL_MEM_WRITE_ONLY; 2997 hostPtr = NULL; 2998 } 2999 /* create a CL buffer from image pixel buffer */ 3000 length = image->columns * image->rows; 3001 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 3002 if (clStatus != CL_SUCCESS) 3003 { 3004 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 3005 goto cleanup; 3006 } 3007 3008 hullPass1 = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "HullPass1"); 3009 hullPass2 = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "HullPass2"); 3010 3011 clStatus =clEnv->library->clSetKernelArg(hullPass1,0,sizeof(cl_mem),(void *)&imageBuffer); 3012 clStatus |=clEnv->library->clSetKernelArg(hullPass1,1,sizeof(cl_mem),(void *)(tempImageBuffer+1)); 3013 imageWidth = (unsigned int) image->columns; 3014 clStatus |=clEnv->library->clSetKernelArg(hullPass1,2,sizeof(unsigned int),(void *)&imageWidth); 3015 imageHeight = (unsigned int) image->rows; 3016 clStatus |=clEnv->library->clSetKernelArg(hullPass1,3,sizeof(unsigned int),(void *)&imageHeight); 3017 matte = (image->alpha_trait > CopyPixelTrait)?1:0; 3018 clStatus |=clEnv->library->clSetKernelArg(hullPass1,6,sizeof(int),(void *)&matte); 3019 if (clStatus != CL_SUCCESS) 3020 { 3021 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 3022 goto cleanup; 3023 } 3024 3025 clStatus = clEnv->library->clSetKernelArg(hullPass2,0,sizeof(cl_mem),(void *)(tempImageBuffer+1)); 3026 clStatus |=clEnv->library->clSetKernelArg(hullPass2,1,sizeof(cl_mem),(void *)tempImageBuffer); 3027 imageWidth = (unsigned int) image->columns; 3028 clStatus |=clEnv->library->clSetKernelArg(hullPass2,2,sizeof(unsigned int),(void *)&imageWidth); 3029 imageHeight = (unsigned int) image->rows; 3030 clStatus |=clEnv->library->clSetKernelArg(hullPass2,3,sizeof(unsigned int),(void *)&imageHeight); 3031 matte = (image->alpha_trait > CopyPixelTrait)?1:0; 3032 clStatus |=clEnv->library->clSetKernelArg(hullPass2,6,sizeof(int),(void *)&matte); 3033 if (clStatus != CL_SUCCESS) 3034 { 3035 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 3036 goto cleanup; 3037 } 3038 3039 3040 global_work_size[0] = image->columns; 3041 global_work_size[1] = image->rows; 3042 3043 3044 for (k = 0; k < 4; k++) 3045 { 3046 cl_int2 offset; 3047 int polarity; 3048 3049 3050 offset.s[0] = X[k]; 3051 offset.s[1] = Y[k]; 3052 polarity = 1; 3053 clStatus = clEnv->library->clSetKernelArg(hullPass1,4,sizeof(cl_int2),(void *)&offset); 3054 clStatus|= clEnv->library->clSetKernelArg(hullPass1,5,sizeof(int),(void *)&polarity); 3055 clStatus|=clEnv->library->clSetKernelArg(hullPass2,4,sizeof(cl_int2),(void *)&offset); 3056 clStatus|=clEnv->library->clSetKernelArg(hullPass2,5,sizeof(int),(void *)&polarity); 3057 if (clStatus != CL_SUCCESS) 3058 { 3059 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 3060 goto cleanup; 3061 } 3062 /* launch the kernel */ 3063 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass1, 2, NULL, global_work_size, NULL, 0, NULL, &event); 3064 if (clStatus != CL_SUCCESS) 3065 { 3066 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 3067 goto cleanup; 3068 } 3069 RecordProfileData(clEnv,HullPass1Kernel,event); 3070 clEnv->library->clReleaseEvent(event); 3071 3072 /* launch the kernel */ 3073 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass2, 2, NULL, global_work_size, NULL, 0, NULL, &event); 3074 if (clStatus != CL_SUCCESS) 3075 { 3076 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 3077 goto cleanup; 3078 } 3079 RecordProfileData(clEnv,HullPass2Kernel,event); 3080 clEnv->library->clReleaseEvent(event); 3081 3082 if (k == 0) 3083 clStatus =clEnv->library->clSetKernelArg(hullPass1,0,sizeof(cl_mem),(void *)(tempImageBuffer)); 3084 offset.s[0] = -X[k]; 3085 offset.s[1] = -Y[k]; 3086 polarity = 1; 3087 clStatus = clEnv->library->clSetKernelArg(hullPass1,4,sizeof(cl_int2),(void *)&offset); 3088 clStatus|= clEnv->library->clSetKernelArg(hullPass1,5,sizeof(int),(void *)&polarity); 3089 clStatus|=clEnv->library->clSetKernelArg(hullPass2,4,sizeof(cl_int2),(void *)&offset); 3090 clStatus|=clEnv->library->clSetKernelArg(hullPass2,5,sizeof(int),(void *)&polarity); 3091 if (clStatus != CL_SUCCESS) 3092 { 3093 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 3094 goto cleanup; 3095 } 3096 /* launch the kernel */ 3097 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass1, 2, NULL, global_work_size, NULL, 0, NULL, &event); 3098 if (clStatus != CL_SUCCESS) 3099 { 3100 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 3101 goto cleanup; 3102 } 3103 RecordProfileData(clEnv,HullPass1Kernel,event); 3104 clEnv->library->clReleaseEvent(event); 3105 3106 /* launch the kernel */ 3107 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass2, 2, NULL, global_work_size, NULL, 0, NULL, &event); 3108 if (clStatus != CL_SUCCESS) 3109 { 3110 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 3111 goto cleanup; 3112 } 3113 RecordProfileData(clEnv,HullPass2Kernel,event); 3114 clEnv->library->clReleaseEvent(event); 3115 3116 offset.s[0] = -X[k]; 3117 offset.s[1] = -Y[k]; 3118 polarity = -1; 3119 clStatus = clEnv->library->clSetKernelArg(hullPass1,4,sizeof(cl_int2),(void *)&offset); 3120 clStatus|= clEnv->library->clSetKernelArg(hullPass1,5,sizeof(int),(void *)&polarity); 3121 clStatus|=clEnv->library->clSetKernelArg(hullPass2,4,sizeof(cl_int2),(void *)&offset); 3122 clStatus|=clEnv->library->clSetKernelArg(hullPass2,5,sizeof(int),(void *)&polarity); 3123 if (clStatus != CL_SUCCESS) 3124 { 3125 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 3126 goto cleanup; 3127 } 3128 /* launch the kernel */ 3129 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass1, 2, NULL, global_work_size, NULL, 0, NULL, &event); 3130 if (clStatus != CL_SUCCESS) 3131 { 3132 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 3133 goto cleanup; 3134 } 3135 RecordProfileData(clEnv,HullPass1Kernel,event); 3136 clEnv->library->clReleaseEvent(event); 3137 3138 /* launch the kernel */ 3139 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass2, 2, NULL, global_work_size, NULL, 0, NULL, &event); 3140 if (clStatus != CL_SUCCESS) 3141 { 3142 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 3143 goto cleanup; 3144 } 3145 RecordProfileData(clEnv,HullPass2Kernel,event); 3146 clEnv->library->clReleaseEvent(event); 3147 3148 offset.s[0] = X[k]; 3149 offset.s[1] = Y[k]; 3150 polarity = -1; 3151 clStatus = clEnv->library->clSetKernelArg(hullPass1,4,sizeof(cl_int2),(void *)&offset); 3152 clStatus|= clEnv->library->clSetKernelArg(hullPass1,5,sizeof(int),(void *)&polarity); 3153 clStatus|=clEnv->library->clSetKernelArg(hullPass2,4,sizeof(cl_int2),(void *)&offset); 3154 clStatus|=clEnv->library->clSetKernelArg(hullPass2,5,sizeof(int),(void *)&polarity); 3155 3156 if (k == 3) 3157 clStatus |=clEnv->library->clSetKernelArg(hullPass2,1,sizeof(cl_mem),(void *)&filteredImageBuffer); 3158 3159 if (clStatus != CL_SUCCESS) 3160 { 3161 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 3162 goto cleanup; 3163 } 3164 /* launch the kernel */ 3165 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass1, 2, NULL, global_work_size, NULL, 0, NULL, &event); 3166 if (clStatus != CL_SUCCESS) 3167 { 3168 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 3169 goto cleanup; 3170 } 3171 RecordProfileData(clEnv,HullPass1Kernel,event); 3172 clEnv->library->clReleaseEvent(event); 3173 3174 /* launch the kernel */ 3175 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, hullPass2, 2, NULL, global_work_size, NULL, 0, NULL, &event); 3176 if (clStatus != CL_SUCCESS) 3177 { 3178 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 3179 goto cleanup; 3180 } 3181 RecordProfileData(clEnv,HullPass2Kernel,event); 3182 clEnv->library->clReleaseEvent(event); 3183 } 3184 3185 if (ALIGNED(filteredPixels,CLPixelPacket)) 3186 { 3187 length = image->columns * image->rows; 3188 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 3189 } 3190 else 3191 { 3192 length = image->columns * image->rows; 3193 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 3194 } 3195 if (clStatus != CL_SUCCESS) 3196 { 3197 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 3198 goto cleanup; 3199 } 3200 3201 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 3202 3203cleanup: 3204 OpenCLLogException(__FUNCTION__,__LINE__,exception); 3205 3206 image_view=DestroyCacheView(image_view); 3207 if (filteredImage_view != NULL) 3208 filteredImage_view=DestroyCacheView(filteredImage_view); 3209 3210 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 3211 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 3212 for (k = 0; k < 2; k++) 3213 { 3214 if (tempImageBuffer[k]!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer[k]); 3215 } 3216 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 3217 if (hullPass1!=NULL) RelinquishOpenCLKernel(clEnv, hullPass1); 3218 if (hullPass2!=NULL) RelinquishOpenCLKernel(clEnv, hullPass2); 3219 if (outputReady == MagickFalse && filteredImage != NULL) 3220 filteredImage=DestroyImage(filteredImage); 3221 return(filteredImage); 3222} 3223 3224MagickExport Image *AccelerateDespeckleImage(const Image* image, 3225 ExceptionInfo* exception) 3226{ 3227 Image 3228 *filteredImage; 3229 3230 assert(image != NULL); 3231 assert(exception != (ExceptionInfo *) NULL); 3232 3233 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 3234 (checkOpenCLEnvironment(exception) == MagickFalse)) 3235 return NULL; 3236 3237 filteredImage=ComputeDespeckleImage(image,exception); 3238 return(filteredImage); 3239} 3240 3241/* 3242%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3243% % 3244% % 3245% % 3246% A c c e l e r a t e E q u a l i z e I m a g e % 3247% % 3248% % 3249% % 3250%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3251*/ 3252 3253static MagickBooleanType ComputeEqualizeImage(Image *image, 3254 ExceptionInfo *exception) 3255{ 3256#define EqualizeImageTag "Equalize/Image" 3257 3258 CacheView 3259 *image_view; 3260 3261 cl_command_queue 3262 queue; 3263 3264 cl_context 3265 context; 3266 3267 cl_int 3268 clStatus; 3269 3270 cl_mem_flags 3271 mem_flags; 3272 3273 cl_mem 3274 equalizeMapBuffer, 3275 histogramBuffer, 3276 imageBuffer; 3277 3278 cl_kernel 3279 equalizeKernel, 3280 histogramKernel; 3281 3282 cl_event 3283 event; 3284 3285 cl_uint4 3286 *histogram; 3287 3288 FloatPixelPacket 3289 white, 3290 black, 3291 intensity, 3292 *map; 3293 3294 MagickBooleanType 3295 outputReady, 3296 status; 3297 3298 MagickCLEnv 3299 clEnv; 3300 3301 MagickSizeType 3302 length; 3303 3304 PixelPacket 3305 *equalize_map; 3306 3307 register ssize_t 3308 i; 3309 3310 size_t 3311 global_work_size[2]; 3312 3313 void 3314 *hostPtr, 3315 *inputPixels; 3316 3317 map=NULL; 3318 histogram=NULL; 3319 equalize_map=NULL; 3320 inputPixels = NULL; 3321 imageBuffer = NULL; 3322 histogramBuffer = NULL; 3323 equalizeMapBuffer = NULL; 3324 histogramKernel = NULL; 3325 equalizeKernel = NULL; 3326 context = NULL; 3327 queue = NULL; 3328 outputReady = MagickFalse; 3329 3330 assert(image != (Image *) NULL); 3331 assert(image->signature == MagickCoreSignature); 3332 if (image->debug != MagickFalse) 3333 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 3334 3335 /* 3336 * initialize opencl env 3337 */ 3338 clEnv = GetDefaultOpenCLEnv(); 3339 context = GetOpenCLContext(clEnv); 3340 queue = AcquireOpenCLCommandQueue(clEnv); 3341 3342 /* 3343 Allocate and initialize histogram arrays. 3344 */ 3345 histogram=(cl_uint4 *) AcquireQuantumMemory(MaxMap+1UL, sizeof(*histogram)); 3346 if (histogram == (cl_uint4 *) NULL) 3347 ThrowBinaryException(ResourceLimitWarning,"MemoryAllocationFailed", image->filename); 3348 3349 /* reset histogram */ 3350 (void) ResetMagickMemory(histogram,0,(MaxMap+1)*sizeof(*histogram)); 3351 3352 /* Create and initialize OpenCL buffers. */ 3353 /* inputPixels = AcquirePixelCachePixels(image, &length, exception); */ 3354 /* assume this will get a writable image */ 3355 image_view=AcquireAuthenticCacheView(image,exception); 3356 inputPixels=GetCacheViewAuthenticPixels(image_view,0,0,image->columns,image->rows,exception); 3357 3358 if (inputPixels == (void *) NULL) 3359 { 3360 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 3361 goto cleanup; 3362 } 3363 /* If the host pointer is aligned to the size of CLPixelPacket, 3364 then use the host buffer directly from the GPU; otherwise, 3365 create a buffer on the GPU and copy the data over */ 3366 if (ALIGNED(inputPixels,CLPixelPacket)) 3367 { 3368 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 3369 } 3370 else 3371 { 3372 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 3373 } 3374 /* create a CL buffer from image pixel buffer */ 3375 length = image->columns * image->rows; 3376 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 3377 if (clStatus != CL_SUCCESS) 3378 { 3379 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 3380 goto cleanup; 3381 } 3382 3383 /* If the host pointer is aligned to the size of cl_uint, 3384 then use the host buffer directly from the GPU; otherwise, 3385 create a buffer on the GPU and copy the data over */ 3386 if (ALIGNED(histogram,cl_uint4)) 3387 { 3388 mem_flags = CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR; 3389 hostPtr = histogram; 3390 } 3391 else 3392 { 3393 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 3394 hostPtr = histogram; 3395 } 3396 /* create a CL buffer for histogram */ 3397 length = (MaxMap+1); 3398 histogramBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(cl_uint4), hostPtr, &clStatus); 3399 if (clStatus != CL_SUCCESS) 3400 { 3401 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 3402 goto cleanup; 3403 } 3404 3405 status = LaunchHistogramKernel(clEnv, queue, imageBuffer, histogramBuffer, image, image->channel_mask, exception); 3406 if (status == MagickFalse) 3407 goto cleanup; 3408 3409 /* read from the kenel output */ 3410 if (ALIGNED(histogram,cl_uint4)) 3411 { 3412 length = (MaxMap+1); 3413 clEnv->library->clEnqueueMapBuffer(queue, histogramBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(cl_uint4), 0, NULL, NULL, &clStatus); 3414 } 3415 else 3416 { 3417 length = (MaxMap+1); 3418 clStatus = clEnv->library->clEnqueueReadBuffer(queue, histogramBuffer, CL_TRUE, 0, length * sizeof(cl_uint4), histogram, 0, NULL, NULL); 3419 } 3420 if (clStatus != CL_SUCCESS) 3421 { 3422 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 3423 goto cleanup; 3424 } 3425 3426 /* unmap, don't block gpu to use this buffer again. */ 3427 if (ALIGNED(histogram,cl_uint4)) 3428 { 3429 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, histogramBuffer, histogram, 0, NULL, NULL); 3430 if (clStatus != CL_SUCCESS) 3431 { 3432 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 3433 goto cleanup; 3434 } 3435 } 3436 3437 /* recreate input buffer later, in case image updated */ 3438#ifdef RECREATEBUFFER 3439 if (imageBuffer!=NULL) 3440 clEnv->library->clReleaseMemObject(imageBuffer); 3441#endif 3442 3443 /* CPU stuff */ 3444 equalize_map=(PixelPacket *) AcquireQuantumMemory(MaxMap+1UL, sizeof(*equalize_map)); 3445 if (equalize_map == (PixelPacket *) NULL) 3446 ThrowBinaryException(ResourceLimitWarning,"MemoryAllocationFailed", image->filename); 3447 3448 map=(FloatPixelPacket *) AcquireQuantumMemory(MaxMap+1UL,sizeof(*map)); 3449 if (map == (FloatPixelPacket *) NULL) 3450 ThrowBinaryException(ResourceLimitWarning,"MemoryAllocationFailed", image->filename); 3451 3452 /* 3453 Integrate the histogram to get the equalization map. 3454 */ 3455 (void) ResetMagickMemory(&intensity,0,sizeof(intensity)); 3456 for (i=0; i <= (ssize_t) MaxMap; i++) 3457 { 3458 if ((image->channel_mask & SyncChannels) != 0) 3459 { 3460 intensity.red+=histogram[i].s[2]; 3461 map[i]=intensity; 3462 continue; 3463 } 3464 if ((image->channel_mask & RedChannel) != 0) 3465 intensity.red+=histogram[i].s[2]; 3466 if ((image->channel_mask & GreenChannel) != 0) 3467 intensity.green+=histogram[i].s[1]; 3468 if ((image->channel_mask & BlueChannel) != 0) 3469 intensity.blue+=histogram[i].s[0]; 3470 if ((image->channel_mask & AlphaChannel) != 0) 3471 intensity.alpha+=histogram[i].s[3]; 3472 /* 3473 if (((channel & IndexChannel) != 0) && 3474 (image->colorspace == CMYKColorspace)) 3475 { 3476 intensity.index+=histogram[i].index; 3477 } 3478 */ 3479 map[i]=intensity; 3480 } 3481 black=map[0]; 3482 white=map[(int) MaxMap]; 3483 (void) ResetMagickMemory(equalize_map,0,(MaxMap+1)*sizeof(*equalize_map)); 3484 for (i=0; i <= (ssize_t) MaxMap; i++) 3485 { 3486 if ((image->channel_mask & SyncChannels) != 0) 3487 { 3488 if (white.red != black.red) 3489 equalize_map[i].red=ScaleMapToQuantum((MagickRealType) ((MaxMap* 3490 (map[i].red-black.red))/(white.red-black.red))); 3491 continue; 3492 } 3493 if (((image->channel_mask & RedChannel) != 0) && (white.red != black.red)) 3494 equalize_map[i].red=ScaleMapToQuantum((MagickRealType) ((MaxMap* 3495 (map[i].red-black.red))/(white.red-black.red))); 3496 if (((image->channel_mask & GreenChannel) != 0) && (white.green != black.green)) 3497 equalize_map[i].green=ScaleMapToQuantum((MagickRealType) ((MaxMap* 3498 (map[i].green-black.green))/(white.green-black.green))); 3499 if (((image->channel_mask & BlueChannel) != 0) && (white.blue != black.blue)) 3500 equalize_map[i].blue=ScaleMapToQuantum((MagickRealType) ((MaxMap* 3501 (map[i].blue-black.blue))/(white.blue-black.blue))); 3502 if (((image->channel_mask & AlphaChannel) != 0) && (white.alpha != black.alpha)) 3503 equalize_map[i].alpha=ScaleMapToQuantum((MagickRealType) ((MaxMap* 3504 (map[i].alpha-black.alpha))/(white.alpha-black.alpha))); 3505 /* 3506 if ((((channel & IndexChannel) != 0) && 3507 (image->colorspace == CMYKColorspace)) && 3508 (white.index != black.index)) 3509 equalize_map[i].index=ScaleMapToQuantum((MagickRealType) ((MaxMap* 3510 (map[i].index-black.index))/(white.index-black.index))); 3511 */ 3512 } 3513 3514 if (image->storage_class == PseudoClass) 3515 { 3516 /* 3517 Equalize colormap. 3518 */ 3519 for (i=0; i < (ssize_t) image->colors; i++) 3520 { 3521 if ((image->channel_mask & SyncChannels) != 0) 3522 { 3523 if (white.red != black.red) 3524 { 3525 image->colormap[i].red=equalize_map[ 3526 ScaleQuantumToMap(image->colormap[i].red)].red; 3527 image->colormap[i].green=equalize_map[ 3528 ScaleQuantumToMap(image->colormap[i].green)].red; 3529 image->colormap[i].blue=equalize_map[ 3530 ScaleQuantumToMap(image->colormap[i].blue)].red; 3531 image->colormap[i].alpha=equalize_map[ 3532 ScaleQuantumToMap(image->colormap[i].alpha)].red; 3533 } 3534 continue; 3535 } 3536 if (((image->channel_mask & RedChannel) != 0) && (white.red != black.red)) 3537 image->colormap[i].red=equalize_map[ 3538 ScaleQuantumToMap(image->colormap[i].red)].red; 3539 if (((image->channel_mask & GreenChannel) != 0) && (white.green != black.green)) 3540 image->colormap[i].green=equalize_map[ 3541 ScaleQuantumToMap(image->colormap[i].green)].green; 3542 if (((image->channel_mask & BlueChannel) != 0) && (white.blue != black.blue)) 3543 image->colormap[i].blue=equalize_map[ 3544 ScaleQuantumToMap(image->colormap[i].blue)].blue; 3545 if (((image->channel_mask & AlphaChannel) != 0) && 3546 (white.alpha != black.alpha)) 3547 image->colormap[i].alpha=equalize_map[ 3548 ScaleQuantumToMap(image->colormap[i].alpha)].alpha; 3549 } 3550 } 3551 3552 /* 3553 Equalize image. 3554 */ 3555 3556 /* GPU can work on this again, image and equalize map as input 3557 image: uchar4 (CLPixelPacket) 3558 equalize_map: uchar4 (PixelPacket) 3559 black, white: float4 (FloatPixelPacket) */ 3560 3561#ifdef RECREATEBUFFER 3562 /* If the host pointer is aligned to the size of CLPixelPacket, 3563 then use the host buffer directly from the GPU; otherwise, 3564 create a buffer on the GPU and copy the data over */ 3565 if (ALIGNED(inputPixels,CLPixelPacket)) 3566 { 3567 mem_flags = CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR; 3568 } 3569 else 3570 { 3571 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 3572 } 3573 /* create a CL buffer from image pixel buffer */ 3574 length = image->columns * image->rows; 3575 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 3576 if (clStatus != CL_SUCCESS) 3577 { 3578 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 3579 goto cleanup; 3580 } 3581#endif 3582 3583 /* Create and initialize OpenCL buffers. */ 3584 if (ALIGNED(equalize_map, PixelPacket)) 3585 { 3586 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 3587 hostPtr = equalize_map; 3588 } 3589 else 3590 { 3591 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 3592 hostPtr = equalize_map; 3593 } 3594 /* create a CL buffer for eqaulize_map */ 3595 length = (MaxMap+1); 3596 equalizeMapBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(PixelPacket), hostPtr, &clStatus); 3597 if (clStatus != CL_SUCCESS) 3598 { 3599 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 3600 goto cleanup; 3601 } 3602 3603 /* get the OpenCL kernel */ 3604 equalizeKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "Equalize"); 3605 if (equalizeKernel == NULL) 3606 { 3607 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 3608 goto cleanup; 3609 } 3610 3611 /* set the kernel arguments */ 3612 i = 0; 3613 clStatus=clEnv->library->clSetKernelArg(equalizeKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 3614 clStatus|=clEnv->library->clSetKernelArg(equalizeKernel,i++,sizeof(ChannelType),&image->channel_mask); 3615 clStatus|=clEnv->library->clSetKernelArg(equalizeKernel,i++,sizeof(cl_mem),(void *)&equalizeMapBuffer); 3616 clStatus|=clEnv->library->clSetKernelArg(equalizeKernel,i++,sizeof(FloatPixelPacket),&white); 3617 clStatus|=clEnv->library->clSetKernelArg(equalizeKernel,i++,sizeof(FloatPixelPacket),&black); 3618 if (clStatus != CL_SUCCESS) 3619 { 3620 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 3621 goto cleanup; 3622 } 3623 3624 /* launch the kernel */ 3625 global_work_size[0] = image->columns; 3626 global_work_size[1] = image->rows; 3627 3628 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, equalizeKernel, 2, NULL, global_work_size, NULL, 0, NULL, &event); 3629 3630 if (clStatus != CL_SUCCESS) 3631 { 3632 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 3633 goto cleanup; 3634 } 3635 clEnv->library->clFlush(queue); 3636 RecordProfileData(clEnv,EqualizeKernel,event); 3637 clEnv->library->clReleaseEvent(event); 3638 3639 /* read the data back */ 3640 if (ALIGNED(inputPixels,CLPixelPacket)) 3641 { 3642 length = image->columns * image->rows; 3643 clEnv->library->clEnqueueMapBuffer(queue, imageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 3644 } 3645 else 3646 { 3647 length = image->columns * image->rows; 3648 clStatus = clEnv->library->clEnqueueReadBuffer(queue, imageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), inputPixels, 0, NULL, NULL); 3649 } 3650 if (clStatus != CL_SUCCESS) 3651 { 3652 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 3653 goto cleanup; 3654 } 3655 3656 outputReady=SyncCacheViewAuthenticPixels(image_view,exception); 3657 3658cleanup: 3659 OpenCLLogException(__FUNCTION__,__LINE__,exception); 3660 3661 image_view=DestroyCacheView(image_view); 3662 3663 if (imageBuffer!=NULL) 3664 clEnv->library->clReleaseMemObject(imageBuffer); 3665 3666 if (map!=NULL) 3667 map=(FloatPixelPacket *) RelinquishMagickMemory(map); 3668 3669 if (equalizeMapBuffer!=NULL) 3670 clEnv->library->clReleaseMemObject(equalizeMapBuffer); 3671 if (equalize_map!=NULL) 3672 equalize_map=(PixelPacket *) RelinquishMagickMemory(equalize_map); 3673 3674 if (histogramBuffer!=NULL) 3675 clEnv->library->clReleaseMemObject(histogramBuffer); 3676 if (histogram!=NULL) 3677 histogram=(cl_uint4 *) RelinquishMagickMemory(histogram); 3678 3679 if (histogramKernel!=NULL) 3680 RelinquishOpenCLKernel(clEnv, histogramKernel); 3681 if (equalizeKernel!=NULL) 3682 RelinquishOpenCLKernel(clEnv, equalizeKernel); 3683 3684 if (queue != NULL) 3685 RelinquishOpenCLCommandQueue(clEnv, queue); 3686 3687 return(outputReady); 3688} 3689 3690MagickExport MagickBooleanType AccelerateEqualizeImage(Image *image, 3691 ExceptionInfo *exception) 3692{ 3693 MagickBooleanType 3694 status; 3695 3696 assert(image != NULL); 3697 assert(exception != (ExceptionInfo *) NULL); 3698 3699 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 3700 (checkHistogramCondition(image) == MagickFalse) || 3701 (checkOpenCLEnvironment(exception) == MagickFalse)) 3702 return(MagickFalse); 3703 3704 status=ComputeEqualizeImage(image,exception); 3705 return(status); 3706} 3707 3708/* 3709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3710% % 3711% % 3712% % 3713% A c c e l e r a t e F u n c t i o n I m a g e % 3714% % 3715% % 3716% % 3717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3718*/ 3719 3720static MagickBooleanType ComputeFunctionImage(Image *image, 3721 const MagickFunction function,const size_t number_parameters, 3722 const double *parameters,ExceptionInfo *exception) 3723{ 3724 CacheView 3725 *image_view; 3726 3727 cl_command_queue 3728 queue; 3729 3730 cl_context 3731 context; 3732 3733 cl_int 3734 clStatus; 3735 3736 cl_kernel 3737 clkernel; 3738 3739 cl_event 3740 event; 3741 3742 cl_mem 3743 imageBuffer, 3744 parametersBuffer; 3745 3746 cl_mem_flags 3747 mem_flags; 3748 3749 float 3750 *parametersBufferPtr; 3751 3752 MagickBooleanType 3753 status; 3754 3755 MagickCLEnv 3756 clEnv; 3757 3758 MagickSizeType 3759 length; 3760 3761 size_t 3762 globalWorkSize[2]; 3763 3764 unsigned int 3765 i; 3766 3767 void 3768 *pixels; 3769 3770 status = MagickFalse; 3771 3772 context = NULL; 3773 clkernel = NULL; 3774 queue = NULL; 3775 imageBuffer = NULL; 3776 parametersBuffer = NULL; 3777 3778 clEnv = GetDefaultOpenCLEnv(); 3779 context = GetOpenCLContext(clEnv); 3780 3781 image_view=AcquireAuthenticCacheView(image,exception); 3782 pixels=GetCacheViewAuthenticPixels(image_view,0,0,image->columns,image->rows,exception); 3783 if (pixels == (void *) NULL) 3784 { 3785 (void) OpenCLThrowMagickException(exception, GetMagickModule(), CacheWarning, 3786 "GetPixelCachePixels failed.", 3787 "'%s'", image->filename); 3788 goto cleanup; 3789 } 3790 3791 3792 if (ALIGNED(pixels,CLPixelPacket)) 3793 { 3794 mem_flags = CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR; 3795 } 3796 else 3797 { 3798 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 3799 } 3800 /* create a CL buffer from image pixel buffer */ 3801 length = image->columns * image->rows; 3802 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)pixels, &clStatus); 3803 if (clStatus != CL_SUCCESS) 3804 { 3805 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 3806 goto cleanup; 3807 } 3808 3809 parametersBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, number_parameters * sizeof(float), NULL, &clStatus); 3810 if (clStatus != CL_SUCCESS) 3811 { 3812 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 3813 goto cleanup; 3814 } 3815 3816 queue = AcquireOpenCLCommandQueue(clEnv); 3817 3818 parametersBufferPtr = (float*)clEnv->library->clEnqueueMapBuffer(queue, parametersBuffer, CL_TRUE, CL_MAP_WRITE, 0, number_parameters * sizeof(float) 3819 , 0, NULL, NULL, &clStatus); 3820 if (clStatus != CL_SUCCESS) 3821 { 3822 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueMapBuffer failed.","."); 3823 goto cleanup; 3824 } 3825 for (i = 0; i < number_parameters; i++) 3826 { 3827 parametersBufferPtr[i] = (float)parameters[i]; 3828 } 3829 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, parametersBuffer, parametersBufferPtr, 0, NULL, NULL); 3830 if (clStatus != CL_SUCCESS) 3831 { 3832 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 3833 goto cleanup; 3834 } 3835 clEnv->library->clFlush(queue); 3836 3837 clkernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "ComputeFunction"); 3838 if (clkernel == NULL) 3839 { 3840 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 3841 goto cleanup; 3842 } 3843 3844 /* set the kernel arguments */ 3845 i = 0; 3846 clStatus =clEnv->library->clSetKernelArg(clkernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 3847 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(ChannelType),(void *)&image->channel_mask); 3848 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(MagickFunction),(void *)&function); 3849 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(unsigned int),(void *)&number_parameters); 3850 clStatus|=clEnv->library->clSetKernelArg(clkernel,i++,sizeof(cl_mem),(void *)¶metersBuffer); 3851 if (clStatus != CL_SUCCESS) 3852 { 3853 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 3854 goto cleanup; 3855 } 3856 3857 globalWorkSize[0] = image->columns; 3858 globalWorkSize[1] = image->rows; 3859 /* launch the kernel */ 3860 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, clkernel, 2, NULL, globalWorkSize, NULL, 0, NULL, &event); 3861 if (clStatus != CL_SUCCESS) 3862 { 3863 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 3864 goto cleanup; 3865 } 3866 clEnv->library->clFlush(queue); 3867 RecordProfileData(clEnv,ComputeFunctionKernel,event); 3868 clEnv->library->clReleaseEvent(event); 3869 3870 if (ALIGNED(pixels,CLPixelPacket)) 3871 { 3872 length = image->columns * image->rows; 3873 clEnv->library->clEnqueueMapBuffer(queue, imageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 3874 } 3875 else 3876 { 3877 length = image->columns * image->rows; 3878 clStatus = clEnv->library->clEnqueueReadBuffer(queue, imageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), pixels, 0, NULL, NULL); 3879 } 3880 if (clStatus != CL_SUCCESS) 3881 { 3882 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 3883 goto cleanup; 3884 } 3885 status=SyncCacheViewAuthenticPixels(image_view,exception); 3886 3887cleanup: 3888 OpenCLLogException(__FUNCTION__,__LINE__,exception); 3889 3890 image_view=DestroyCacheView(image_view); 3891 3892 if (clkernel != NULL) RelinquishOpenCLKernel(clEnv, clkernel); 3893 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 3894 if (imageBuffer != NULL) clEnv->library->clReleaseMemObject(imageBuffer); 3895 if (parametersBuffer != NULL) clEnv->library->clReleaseMemObject(parametersBuffer); 3896 3897 return(status); 3898} 3899 3900MagickExport MagickBooleanType AccelerateFunctionImage(Image *image, 3901 const MagickFunction function,const size_t number_parameters, 3902 const double *parameters,ExceptionInfo *exception) 3903{ 3904 MagickBooleanType 3905 status; 3906 3907 assert(image != NULL); 3908 assert(exception != (ExceptionInfo *) NULL); 3909 3910 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 3911 (checkOpenCLEnvironment(exception) == MagickFalse)) 3912 return(MagickFalse); 3913 3914 status=ComputeFunctionImage(image,function,number_parameters,parameters, 3915 exception); 3916 return(status); 3917} 3918 3919/* 3920%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3921% % 3922% % 3923% % 3924% A c c e l e r a t e G r a y s c a l e I m a g e % 3925% % 3926% % 3927% % 3928%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3929*/ 3930 3931static MagickBooleanType ComputeGrayscaleImage(Image *image, 3932 const PixelIntensityMethod method,ExceptionInfo *exception) 3933{ 3934 CacheView 3935 *image_view; 3936 3937 cl_command_queue 3938 queue; 3939 3940 cl_context 3941 context; 3942 3943 cl_int 3944 clStatus, 3945 number_channels, 3946 colorspace, 3947 intensityMethod; 3948 3949 cl_kernel 3950 grayscaleKernel; 3951 3952 cl_event 3953 event; 3954 3955 cl_mem 3956 imageBuffer; 3957 3958 cl_mem_flags 3959 mem_flags; 3960 3961 MagickBooleanType 3962 outputReady; 3963 3964 MagickCLEnv 3965 clEnv; 3966 3967 MagickSizeType 3968 length; 3969 3970 register ssize_t 3971 i; 3972 3973 void 3974 *inputPixels; 3975 3976 inputPixels = NULL; 3977 imageBuffer = NULL; 3978 grayscaleKernel = NULL; 3979 3980 assert(image != (Image *) NULL); 3981 assert(image->signature == MagickCoreSignature); 3982 if (image->debug != MagickFalse) 3983 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 3984 3985 /* 3986 * initialize opencl env 3987 */ 3988 clEnv = GetDefaultOpenCLEnv(); 3989 context = GetOpenCLContext(clEnv); 3990 queue = AcquireOpenCLCommandQueue(clEnv); 3991 3992 outputReady = MagickFalse; 3993 3994 /* Create and initialize OpenCL buffers. 3995 inputPixels = AcquirePixelCachePixels(image, &length, exception); 3996 assume this will get a writable image 3997 */ 3998 image_view=AcquireAuthenticCacheView(image,exception); 3999 inputPixels=GetCacheViewAuthenticPixels(image_view,0,0,image->columns,image->rows,exception); 4000 if (inputPixels == (void *) NULL) 4001 { 4002 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 4003 goto cleanup; 4004 } 4005 4006 /* If the host pointer is aligned to the size of CLPixelPacket, 4007 then use the host buffer directly from the GPU; otherwise, 4008 create a buffer on the GPU and copy the data over 4009 */ 4010 if (ALIGNED(inputPixels,CLQuantum)) 4011 { 4012 mem_flags = CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR; 4013 } 4014 else 4015 { 4016 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 4017 } 4018 /* create a CL buffer from image pixel buffer */ 4019 length = image->columns * image->rows * image->number_channels; 4020 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLQuantum), (void*)inputPixels, &clStatus); 4021 if (clStatus != CL_SUCCESS) 4022 { 4023 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 4024 goto cleanup; 4025 } 4026 4027 grayscaleKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "Grayscale"); 4028 if (grayscaleKernel == NULL) 4029 { 4030 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 4031 goto cleanup; 4032 } 4033 4034 number_channels = (cl_int) image->number_channels; 4035 intensityMethod = (cl_int) method; 4036 colorspace = (cl_int) image->colorspace; 4037 4038 i = 0; 4039 clStatus=clEnv->library->clSetKernelArg(grayscaleKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 4040 clStatus|=clEnv->library->clSetKernelArg(grayscaleKernel,i++,sizeof(cl_int),&number_channels); 4041 clStatus|=clEnv->library->clSetKernelArg(grayscaleKernel,i++,sizeof(cl_int),&intensityMethod); 4042 clStatus|=clEnv->library->clSetKernelArg(grayscaleKernel,i++,sizeof(cl_int),&colorspace); 4043 if (clStatus != CL_SUCCESS) 4044 { 4045 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 4046 printf("no kernel\n"); 4047 goto cleanup; 4048 } 4049 4050 { 4051 size_t global_work_size[2]; 4052 global_work_size[0] = image->columns; 4053 global_work_size[1] = image->rows; 4054 /* launch the kernel */ 4055 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, grayscaleKernel, 2, NULL, global_work_size, NULL, 0, NULL, &event); 4056 if (clStatus != CL_SUCCESS) 4057 { 4058 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 4059 goto cleanup; 4060 } 4061 clEnv->library->clFlush(queue); 4062 RecordProfileData(clEnv,GrayScaleKernel,event); 4063 clEnv->library->clReleaseEvent(event); 4064 } 4065 4066 if (ALIGNED(inputPixels,CLQuantum)) 4067 { 4068 clEnv->library->clEnqueueMapBuffer(queue, imageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLQuantum), 0, NULL, NULL, &clStatus); 4069 } 4070 else 4071 { 4072 clStatus = clEnv->library->clEnqueueReadBuffer(queue, imageBuffer, CL_TRUE, 0, length * sizeof(CLQuantum), inputPixels, 0, NULL, NULL); 4073 } 4074 if (clStatus != CL_SUCCESS) 4075 { 4076 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 4077 goto cleanup; 4078 } 4079 4080 outputReady=SyncCacheViewAuthenticPixels(image_view,exception); 4081 4082cleanup: 4083 OpenCLLogException(__FUNCTION__,__LINE__,exception); 4084 4085 image_view=DestroyCacheView(image_view); 4086 4087 if (imageBuffer!=NULL) 4088 clEnv->library->clReleaseMemObject(imageBuffer); 4089 if (grayscaleKernel!=NULL) 4090 RelinquishOpenCLKernel(clEnv, grayscaleKernel); 4091 if (queue != NULL) 4092 RelinquishOpenCLCommandQueue(clEnv, queue); 4093 4094 return( outputReady); 4095} 4096 4097MagickExport MagickBooleanType AccelerateGrayscaleImage(Image* image, 4098 const PixelIntensityMethod method,ExceptionInfo *exception) 4099{ 4100 MagickBooleanType 4101 status; 4102 4103 assert(image != NULL); 4104 assert(exception != (ExceptionInfo *) NULL); 4105 4106 if ((checkAccelerateCondition(image) == MagickFalse) || 4107 (checkOpenCLEnvironment(exception) == MagickFalse)) 4108 return(MagickFalse); 4109 4110 if ((method == Rec601LuminancePixelIntensityMethod) || 4111 (method == Rec709LuminancePixelIntensityMethod)) 4112 return(MagickFalse); 4113 4114 if (image->colorspace != sRGBColorspace) 4115 return(MagickFalse); 4116 4117 if (image->number_channels < 3) 4118 return(MagickFalse); 4119 4120 status=ComputeGrayscaleImage(image,method,exception); 4121 return(status); 4122} 4123 4124/* 4125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4126% % 4127% % 4128% % 4129% A c c e l e r a t e L o c a l C o n t r a s t I m a g e % 4130% % 4131% % 4132% % 4133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4134*/ 4135 4136static Image *ComputeLocalContrastImage(const Image *image, 4137 const double radius,const double strength,ExceptionInfo *exception) 4138{ 4139 CacheView 4140 *filteredImage_view, 4141 *image_view; 4142 4143 cl_command_queue 4144 queue; 4145 4146 cl_context 4147 context; 4148 4149 cl_int 4150 clStatus, 4151 iRadius; 4152 4153 cl_kernel 4154 blurRowKernel, 4155 blurColumnKernel; 4156 4157 cl_event 4158 event; 4159 4160 cl_mem 4161 filteredImageBuffer, 4162 imageBuffer, 4163 imageKernelBuffer, 4164 tempImageBuffer; 4165 4166 cl_mem_flags 4167 mem_flags; 4168 4169 const void 4170 *inputPixels; 4171 4172 Image 4173 *filteredImage; 4174 4175 MagickBooleanType 4176 outputReady; 4177 4178 MagickCLEnv 4179 clEnv; 4180 4181 MagickSizeType 4182 length; 4183 4184 void 4185 *filteredPixels, 4186 *hostPtr; 4187 4188 unsigned int 4189 i, 4190 imageColumns, 4191 imageRows, 4192 passes; 4193 4194 clEnv = NULL; 4195 filteredImage = NULL; 4196 filteredImage_view = NULL; 4197 context = NULL; 4198 imageBuffer = NULL; 4199 filteredImageBuffer = NULL; 4200 tempImageBuffer = NULL; 4201 imageKernelBuffer = NULL; 4202 blurRowKernel = NULL; 4203 blurColumnKernel = NULL; 4204 queue = NULL; 4205 outputReady = MagickFalse; 4206 4207 clEnv = GetDefaultOpenCLEnv(); 4208 context = GetOpenCLContext(clEnv); 4209 queue = AcquireOpenCLCommandQueue(clEnv); 4210 4211 /* Create and initialize OpenCL buffers. */ 4212 { 4213 image_view=AcquireVirtualCacheView(image,exception); 4214 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 4215 if (inputPixels == (const void *) NULL) 4216 { 4217 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 4218 goto cleanup; 4219 } 4220 4221 /* If the host pointer is aligned to the size of CLPixelPacket, 4222 then use the host buffer directly from the GPU; otherwise, 4223 create a buffer on the GPU and copy the data over */ 4224 if (ALIGNED(inputPixels,CLPixelPacket)) 4225 { 4226 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 4227 } 4228 else 4229 { 4230 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 4231 } 4232 /* create a CL buffer from image pixel buffer */ 4233 length = image->columns * image->rows; 4234 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 4235 if (clStatus != CL_SUCCESS) 4236 { 4237 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 4238 goto cleanup; 4239 } 4240 } 4241 4242 /* create output */ 4243 { 4244 filteredImage = CloneImage(image,image->columns,image->rows,MagickTrue,exception); 4245 assert(filteredImage != NULL); 4246 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 4247 { 4248 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 4249 goto cleanup; 4250 } 4251 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 4252 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 4253 if (filteredPixels == (void *) NULL) 4254 { 4255 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 4256 goto cleanup; 4257 } 4258 4259 if (ALIGNED(filteredPixels,CLPixelPacket)) 4260 { 4261 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 4262 hostPtr = filteredPixels; 4263 } 4264 else 4265 { 4266 mem_flags = CL_MEM_WRITE_ONLY; 4267 hostPtr = NULL; 4268 } 4269 4270 /* create a CL buffer from image pixel buffer */ 4271 length = image->columns * image->rows; 4272 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 4273 if (clStatus != CL_SUCCESS) 4274 { 4275 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 4276 goto cleanup; 4277 } 4278 } 4279 4280 { 4281 /* create temp buffer */ 4282 { 4283 length = image->columns * image->rows; 4284 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length * sizeof(float), NULL, &clStatus); 4285 if (clStatus != CL_SUCCESS) 4286 { 4287 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 4288 goto cleanup; 4289 } 4290 } 4291 4292 /* get the opencl kernel */ 4293 { 4294 blurRowKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "LocalContrastBlurRow"); 4295 if (blurRowKernel == NULL) 4296 { 4297 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 4298 goto cleanup; 4299 }; 4300 4301 blurColumnKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "LocalContrastBlurApplyColumn"); 4302 if (blurColumnKernel == NULL) 4303 { 4304 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 4305 goto cleanup; 4306 }; 4307 } 4308 4309 { 4310 imageColumns = (unsigned int) image->columns; 4311 imageRows = (unsigned int) image->rows; 4312 iRadius = (cl_int) (image->rows > image->columns ? image->rows : image->columns) * 0.002f * fabs(radius); // Normalized radius, 100% gives blur radius of 20% of the largest dimension 4313 4314 passes = ((1.0f * imageColumns) * imageColumns * iRadius) / 4000000000.0f; 4315 passes = (passes < 1) ? 1: passes; 4316 4317 /* set the kernel arguments */ 4318 i = 0; 4319 clStatus=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 4320 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&filteredImageBuffer); 4321 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&tempImageBuffer); 4322 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_int),(void *)&iRadius); 4323 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 4324 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&imageRows); 4325 4326 if (clStatus != CL_SUCCESS) 4327 { 4328 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 4329 goto cleanup; 4330 } 4331 } 4332 4333 /* launch the kernel */ 4334 { 4335 int x; 4336 for (x = 0; x < passes; ++x) { 4337 size_t gsize[2]; 4338 size_t wsize[2]; 4339 size_t goffset[2]; 4340 4341 gsize[0] = 256; 4342 gsize[1] = image->rows / passes; 4343 wsize[0] = 256; 4344 wsize[1] = 1; 4345 goffset[0] = 0; 4346 goffset[1] = x * gsize[1]; 4347 4348 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurRowKernel, 2, goffset, gsize, wsize, 0, NULL, &event); 4349 if (clStatus != CL_SUCCESS) 4350 { 4351 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 4352 goto cleanup; 4353 } 4354 RecordProfileData(clEnv,LocalContrastBlurRowKernel,event); 4355 clEnv->library->clReleaseEvent(event); 4356 } 4357 } 4358 4359 { 4360 cl_float FStrength = strength; 4361 i = 0; 4362 clStatus=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 4363 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_mem),(void *)&filteredImageBuffer); 4364 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_mem),(void *)&tempImageBuffer); 4365 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&iRadius); 4366 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(cl_float),(void *)&FStrength); 4367 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 4368 clStatus|=clEnv->library->clSetKernelArg(blurColumnKernel,i++,sizeof(unsigned int),(void *)&imageRows); 4369 4370 if (clStatus != CL_SUCCESS) 4371 { 4372 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 4373 goto cleanup; 4374 } 4375 } 4376 4377 /* launch the kernel */ 4378 { 4379 int x; 4380 for (x = 0; x < passes; ++x) { 4381 size_t gsize[2]; 4382 size_t wsize[2]; 4383 size_t goffset[2]; 4384 4385 gsize[0] = ((image->columns + 3) / 4) * 4; 4386 gsize[1] = ((((image->rows + 63) / 64) + (passes + 1)) / passes) * 64; 4387 wsize[0] = 4; 4388 wsize[1] = 64; 4389 goffset[0] = 0; 4390 goffset[1] = x * gsize[1]; 4391 4392 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurColumnKernel, 2, goffset, gsize, wsize, 0, NULL, &event); 4393 if (clStatus != CL_SUCCESS) 4394 { 4395 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 4396 goto cleanup; 4397 } 4398 RecordProfileData(clEnv,LocalContrastBlurApplyColumnKernel,event); 4399 clEnv->library->clReleaseEvent(event); 4400 } 4401 } 4402 } 4403 4404 /* get result */ 4405 if (ALIGNED(filteredPixels,CLPixelPacket)) 4406 { 4407 length = image->columns * image->rows; 4408 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 4409 } 4410 else 4411 { 4412 length = image->columns * image->rows; 4413 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 4414 } 4415 if (clStatus != CL_SUCCESS) 4416 { 4417 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 4418 goto cleanup; 4419 } 4420 4421 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 4422 4423cleanup: 4424 OpenCLLogException(__FUNCTION__,__LINE__,exception); 4425 4426 image_view=DestroyCacheView(image_view); 4427 if (filteredImage_view != NULL) 4428 filteredImage_view=DestroyCacheView(filteredImage_view); 4429 4430 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 4431 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 4432 if (tempImageBuffer!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer); 4433 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer); 4434 if (blurRowKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurRowKernel); 4435 if (blurColumnKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurColumnKernel); 4436 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 4437 if (outputReady == MagickFalse) 4438 { 4439 if (filteredImage != NULL) 4440 { 4441 DestroyImage(filteredImage); 4442 filteredImage = NULL; 4443 } 4444 } 4445 return(filteredImage); 4446} 4447 4448MagickExport Image *AccelerateLocalContrastImage(const Image *image, 4449 const double radius,const double strength,ExceptionInfo *exception) 4450{ 4451 Image 4452 *filteredImage; 4453 4454 assert(image != NULL); 4455 assert(exception != (ExceptionInfo *) NULL); 4456 4457 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 4458 (checkOpenCLEnvironment(exception) == MagickFalse)) 4459 return NULL; 4460 4461 filteredImage=ComputeLocalContrastImage(image,radius,strength,exception); 4462 return(filteredImage); 4463} 4464 4465/* 4466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4467% % 4468% % 4469% % 4470% A c c e l e r a t e M o d u l a t e I m a g e % 4471% % 4472% % 4473% % 4474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4475*/ 4476 4477static MagickBooleanType ComputeModulateImage(Image *image, 4478 const double percent_brightness,const double percent_hue, 4479 const double percent_saturation,const ColorspaceType colorspace, 4480 ExceptionInfo *exception) 4481{ 4482 CacheView 4483 *image_view; 4484 4485 cl_float 4486 bright, 4487 hue, 4488 saturation; 4489 4490 cl_context 4491 context; 4492 4493 cl_command_queue 4494 queue; 4495 4496 cl_int 4497 color, 4498 clStatus; 4499 4500 cl_kernel 4501 modulateKernel; 4502 4503 cl_event 4504 event; 4505 4506 cl_mem 4507 imageBuffer; 4508 4509 cl_mem_flags 4510 mem_flags; 4511 4512 MagickBooleanType 4513 outputReady; 4514 4515 MagickCLEnv 4516 clEnv; 4517 4518 MagickSizeType 4519 length; 4520 4521 register ssize_t 4522 i; 4523 4524 void 4525 *inputPixels; 4526 4527 inputPixels = NULL; 4528 imageBuffer = NULL; 4529 modulateKernel = NULL; 4530 4531 assert(image != (Image *) NULL); 4532 assert(image->signature == MagickCoreSignature); 4533 if (image->debug != MagickFalse) 4534 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 4535 4536 /* 4537 * initialize opencl env 4538 */ 4539 clEnv = GetDefaultOpenCLEnv(); 4540 context = GetOpenCLContext(clEnv); 4541 queue = AcquireOpenCLCommandQueue(clEnv); 4542 4543 outputReady = MagickFalse; 4544 4545 /* Create and initialize OpenCL buffers. 4546 inputPixels = AcquirePixelCachePixels(image, &length, exception); 4547 assume this will get a writable image 4548 */ 4549 image_view=AcquireAuthenticCacheView(image,exception); 4550 inputPixels=GetCacheViewAuthenticPixels(image_view,0,0,image->columns,image->rows,exception); 4551 if (inputPixels == (void *) NULL) 4552 { 4553 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 4554 goto cleanup; 4555 } 4556 4557 /* If the host pointer is aligned to the size of CLPixelPacket, 4558 then use the host buffer directly from the GPU; otherwise, 4559 create a buffer on the GPU and copy the data over 4560 */ 4561 if (ALIGNED(inputPixels,CLPixelPacket)) 4562 { 4563 mem_flags = CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR; 4564 } 4565 else 4566 { 4567 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 4568 } 4569 /* create a CL buffer from image pixel buffer */ 4570 length = image->columns * image->rows; 4571 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 4572 if (clStatus != CL_SUCCESS) 4573 { 4574 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 4575 goto cleanup; 4576 } 4577 4578 modulateKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "Modulate"); 4579 if (modulateKernel == NULL) 4580 { 4581 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 4582 goto cleanup; 4583 } 4584 4585 bright=percent_brightness; 4586 hue=percent_hue; 4587 saturation=percent_saturation; 4588 color=colorspace; 4589 4590 i = 0; 4591 clStatus=clEnv->library->clSetKernelArg(modulateKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 4592 clStatus|=clEnv->library->clSetKernelArg(modulateKernel,i++,sizeof(cl_float),&bright); 4593 clStatus|=clEnv->library->clSetKernelArg(modulateKernel,i++,sizeof(cl_float),&hue); 4594 clStatus|=clEnv->library->clSetKernelArg(modulateKernel,i++,sizeof(cl_float),&saturation); 4595 clStatus|=clEnv->library->clSetKernelArg(modulateKernel,i++,sizeof(cl_float),&color); 4596 if (clStatus != CL_SUCCESS) 4597 { 4598 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 4599 printf("no kernel\n"); 4600 goto cleanup; 4601 } 4602 4603 { 4604 size_t global_work_size[2]; 4605 global_work_size[0] = image->columns; 4606 global_work_size[1] = image->rows; 4607 /* launch the kernel */ 4608 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, modulateKernel, 2, NULL, global_work_size, NULL, 0, NULL, &event); 4609 if (clStatus != CL_SUCCESS) 4610 { 4611 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 4612 goto cleanup; 4613 } 4614 clEnv->library->clFlush(queue); 4615 RecordProfileData(clEnv,ModulateKernel,event); 4616 clEnv->library->clReleaseEvent(event); 4617 } 4618 4619 if (ALIGNED(inputPixels,CLPixelPacket)) 4620 { 4621 length = image->columns * image->rows; 4622 clEnv->library->clEnqueueMapBuffer(queue, imageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 4623 } 4624 else 4625 { 4626 length = image->columns * image->rows; 4627 clStatus = clEnv->library->clEnqueueReadBuffer(queue, imageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), inputPixels, 0, NULL, NULL); 4628 } 4629 if (clStatus != CL_SUCCESS) 4630 { 4631 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 4632 goto cleanup; 4633 } 4634 4635 outputReady=SyncCacheViewAuthenticPixels(image_view,exception); 4636 4637cleanup: 4638 OpenCLLogException(__FUNCTION__,__LINE__,exception); 4639 4640 image_view=DestroyCacheView(image_view); 4641 4642 if (imageBuffer!=NULL) 4643 clEnv->library->clReleaseMemObject(imageBuffer); 4644 if (modulateKernel!=NULL) 4645 RelinquishOpenCLKernel(clEnv, modulateKernel); 4646 if (queue != NULL) 4647 RelinquishOpenCLCommandQueue(clEnv, queue); 4648 4649 return outputReady; 4650 4651} 4652 4653MagickExport MagickBooleanType AccelerateModulateImage(Image *image, 4654 const double percent_brightness,const double percent_hue, 4655 const double percent_saturation,const ColorspaceType colorspace, 4656 ExceptionInfo *exception) 4657{ 4658 MagickBooleanType 4659 status; 4660 4661 assert(image != NULL); 4662 assert(exception != (ExceptionInfo *) NULL); 4663 4664 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 4665 (checkOpenCLEnvironment(exception) == MagickFalse)) 4666 return(MagickFalse); 4667 4668 if ((colorspace != HSLColorspace) && (colorspace != UndefinedColorspace)) 4669 return(MagickFalse); 4670 4671 status=ComputeModulateImage(image,percent_brightness,percent_hue, 4672 percent_saturation,colorspace,exception); 4673 return(status); 4674} 4675 4676/* 4677%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4678% % 4679% % 4680% % 4681% A c c e l e r a t e M o t i o n B l u r I m a g e % 4682% % 4683% % 4684% % 4685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4686*/ 4687 4688static Image* ComputeMotionBlurImage(const Image *image,const double *kernel, 4689 const size_t width,const OffsetInfo *offset,ExceptionInfo *exception) 4690{ 4691 CacheView 4692 *filteredImage_view, 4693 *image_view; 4694 4695 cl_command_queue 4696 queue; 4697 4698 cl_context 4699 context; 4700 4701 cl_float4 4702 biasPixel; 4703 4704 cl_int 4705 clStatus; 4706 4707 cl_kernel 4708 motionBlurKernel; 4709 4710 cl_event 4711 event; 4712 4713 cl_mem 4714 filteredImageBuffer, 4715 imageBuffer, 4716 imageKernelBuffer, 4717 offsetBuffer; 4718 4719 cl_mem_flags 4720 mem_flags; 4721 4722 const void 4723 *inputPixels; 4724 4725 float 4726 *kernelBufferPtr; 4727 4728 Image 4729 *filteredImage; 4730 4731 int 4732 *offsetBufferPtr; 4733 4734 MagickBooleanType 4735 outputReady; 4736 4737 MagickCLEnv 4738 clEnv; 4739 4740 PixelInfo 4741 bias; 4742 4743 MagickSizeType 4744 length; 4745 4746 size_t 4747 global_work_size[2], 4748 local_work_size[2]; 4749 4750 unsigned int 4751 i, 4752 imageHeight, 4753 imageWidth, 4754 matte; 4755 4756 void 4757 *filteredPixels, 4758 *hostPtr; 4759 4760 outputReady = MagickFalse; 4761 context = NULL; 4762 filteredImage = NULL; 4763 filteredImage_view = NULL; 4764 imageBuffer = NULL; 4765 filteredImageBuffer = NULL; 4766 imageKernelBuffer = NULL; 4767 motionBlurKernel = NULL; 4768 queue = NULL; 4769 4770 clEnv = GetDefaultOpenCLEnv(); 4771 context = GetOpenCLContext(clEnv); 4772 4773 /* Create and initialize OpenCL buffers. */ 4774 4775 image_view=AcquireVirtualCacheView(image,exception); 4776 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 4777 if (inputPixels == (const void *) NULL) 4778 { 4779 (void) ThrowMagickException(exception,GetMagickModule(),CacheError, 4780 "UnableToReadPixelCache.","`%s'",image->filename); 4781 goto cleanup; 4782 } 4783 4784 // If the host pointer is aligned to the size of CLPixelPacket, 4785 // then use the host buffer directly from the GPU; otherwise, 4786 // create a buffer on the GPU and copy the data over 4787 if (ALIGNED(inputPixels,CLPixelPacket)) 4788 { 4789 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 4790 } 4791 else 4792 { 4793 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 4794 } 4795 // create a CL buffer from image pixel buffer 4796 length = image->columns * image->rows; 4797 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, 4798 length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 4799 if (clStatus != CL_SUCCESS) 4800 { 4801 (void) ThrowMagickException(exception, GetMagickModule(), 4802 ResourceLimitError, "clEnv->library->clCreateBuffer failed.","."); 4803 goto cleanup; 4804 } 4805 4806 4807 filteredImage = CloneImage(image,image->columns,image->rows, 4808 MagickTrue,exception); 4809 assert(filteredImage != NULL); 4810 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 4811 { 4812 (void) ThrowMagickException(exception, GetMagickModule(), 4813 ResourceLimitError, "CloneImage failed.", "'%s'", "."); 4814 goto cleanup; 4815 } 4816 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 4817 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 4818 if (filteredPixels == (void *) NULL) 4819 { 4820 (void) ThrowMagickException(exception,GetMagickModule(),CacheError, 4821 "UnableToReadPixelCache.","`%s'",filteredImage->filename); 4822 goto cleanup; 4823 } 4824 4825 if (ALIGNED(filteredPixels,CLPixelPacket)) 4826 { 4827 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 4828 hostPtr = filteredPixels; 4829 } 4830 else 4831 { 4832 mem_flags = CL_MEM_WRITE_ONLY; 4833 hostPtr = NULL; 4834 } 4835 // create a CL buffer from image pixel buffer 4836 length = image->columns * image->rows; 4837 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, 4838 length * sizeof(CLPixelPacket), hostPtr, &clStatus); 4839 if (clStatus != CL_SUCCESS) 4840 { 4841 (void) ThrowMagickException(exception, GetMagickModule(), 4842 ResourceLimitError, "clEnv->library->clCreateBuffer failed.","."); 4843 goto cleanup; 4844 } 4845 4846 4847 imageKernelBuffer = clEnv->library->clCreateBuffer(context, 4848 CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, width * sizeof(float), NULL, 4849 &clStatus); 4850 if (clStatus != CL_SUCCESS) 4851 { 4852 (void) ThrowMagickException(exception, GetMagickModule(), 4853 ResourceLimitError, "clEnv->library->clCreateBuffer failed.","."); 4854 goto cleanup; 4855 } 4856 4857 queue = AcquireOpenCLCommandQueue(clEnv); 4858 kernelBufferPtr = (float*)clEnv->library->clEnqueueMapBuffer(queue, imageKernelBuffer, 4859 CL_TRUE, CL_MAP_WRITE, 0, width * sizeof(float), 0, NULL, NULL, &clStatus); 4860 if (clStatus != CL_SUCCESS) 4861 { 4862 (void) ThrowMagickException(exception, GetMagickModule(), 4863 ResourceLimitError, "clEnv->library->clEnqueueMapBuffer failed.","."); 4864 goto cleanup; 4865 } 4866 for (i = 0; i < width; i++) 4867 { 4868 kernelBufferPtr[i] = (float) kernel[i]; 4869 } 4870 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, imageKernelBuffer, kernelBufferPtr, 4871 0, NULL, NULL); 4872 if (clStatus != CL_SUCCESS) 4873 { 4874 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError, 4875 "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 4876 goto cleanup; 4877 } 4878 4879 offsetBuffer = clEnv->library->clCreateBuffer(context, 4880 CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, width * sizeof(cl_int2), NULL, 4881 &clStatus); 4882 if (clStatus != CL_SUCCESS) 4883 { 4884 (void) ThrowMagickException(exception, GetMagickModule(), 4885 ResourceLimitError, "clEnv->library->clCreateBuffer failed.","."); 4886 goto cleanup; 4887 } 4888 4889 offsetBufferPtr = (int*)clEnv->library->clEnqueueMapBuffer(queue, offsetBuffer, CL_TRUE, 4890 CL_MAP_WRITE, 0, width * sizeof(cl_int2), 0, NULL, NULL, &clStatus); 4891 if (clStatus != CL_SUCCESS) 4892 { 4893 (void) ThrowMagickException(exception, GetMagickModule(), 4894 ResourceLimitError, "clEnv->library->clEnqueueMapBuffer failed.","."); 4895 goto cleanup; 4896 } 4897 for (i = 0; i < width; i++) 4898 { 4899 offsetBufferPtr[2*i] = (int)offset[i].x; 4900 offsetBufferPtr[2*i+1] = (int)offset[i].y; 4901 } 4902 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, offsetBuffer, offsetBufferPtr, 0, 4903 NULL, NULL); 4904 if (clStatus != CL_SUCCESS) 4905 { 4906 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError, 4907 "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 4908 goto cleanup; 4909 } 4910 4911 4912 // get the OpenCL kernel 4913 motionBlurKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, 4914 "MotionBlur"); 4915 if (motionBlurKernel == NULL) 4916 { 4917 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError, 4918 "AcquireOpenCLKernel failed.", "'%s'", "."); 4919 goto cleanup; 4920 } 4921 4922 // set the kernel arguments 4923 i = 0; 4924 clStatus=clEnv->library->clSetKernelArg(motionBlurKernel,i++,sizeof(cl_mem), 4925 (void *)&imageBuffer); 4926 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,sizeof(cl_mem), 4927 (void *)&filteredImageBuffer); 4928 imageWidth = (unsigned int) image->columns; 4929 imageHeight = (unsigned int) image->rows; 4930 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,sizeof(unsigned int), 4931 &imageWidth); 4932 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,sizeof(unsigned int), 4933 &imageHeight); 4934 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,sizeof(cl_mem), 4935 (void *)&imageKernelBuffer); 4936 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,sizeof(unsigned int), 4937 &width); 4938 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,sizeof(cl_mem), 4939 (void *)&offsetBuffer); 4940 4941 GetPixelInfo(image,&bias); 4942 biasPixel.s[0] = bias.red; 4943 biasPixel.s[1] = bias.green; 4944 biasPixel.s[2] = bias.blue; 4945 biasPixel.s[3] = bias.alpha; 4946 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,sizeof(cl_float4), &biasPixel); 4947 4948 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,sizeof(ChannelType), &image->channel_mask); 4949 matte = (image->alpha_trait > CopyPixelTrait)?1:0; 4950 clStatus|=clEnv->library->clSetKernelArg(motionBlurKernel,i++,sizeof(unsigned int), &matte); 4951 if (clStatus != CL_SUCCESS) 4952 { 4953 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError, 4954 "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 4955 goto cleanup; 4956 } 4957 4958 // launch the kernel 4959 local_work_size[0] = 16; 4960 local_work_size[1] = 16; 4961 global_work_size[0] = (size_t)padGlobalWorkgroupSizeToLocalWorkgroupSize( 4962 (unsigned int) image->columns,(unsigned int) local_work_size[0]); 4963 global_work_size[1] = (size_t)padGlobalWorkgroupSizeToLocalWorkgroupSize( 4964 (unsigned int) image->rows,(unsigned int) local_work_size[1]); 4965 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, motionBlurKernel, 2, NULL, 4966 global_work_size, local_work_size, 0, NULL, &event); 4967 4968 if (clStatus != CL_SUCCESS) 4969 { 4970 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError, 4971 "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 4972 goto cleanup; 4973 } 4974 clEnv->library->clFlush(queue); 4975 RecordProfileData(clEnv,MotionBlurKernel,event); 4976 clEnv->library->clReleaseEvent(event); 4977 4978 if (ALIGNED(filteredPixels,CLPixelPacket)) 4979 { 4980 length = image->columns * image->rows; 4981 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, 4982 CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, 4983 NULL, &clStatus); 4984 } 4985 else 4986 { 4987 length = image->columns * image->rows; 4988 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, 4989 length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 4990 } 4991 if (clStatus != CL_SUCCESS) 4992 { 4993 (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError, 4994 "Reading output image from CL buffer failed.", "'%s'", "."); 4995 goto cleanup; 4996 } 4997 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 4998 4999cleanup: 5000 5001 image_view=DestroyCacheView(image_view); 5002 if (filteredImage_view != NULL) 5003 filteredImage_view=DestroyCacheView(filteredImage_view); 5004 5005 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 5006 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 5007 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer); 5008 if (motionBlurKernel!=NULL) RelinquishOpenCLKernel(clEnv, motionBlurKernel); 5009 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 5010 if (outputReady == MagickFalse && filteredImage != NULL) 5011 filteredImage=DestroyImage(filteredImage); 5012 5013 return(filteredImage); 5014} 5015 5016MagickExport Image *AccelerateMotionBlurImage(const Image *image, 5017 const double* kernel,const size_t width,const OffsetInfo *offset, 5018 ExceptionInfo *exception) 5019{ 5020 Image 5021 *filteredImage; 5022 5023 assert(image != NULL); 5024 assert(kernel != (double *) NULL); 5025 assert(offset != (OffsetInfo *) NULL); 5026 assert(exception != (ExceptionInfo *) NULL); 5027 5028 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 5029 (checkOpenCLEnvironment(exception) == MagickFalse)) 5030 return NULL; 5031 5032 filteredImage=ComputeMotionBlurImage(image,kernel,width,offset,exception); 5033 return(filteredImage); 5034} 5035 5036/* 5037%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5038% % 5039% % 5040% % 5041% A c c e l e r a t e R a n d o m I m a g e % 5042% % 5043% % 5044% % 5045%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5046*/ 5047 5048static MagickBooleanType LaunchRandomImageKernel(MagickCLEnv clEnv, 5049 cl_command_queue queue,cl_mem imageBuffer,const unsigned int imageColumns, 5050 const unsigned int imageRows,cl_mem seedBuffer, 5051 const unsigned int numGenerators,ExceptionInfo *exception) 5052{ 5053 int 5054 k; 5055 5056 cl_int 5057 clStatus; 5058 5059 cl_kernel 5060 randomImageKernel; 5061 5062 cl_event 5063 event; 5064 5065 MagickBooleanType 5066 status; 5067 5068 size_t 5069 global_work_size, 5070 local_work_size; 5071 5072 status = MagickFalse; 5073 randomImageKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "RandomNumberGenerator"); 5074 5075 k = 0; 5076 clEnv->library->clSetKernelArg(randomImageKernel,k++,sizeof(cl_mem),(void*)&imageBuffer); 5077 clEnv->library->clSetKernelArg(randomImageKernel,k++,sizeof(cl_uint),(void*)&imageColumns); 5078 clEnv->library->clSetKernelArg(randomImageKernel,k++,sizeof(cl_uint),(void*)&imageRows); 5079 clEnv->library->clSetKernelArg(randomImageKernel,k++,sizeof(cl_mem),(void*)&seedBuffer); 5080 { 5081 const float randNormNumerator = 1.0f; 5082 const unsigned int randNormDenominator = (unsigned int)(~0UL); 5083 clEnv->library->clSetKernelArg(randomImageKernel,k++, 5084 sizeof(float),(void*)&randNormNumerator); 5085 clEnv->library->clSetKernelArg(randomImageKernel,k++, 5086 sizeof(cl_uint),(void*)&randNormDenominator); 5087 } 5088 5089 5090 global_work_size = numGenerators; 5091 local_work_size = 64; 5092 5093 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue,randomImageKernel,1,NULL,&global_work_size, 5094 &local_work_size, 0, NULL, &event); 5095 5096 if (clStatus != CL_SUCCESS) 5097 { 5098 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, 5099 "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 5100 goto cleanup; 5101 } 5102 RecordProfileData(clEnv,RandomNumberGeneratorKernel,event); 5103 clEnv->library->clReleaseEvent(event); 5104 5105 status = MagickTrue; 5106 5107cleanup: 5108 if (randomImageKernel!=NULL) RelinquishOpenCLKernel(clEnv, randomImageKernel); 5109 return(status); 5110} 5111 5112static MagickBooleanType ComputeRandomImage(Image* image, 5113 ExceptionInfo* exception) 5114{ 5115 CacheView 5116 *image_view; 5117 5118 cl_command_queue 5119 queue; 5120 5121 cl_context 5122 context; 5123 5124 cl_int 5125 clStatus; 5126 5127 /* Don't release this buffer in this function !!! */ 5128 cl_mem 5129 randomNumberSeedsBuffer; 5130 5131 cl_mem_flags 5132 mem_flags; 5133 5134 cl_mem 5135 imageBuffer; 5136 5137 MagickBooleanType 5138 outputReady, 5139 status; 5140 5141 MagickCLEnv 5142 clEnv; 5143 5144 MagickSizeType 5145 length; 5146 5147 void 5148 *inputPixels; 5149 5150 status = MagickFalse; 5151 outputReady = MagickFalse; 5152 inputPixels = NULL; 5153 context = NULL; 5154 imageBuffer = NULL; 5155 queue = NULL; 5156 5157 clEnv = GetDefaultOpenCLEnv(); 5158 context = GetOpenCLContext(clEnv); 5159 5160 /* Create and initialize OpenCL buffers. */ 5161 image_view=AcquireAuthenticCacheView(image,exception); 5162 inputPixels=GetCacheViewAuthenticPixels(image_view,0,0,image->columns,image->rows,exception); 5163 if (inputPixels == (void *) NULL) 5164 { 5165 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 5166 goto cleanup; 5167 } 5168 5169 /* If the host pointer is aligned to the size of CLPixelPacket, 5170 then use the host buffer directly from the GPU; otherwise, 5171 create a buffer on the GPU and copy the data over */ 5172 if (ALIGNED(inputPixels,CLPixelPacket)) 5173 { 5174 mem_flags = CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR; 5175 } 5176 else 5177 { 5178 mem_flags = CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR; 5179 } 5180 /* create a CL buffer from image pixel buffer */ 5181 length = image->columns * image->rows; 5182 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 5183 if (clStatus != CL_SUCCESS) 5184 { 5185 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 5186 goto cleanup; 5187 } 5188 5189 queue = AcquireOpenCLCommandQueue(clEnv); 5190 5191 randomNumberSeedsBuffer = GetAndLockRandSeedBuffer(clEnv); 5192 if (randomNumberSeedsBuffer==NULL) 5193 { 5194 (void) OpenCLThrowMagickException(exception, GetMagickModule(), 5195 ResourceLimitWarning, "Failed to get GPU random number generators.", 5196 "'%s'", "."); 5197 goto cleanup; 5198 } 5199 5200 status = LaunchRandomImageKernel(clEnv,queue, 5201 imageBuffer, 5202 (unsigned int) image->columns, 5203 (unsigned int) image->rows, 5204 randomNumberSeedsBuffer, 5205 GetNumRandGenerators(clEnv), 5206 exception); 5207 if (status==MagickFalse) 5208 { 5209 goto cleanup; 5210 } 5211 5212 if (ALIGNED(inputPixels,CLPixelPacket)) 5213 { 5214 length = image->columns * image->rows; 5215 clEnv->library->clEnqueueMapBuffer(queue, imageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 5216 } 5217 else 5218 { 5219 length = image->columns * image->rows; 5220 clStatus = clEnv->library->clEnqueueReadBuffer(queue, imageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), inputPixels, 0, NULL, NULL); 5221 } 5222 if (clStatus != CL_SUCCESS) 5223 { 5224 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 5225 goto cleanup; 5226 } 5227 outputReady=SyncCacheViewAuthenticPixels(image_view,exception); 5228 5229cleanup: 5230 OpenCLLogException(__FUNCTION__,__LINE__,exception); 5231 5232 image_view=DestroyCacheView(image_view); 5233 5234 UnlockRandSeedBuffer(clEnv); 5235 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 5236 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 5237 return outputReady; 5238} 5239 5240MagickExport MagickBooleanType AccelerateRandomImage(Image *image, 5241 ExceptionInfo* exception) 5242{ 5243 MagickBooleanType 5244 status; 5245 5246 assert(image != NULL); 5247 assert(exception != (ExceptionInfo *) NULL); 5248 5249 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 5250 (checkOpenCLEnvironment(exception) == MagickFalse)) 5251 return(MagickFalse); 5252 5253 status=ComputeRandomImage(image,exception); 5254 return(status); 5255} 5256 5257/* 5258%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5259% % 5260% % 5261% % 5262% A c c e l e r a t e R e s i z e I m a g e % 5263% % 5264% % 5265% % 5266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5267*/ 5268 5269static MagickBooleanType resizeHorizontalFilter(cl_mem image, 5270 const unsigned int imageColumns,const unsigned int imageRows, 5271 const unsigned int matte,cl_mem resizedImage, 5272 const unsigned int resizedColumns,const unsigned int resizedRows, 5273 const ResizeFilter *resizeFilter,cl_mem resizeFilterCubicCoefficients, 5274 const float xFactor,MagickCLEnv clEnv,cl_command_queue queue, 5275 ExceptionInfo *exception) 5276{ 5277 cl_kernel 5278 horizontalKernel; 5279 5280 cl_event 5281 event; 5282 5283 cl_int clStatus; 5284 5285 const unsigned int 5286 workgroupSize = 256; 5287 5288 float 5289 resizeFilterScale, 5290 resizeFilterSupport, 5291 resizeFilterWindowSupport, 5292 resizeFilterBlur, 5293 scale, 5294 support; 5295 5296 int 5297 cacheRangeStart, 5298 cacheRangeEnd, 5299 numCachedPixels, 5300 resizeFilterType, 5301 resizeWindowType; 5302 5303 MagickBooleanType 5304 status = MagickFalse; 5305 5306 size_t 5307 deviceLocalMemorySize, 5308 gammaAccumulatorLocalMemorySize, 5309 global_work_size[2], 5310 imageCacheLocalMemorySize, 5311 pixelAccumulatorLocalMemorySize, 5312 local_work_size[2], 5313 totalLocalMemorySize, 5314 weightAccumulatorLocalMemorySize; 5315 5316 unsigned int 5317 chunkSize, 5318 i, 5319 pixelPerWorkgroup; 5320 5321 horizontalKernel = NULL; 5322 status = MagickFalse; 5323 5324 /* 5325 Apply filter to resize vertically from image to resize image. 5326 */ 5327 scale=MAGICK_MAX(1.0/xFactor+MagickEpsilon,1.0); 5328 support=scale*GetResizeFilterSupport(resizeFilter); 5329 if (support < 0.5) 5330 { 5331 /* 5332 Support too small even for nearest neighbour: Reduce to point 5333 sampling. 5334 */ 5335 support=(MagickRealType) 0.5; 5336 scale=1.0; 5337 } 5338 scale=PerceptibleReciprocal(scale); 5339 5340 if (resizedColumns < workgroupSize) 5341 { 5342 chunkSize = 32; 5343 pixelPerWorkgroup = 32; 5344 } 5345 else 5346 { 5347 chunkSize = workgroupSize; 5348 pixelPerWorkgroup = workgroupSize; 5349 } 5350 5351 /* get the local memory size supported by the device */ 5352 deviceLocalMemorySize = GetOpenCLDeviceLocalMemorySize(clEnv); 5353 5354DisableMSCWarning(4127) 5355 while(1) 5356RestoreMSCWarning 5357 { 5358 /* calculate the local memory size needed per workgroup */ 5359 cacheRangeStart = (int) (((0 + 0.5)/xFactor+MagickEpsilon)-support+0.5); 5360 cacheRangeEnd = (int) ((((pixelPerWorkgroup-1) + 0.5)/xFactor+MagickEpsilon)+support+0.5); 5361 numCachedPixels = cacheRangeEnd - cacheRangeStart + 1; 5362 imageCacheLocalMemorySize = numCachedPixels * sizeof(CLPixelPacket); 5363 totalLocalMemorySize = imageCacheLocalMemorySize; 5364 5365 /* local size for the pixel accumulator */ 5366 pixelAccumulatorLocalMemorySize = chunkSize * sizeof(cl_float4); 5367 totalLocalMemorySize+=pixelAccumulatorLocalMemorySize; 5368 5369 /* local memory size for the weight accumulator */ 5370 weightAccumulatorLocalMemorySize = chunkSize * sizeof(float); 5371 totalLocalMemorySize+=weightAccumulatorLocalMemorySize; 5372 5373 /* local memory size for the gamma accumulator */ 5374 if (matte == 0) 5375 gammaAccumulatorLocalMemorySize = sizeof(float); 5376 else 5377 gammaAccumulatorLocalMemorySize = chunkSize * sizeof(float); 5378 totalLocalMemorySize+=gammaAccumulatorLocalMemorySize; 5379 5380 if (totalLocalMemorySize <= deviceLocalMemorySize) 5381 break; 5382 else 5383 { 5384 pixelPerWorkgroup = pixelPerWorkgroup/2; 5385 chunkSize = chunkSize/2; 5386 if (pixelPerWorkgroup == 0 5387 || chunkSize == 0) 5388 { 5389 /* quit, fallback to CPU */ 5390 goto cleanup; 5391 } 5392 } 5393 } 5394 5395 resizeFilterType = (int)GetResizeFilterWeightingType(resizeFilter); 5396 resizeWindowType = (int)GetResizeFilterWindowWeightingType(resizeFilter); 5397 5398 horizontalKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "ResizeHorizontalFilter"); 5399 if (horizontalKernel == NULL) 5400 { 5401 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 5402 goto cleanup; 5403 } 5404 5405 i = 0; 5406 clStatus = clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(cl_mem), (void*)&image); 5407 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(unsigned int), (void*)&imageColumns); 5408 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(unsigned int), (void*)&imageRows); 5409 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(unsigned int), (void*)&matte); 5410 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(float), (void*)&xFactor); 5411 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(cl_mem), (void*)&resizedImage); 5412 5413 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(unsigned int), (void*)&resizedColumns); 5414 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(unsigned int), (void*)&resizedRows); 5415 5416 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(int), (void*)&resizeFilterType); 5417 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(int), (void*)&resizeWindowType); 5418 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(cl_mem), (void*)&resizeFilterCubicCoefficients); 5419 5420 resizeFilterScale = (float) GetResizeFilterScale(resizeFilter); 5421 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(float), (void*)&resizeFilterScale); 5422 5423 resizeFilterSupport = (float) GetResizeFilterSupport(resizeFilter); 5424 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(float), (void*)&resizeFilterSupport); 5425 5426 resizeFilterWindowSupport = (float) GetResizeFilterWindowSupport(resizeFilter); 5427 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(float), (void*)&resizeFilterWindowSupport); 5428 5429 resizeFilterBlur = (float) GetResizeFilterBlur(resizeFilter); 5430 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(float), (void*)&resizeFilterBlur); 5431 5432 5433 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, imageCacheLocalMemorySize, NULL); 5434 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(int), &numCachedPixels); 5435 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(unsigned int), &pixelPerWorkgroup); 5436 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, sizeof(unsigned int), &chunkSize); 5437 5438 5439 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, pixelAccumulatorLocalMemorySize, NULL); 5440 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, weightAccumulatorLocalMemorySize, NULL); 5441 clStatus |= clEnv->library->clSetKernelArg(horizontalKernel, i++, gammaAccumulatorLocalMemorySize, NULL); 5442 5443 if (clStatus != CL_SUCCESS) 5444 { 5445 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 5446 goto cleanup; 5447 } 5448 5449 global_work_size[0] = (resizedColumns+pixelPerWorkgroup-1)/pixelPerWorkgroup*workgroupSize; 5450 global_work_size[1] = resizedRows; 5451 5452 local_work_size[0] = workgroupSize; 5453 local_work_size[1] = 1; 5454 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, horizontalKernel, 2, NULL, global_work_size, local_work_size, 0, NULL, &event); 5455 (void) local_work_size; 5456 if (clStatus != CL_SUCCESS) 5457 { 5458 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 5459 goto cleanup; 5460 } 5461 clEnv->library->clFlush(queue); 5462 RecordProfileData(clEnv,ResizeHorizontalKernel,event); 5463 clEnv->library->clReleaseEvent(event); 5464 status = MagickTrue; 5465 5466 5467cleanup: 5468 OpenCLLogException(__FUNCTION__,__LINE__,exception); 5469 5470 if (horizontalKernel != NULL) RelinquishOpenCLKernel(clEnv, horizontalKernel); 5471 5472 return(status); 5473} 5474 5475static MagickBooleanType resizeVerticalFilter(cl_mem image, 5476 const unsigned int imageColumns,const unsigned int imageRows, 5477 const unsigned int matte,cl_mem resizedImage, 5478 const unsigned int resizedColumns,const unsigned int resizedRows, 5479 const ResizeFilter *resizeFilter,cl_mem resizeFilterCubicCoefficients, 5480 const float yFactor,MagickCLEnv clEnv,cl_command_queue queue, 5481 ExceptionInfo *exception) 5482{ 5483 cl_kernel 5484 verticalKernel; 5485 5486 cl_event 5487 event; 5488 5489 cl_int clStatus; 5490 5491 const unsigned int 5492 workgroupSize = 256; 5493 5494 float 5495 resizeFilterScale, 5496 resizeFilterSupport, 5497 resizeFilterWindowSupport, 5498 resizeFilterBlur, 5499 scale, 5500 support; 5501 5502 int 5503 cacheRangeStart, 5504 cacheRangeEnd, 5505 numCachedPixels, 5506 resizeFilterType, 5507 resizeWindowType; 5508 5509 MagickBooleanType 5510 status = MagickFalse; 5511 5512 size_t 5513 deviceLocalMemorySize, 5514 gammaAccumulatorLocalMemorySize, 5515 global_work_size[2], 5516 imageCacheLocalMemorySize, 5517 pixelAccumulatorLocalMemorySize, 5518 local_work_size[2], 5519 totalLocalMemorySize, 5520 weightAccumulatorLocalMemorySize; 5521 5522 unsigned int 5523 chunkSize, 5524 i, 5525 pixelPerWorkgroup; 5526 5527 verticalKernel = NULL; 5528 status = MagickFalse; 5529 5530 /* 5531 Apply filter to resize vertically from image to resize image. 5532 */ 5533 scale=MAGICK_MAX(1.0/yFactor+MagickEpsilon,1.0); 5534 support=scale*GetResizeFilterSupport(resizeFilter); 5535 if (support < 0.5) 5536 { 5537 /* 5538 Support too small even for nearest neighbour: Reduce to point 5539 sampling. 5540 */ 5541 support=(MagickRealType) 0.5; 5542 scale=1.0; 5543 } 5544 scale=PerceptibleReciprocal(scale); 5545 5546 if (resizedRows < workgroupSize) 5547 { 5548 chunkSize = 32; 5549 pixelPerWorkgroup = 32; 5550 } 5551 else 5552 { 5553 chunkSize = workgroupSize; 5554 pixelPerWorkgroup = workgroupSize; 5555 } 5556 5557 /* get the local memory size supported by the device */ 5558 deviceLocalMemorySize = GetOpenCLDeviceLocalMemorySize(clEnv); 5559 5560DisableMSCWarning(4127) 5561 while(1) 5562RestoreMSCWarning 5563 { 5564 /* calculate the local memory size needed per workgroup */ 5565 cacheRangeStart = (int) (((0 + 0.5)/yFactor+MagickEpsilon)-support+0.5); 5566 cacheRangeEnd = (int) ((((pixelPerWorkgroup-1) + 0.5)/yFactor+MagickEpsilon)+support+0.5); 5567 numCachedPixels = cacheRangeEnd - cacheRangeStart + 1; 5568 imageCacheLocalMemorySize = numCachedPixels * sizeof(CLPixelPacket); 5569 totalLocalMemorySize = imageCacheLocalMemorySize; 5570 5571 /* local size for the pixel accumulator */ 5572 pixelAccumulatorLocalMemorySize = chunkSize * sizeof(cl_float4); 5573 totalLocalMemorySize+=pixelAccumulatorLocalMemorySize; 5574 5575 /* local memory size for the weight accumulator */ 5576 weightAccumulatorLocalMemorySize = chunkSize * sizeof(float); 5577 totalLocalMemorySize+=weightAccumulatorLocalMemorySize; 5578 5579 /* local memory size for the gamma accumulator */ 5580 if (matte == 0) 5581 gammaAccumulatorLocalMemorySize = sizeof(float); 5582 else 5583 gammaAccumulatorLocalMemorySize = chunkSize * sizeof(float); 5584 totalLocalMemorySize+=gammaAccumulatorLocalMemorySize; 5585 5586 if (totalLocalMemorySize <= deviceLocalMemorySize) 5587 break; 5588 else 5589 { 5590 pixelPerWorkgroup = pixelPerWorkgroup/2; 5591 chunkSize = chunkSize/2; 5592 if (pixelPerWorkgroup == 0 5593 || chunkSize == 0) 5594 { 5595 /* quit, fallback to CPU */ 5596 goto cleanup; 5597 } 5598 } 5599 } 5600 5601 resizeFilterType = (int)GetResizeFilterWeightingType(resizeFilter); 5602 resizeWindowType = (int)GetResizeFilterWindowWeightingType(resizeFilter); 5603 5604 verticalKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "ResizeVerticalFilter"); 5605 if (verticalKernel == NULL) 5606 { 5607 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 5608 goto cleanup; 5609 } 5610 5611 i = 0; 5612 clStatus = clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(cl_mem), (void*)&image); 5613 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(unsigned int), (void*)&imageColumns); 5614 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(unsigned int), (void*)&imageRows); 5615 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(unsigned int), (void*)&matte); 5616 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(float), (void*)&yFactor); 5617 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(cl_mem), (void*)&resizedImage); 5618 5619 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(unsigned int), (void*)&resizedColumns); 5620 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(unsigned int), (void*)&resizedRows); 5621 5622 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(int), (void*)&resizeFilterType); 5623 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(int), (void*)&resizeWindowType); 5624 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(cl_mem), (void*)&resizeFilterCubicCoefficients); 5625 5626 resizeFilterScale = (float) GetResizeFilterScale(resizeFilter); 5627 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(float), (void*)&resizeFilterScale); 5628 5629 resizeFilterSupport = (float) GetResizeFilterSupport(resizeFilter); 5630 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(float), (void*)&resizeFilterSupport); 5631 5632 resizeFilterWindowSupport = (float) GetResizeFilterWindowSupport(resizeFilter); 5633 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(float), (void*)&resizeFilterWindowSupport); 5634 5635 resizeFilterBlur = (float) GetResizeFilterBlur(resizeFilter); 5636 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(float), (void*)&resizeFilterBlur); 5637 5638 5639 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, imageCacheLocalMemorySize, NULL); 5640 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(int), &numCachedPixels); 5641 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(unsigned int), &pixelPerWorkgroup); 5642 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, sizeof(unsigned int), &chunkSize); 5643 5644 5645 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, pixelAccumulatorLocalMemorySize, NULL); 5646 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, weightAccumulatorLocalMemorySize, NULL); 5647 clStatus |= clEnv->library->clSetKernelArg(verticalKernel, i++, gammaAccumulatorLocalMemorySize, NULL); 5648 5649 if (clStatus != CL_SUCCESS) 5650 { 5651 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 5652 goto cleanup; 5653 } 5654 5655 global_work_size[0] = resizedColumns; 5656 global_work_size[1] = (resizedRows+pixelPerWorkgroup-1)/pixelPerWorkgroup*workgroupSize; 5657 5658 local_work_size[0] = 1; 5659 local_work_size[1] = workgroupSize; 5660 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, verticalKernel, 2, NULL, global_work_size, local_work_size, 0, NULL, &event); 5661 if (clStatus != CL_SUCCESS) 5662 { 5663 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 5664 goto cleanup; 5665 } 5666 clEnv->library->clFlush(queue); 5667 RecordProfileData(clEnv,ResizeVerticalKernel,event); 5668 clEnv->library->clReleaseEvent(event); 5669 status = MagickTrue; 5670 5671 5672cleanup: 5673 OpenCLLogException(__FUNCTION__,__LINE__,exception); 5674 5675 if (verticalKernel != NULL) RelinquishOpenCLKernel(clEnv, verticalKernel); 5676 5677 return(status); 5678} 5679 5680static Image *ComputeResizeImage(const Image* image, 5681 const size_t resizedColumns,const size_t resizedRows, 5682 const ResizeFilter *resizeFilter,ExceptionInfo *exception) 5683{ 5684 CacheView 5685 *filteredImage_view, 5686 *image_view; 5687 5688 cl_command_queue 5689 queue; 5690 5691 cl_int 5692 clStatus; 5693 5694 cl_context 5695 context; 5696 5697 cl_mem 5698 cubicCoefficientsBuffer, 5699 filteredImageBuffer, 5700 imageBuffer, 5701 tempImageBuffer; 5702 5703 cl_mem_flags 5704 mem_flags; 5705 5706 const double 5707 *resizeFilterCoefficient; 5708 5709 const void 5710 *inputPixels; 5711 5712 float 5713 *mappedCoefficientBuffer, 5714 xFactor, 5715 yFactor; 5716 5717 MagickBooleanType 5718 outputReady, 5719 status; 5720 5721 MagickCLEnv 5722 clEnv; 5723 5724 MagickSizeType 5725 length; 5726 5727 Image 5728 *filteredImage; 5729 5730 unsigned int 5731 i, 5732 matte; 5733 5734 void 5735 *filteredPixels, 5736 *hostPtr; 5737 5738 outputReady = MagickFalse; 5739 filteredImage = NULL; 5740 filteredImage_view = NULL; 5741 clEnv = NULL; 5742 context = NULL; 5743 imageBuffer = NULL; 5744 tempImageBuffer = NULL; 5745 filteredImageBuffer = NULL; 5746 cubicCoefficientsBuffer = NULL; 5747 queue = NULL; 5748 5749 clEnv = GetDefaultOpenCLEnv(); 5750 context = GetOpenCLContext(clEnv); 5751 5752 /* Create and initialize OpenCL buffers. */ 5753 image_view=AcquireVirtualCacheView(image,exception); 5754 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 5755 if (inputPixels == (const void *) NULL) 5756 { 5757 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 5758 goto cleanup; 5759 } 5760 5761 /* If the host pointer is aligned to the size of CLPixelPacket, 5762 then use the host buffer directly from the GPU; otherwise, 5763 create a buffer on the GPU and copy the data over */ 5764 if (ALIGNED(inputPixels,CLPixelPacket)) 5765 { 5766 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 5767 } 5768 else 5769 { 5770 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 5771 } 5772 /* create a CL buffer from image pixel buffer */ 5773 length = image->columns * image->rows; 5774 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 5775 if (clStatus != CL_SUCCESS) 5776 { 5777 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 5778 goto cleanup; 5779 } 5780 5781 cubicCoefficientsBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY, 7 * sizeof(float), NULL, &clStatus); 5782 if (clStatus != CL_SUCCESS) 5783 { 5784 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 5785 goto cleanup; 5786 } 5787 queue = AcquireOpenCLCommandQueue(clEnv); 5788 mappedCoefficientBuffer = (float*)clEnv->library->clEnqueueMapBuffer(queue, cubicCoefficientsBuffer, CL_TRUE, CL_MAP_WRITE, 0, 7 * sizeof(float) 5789 , 0, NULL, NULL, &clStatus); 5790 if (clStatus != CL_SUCCESS) 5791 { 5792 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueMapBuffer failed.","."); 5793 goto cleanup; 5794 } 5795 resizeFilterCoefficient = GetResizeFilterCoefficient(resizeFilter); 5796 for (i = 0; i < 7; i++) 5797 { 5798 mappedCoefficientBuffer[i] = (float) resizeFilterCoefficient[i]; 5799 } 5800 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, cubicCoefficientsBuffer, mappedCoefficientBuffer, 0, NULL, NULL); 5801 if (clStatus != CL_SUCCESS) 5802 { 5803 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 5804 goto cleanup; 5805 } 5806 5807 filteredImage = CloneImage(image,resizedColumns,resizedRows,MagickTrue,exception); 5808 if (filteredImage == NULL) 5809 goto cleanup; 5810 5811 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 5812 { 5813 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 5814 goto cleanup; 5815 } 5816 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 5817 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 5818 if (filteredPixels == (void *) NULL) 5819 { 5820 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 5821 goto cleanup; 5822 } 5823 5824 if (ALIGNED(filteredPixels,CLPixelPacket)) 5825 { 5826 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 5827 hostPtr = filteredPixels; 5828 } 5829 else 5830 { 5831 mem_flags = CL_MEM_WRITE_ONLY; 5832 hostPtr = NULL; 5833 } 5834 5835 /* create a CL buffer from image pixel buffer */ 5836 length = filteredImage->columns * filteredImage->rows; 5837 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 5838 if (clStatus != CL_SUCCESS) 5839 { 5840 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 5841 goto cleanup; 5842 } 5843 5844 xFactor=(float) resizedColumns/(float) image->columns; 5845 yFactor=(float) resizedRows/(float) image->rows; 5846 matte=(image->alpha_trait > CopyPixelTrait)?1:0; 5847 if (xFactor > yFactor) 5848 { 5849 5850 length = resizedColumns*image->rows; 5851 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length*sizeof(CLPixelPacket), NULL, &clStatus); 5852 if (clStatus != CL_SUCCESS) 5853 { 5854 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 5855 goto cleanup; 5856 } 5857 5858 status = resizeHorizontalFilter(imageBuffer, (unsigned int) image->columns, (unsigned int) image->rows, matte 5859 , tempImageBuffer, (unsigned int) resizedColumns, (unsigned int) image->rows 5860 , resizeFilter, cubicCoefficientsBuffer 5861 , xFactor, clEnv, queue, exception); 5862 if (status != MagickTrue) 5863 goto cleanup; 5864 5865 status = resizeVerticalFilter(tempImageBuffer, (unsigned int) resizedColumns, (unsigned int) image->rows, matte 5866 , filteredImageBuffer, (unsigned int) resizedColumns, (unsigned int) resizedRows 5867 , resizeFilter, cubicCoefficientsBuffer 5868 , yFactor, clEnv, queue, exception); 5869 if (status != MagickTrue) 5870 goto cleanup; 5871 } 5872 else 5873 { 5874 length = image->columns*resizedRows; 5875 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length*sizeof(CLPixelPacket), NULL, &clStatus); 5876 if (clStatus != CL_SUCCESS) 5877 { 5878 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 5879 goto cleanup; 5880 } 5881 5882 status = resizeVerticalFilter(imageBuffer, (unsigned int) image->columns, (unsigned int) image->rows, matte 5883 , tempImageBuffer, (unsigned int) image->columns, (unsigned int) resizedRows 5884 , resizeFilter, cubicCoefficientsBuffer 5885 , yFactor, clEnv, queue, exception); 5886 if (status != MagickTrue) 5887 goto cleanup; 5888 5889 status = resizeHorizontalFilter(tempImageBuffer, (unsigned int) image->columns, (unsigned int) resizedRows, matte 5890 , filteredImageBuffer, (unsigned int) resizedColumns, (unsigned int) resizedRows 5891 , resizeFilter, cubicCoefficientsBuffer 5892 , xFactor, clEnv, queue, exception); 5893 if (status != MagickTrue) 5894 goto cleanup; 5895 } 5896 length = resizedColumns*resizedRows; 5897 if (ALIGNED(filteredPixels,CLPixelPacket)) 5898 { 5899 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 5900 } 5901 else 5902 { 5903 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 5904 } 5905 if (clStatus != CL_SUCCESS) 5906 { 5907 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 5908 goto cleanup; 5909 } 5910 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 5911 5912cleanup: 5913 OpenCLLogException(__FUNCTION__,__LINE__,exception); 5914 5915 image_view=DestroyCacheView(image_view); 5916 if (filteredImage_view != NULL) 5917 filteredImage_view=DestroyCacheView(filteredImage_view); 5918 5919 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 5920 if (tempImageBuffer!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer); 5921 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 5922 if (cubicCoefficientsBuffer!=NULL) clEnv->library->clReleaseMemObject(cubicCoefficientsBuffer); 5923 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 5924 if (outputReady == MagickFalse && filteredImage != NULL) 5925 filteredImage=DestroyImage(filteredImage); 5926 return(filteredImage); 5927} 5928 5929static MagickBooleanType gpuSupportedResizeWeighting( 5930 ResizeWeightingFunctionType f) 5931{ 5932 unsigned int 5933 i; 5934 5935 for (i = 0; ;i++) 5936 { 5937 if (supportedResizeWeighting[i] == LastWeightingFunction) 5938 break; 5939 if (supportedResizeWeighting[i] == f) 5940 return(MagickTrue); 5941 } 5942 return(MagickFalse); 5943} 5944 5945MagickExport Image *AccelerateResizeImage(const Image *image, 5946 const size_t resizedColumns,const size_t resizedRows, 5947 const ResizeFilter *resizeFilter,ExceptionInfo *exception) 5948{ 5949 Image 5950 *filteredImage; 5951 5952 assert(image != NULL); 5953 assert(exception != (ExceptionInfo *) NULL); 5954 5955 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 5956 (checkOpenCLEnvironment(exception) == MagickFalse)) 5957 return NULL; 5958 5959 if ((gpuSupportedResizeWeighting(GetResizeFilterWeightingType( 5960 resizeFilter)) == MagickFalse) || 5961 (gpuSupportedResizeWeighting(GetResizeFilterWindowWeightingType( 5962 resizeFilter)) == MagickFalse)) 5963 return NULL; 5964 5965 filteredImage=ComputeResizeImage(image,resizedColumns,resizedRows, 5966 resizeFilter,exception); 5967 return(filteredImage); 5968} 5969 5970/* 5971%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5972% % 5973% % 5974% % 5975% A c c e l e r a t e R o t a t i o n a l B l u r I m a g e % 5976% % 5977% % 5978% % 5979%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5980*/ 5981 5982static Image* ComputeRotationalBlurImage(const Image *image,const double angle, 5983 ExceptionInfo *exception) 5984{ 5985 CacheView 5986 *image_view, 5987 *filteredImage_view; 5988 5989 cl_command_queue 5990 queue; 5991 5992 cl_context 5993 context; 5994 5995 cl_float2 5996 blurCenter; 5997 5998 cl_float4 5999 biasPixel; 6000 6001 cl_int 6002 clStatus; 6003 6004 cl_mem 6005 cosThetaBuffer, 6006 filteredImageBuffer, 6007 imageBuffer, 6008 sinThetaBuffer; 6009 6010 cl_mem_flags 6011 mem_flags; 6012 6013 cl_kernel 6014 rotationalBlurKernel; 6015 6016 cl_event 6017 event; 6018 6019 const void 6020 *inputPixels; 6021 6022 float 6023 blurRadius, 6024 *cosThetaPtr, 6025 offset, 6026 *sinThetaPtr, 6027 theta; 6028 6029 Image 6030 *filteredImage; 6031 6032 MagickBooleanType 6033 outputReady; 6034 6035 MagickCLEnv 6036 clEnv; 6037 6038 PixelInfo 6039 bias; 6040 6041 MagickSizeType 6042 length; 6043 6044 size_t 6045 global_work_size[2]; 6046 6047 unsigned int 6048 cossin_theta_size, 6049 i, 6050 matte; 6051 6052 void 6053 *filteredPixels, 6054 *hostPtr; 6055 6056 outputReady = MagickFalse; 6057 context = NULL; 6058 filteredImage = NULL; 6059 filteredImage_view = NULL; 6060 imageBuffer = NULL; 6061 filteredImageBuffer = NULL; 6062 sinThetaBuffer = NULL; 6063 cosThetaBuffer = NULL; 6064 queue = NULL; 6065 rotationalBlurKernel = NULL; 6066 6067 6068 clEnv = GetDefaultOpenCLEnv(); 6069 context = GetOpenCLContext(clEnv); 6070 6071 6072 /* Create and initialize OpenCL buffers. */ 6073 6074 image_view=AcquireVirtualCacheView(image,exception); 6075 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 6076 if (inputPixels == (const void *) NULL) 6077 { 6078 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 6079 goto cleanup; 6080 } 6081 6082 /* If the host pointer is aligned to the size of CLPixelPacket, 6083 then use the host buffer directly from the GPU; otherwise, 6084 create a buffer on the GPU and copy the data over */ 6085 if (ALIGNED(inputPixels,CLPixelPacket)) 6086 { 6087 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 6088 } 6089 else 6090 { 6091 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 6092 } 6093 /* create a CL buffer from image pixel buffer */ 6094 length = image->columns * image->rows; 6095 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 6096 if (clStatus != CL_SUCCESS) 6097 { 6098 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6099 goto cleanup; 6100 } 6101 6102 6103 filteredImage = CloneImage(image,image->columns,image->rows,MagickTrue,exception); 6104 assert(filteredImage != NULL); 6105 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 6106 { 6107 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 6108 goto cleanup; 6109 } 6110 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 6111 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 6112 if (filteredPixels == (void *) NULL) 6113 { 6114 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 6115 goto cleanup; 6116 } 6117 6118 if (ALIGNED(filteredPixels,CLPixelPacket)) 6119 { 6120 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 6121 hostPtr = filteredPixels; 6122 } 6123 else 6124 { 6125 mem_flags = CL_MEM_WRITE_ONLY; 6126 hostPtr = NULL; 6127 } 6128 /* create a CL buffer from image pixel buffer */ 6129 length = image->columns * image->rows; 6130 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 6131 if (clStatus != CL_SUCCESS) 6132 { 6133 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6134 goto cleanup; 6135 } 6136 6137 blurCenter.s[0] = (float) (image->columns-1)/2.0; 6138 blurCenter.s[1] = (float) (image->rows-1)/2.0; 6139 blurRadius=hypot(blurCenter.s[0],blurCenter.s[1]); 6140 cossin_theta_size=(unsigned int) fabs(4.0*DegreesToRadians(angle)*sqrt((double)blurRadius)+2UL); 6141 6142 /* create a buffer for sin_theta and cos_theta */ 6143 sinThetaBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, cossin_theta_size * sizeof(float), NULL, &clStatus); 6144 if (clStatus != CL_SUCCESS) 6145 { 6146 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6147 goto cleanup; 6148 } 6149 cosThetaBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_ALLOC_HOST_PTR, cossin_theta_size * sizeof(float), NULL, &clStatus); 6150 if (clStatus != CL_SUCCESS) 6151 { 6152 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6153 goto cleanup; 6154 } 6155 6156 6157 queue = AcquireOpenCLCommandQueue(clEnv); 6158 sinThetaPtr = (float*) clEnv->library->clEnqueueMapBuffer(queue, sinThetaBuffer, CL_TRUE, CL_MAP_WRITE, 0, cossin_theta_size*sizeof(float), 0, NULL, NULL, &clStatus); 6159 if (clStatus != CL_SUCCESS) 6160 { 6161 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnqueuemapBuffer failed.","."); 6162 goto cleanup; 6163 } 6164 6165 cosThetaPtr = (float*) clEnv->library->clEnqueueMapBuffer(queue, cosThetaBuffer, CL_TRUE, CL_MAP_WRITE, 0, cossin_theta_size*sizeof(float), 0, NULL, NULL, &clStatus); 6166 if (clStatus != CL_SUCCESS) 6167 { 6168 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnqueuemapBuffer failed.","."); 6169 goto cleanup; 6170 } 6171 6172 theta=DegreesToRadians(angle)/(MagickRealType) (cossin_theta_size-1); 6173 offset=theta*(MagickRealType) (cossin_theta_size-1)/2.0; 6174 for (i=0; i < (ssize_t) cossin_theta_size; i++) 6175 { 6176 cosThetaPtr[i]=(float)cos((double) (theta*i-offset)); 6177 sinThetaPtr[i]=(float)sin((double) (theta*i-offset)); 6178 } 6179 6180 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, sinThetaBuffer, sinThetaPtr, 0, NULL, NULL); 6181 clStatus |= clEnv->library->clEnqueueUnmapMemObject(queue, cosThetaBuffer, cosThetaPtr, 0, NULL, NULL); 6182 if (clStatus != CL_SUCCESS) 6183 { 6184 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 6185 goto cleanup; 6186 } 6187 6188 /* get the OpenCL kernel */ 6189 rotationalBlurKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "RotationalBlur"); 6190 if (rotationalBlurKernel == NULL) 6191 { 6192 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 6193 goto cleanup; 6194 } 6195 6196 6197 /* set the kernel arguments */ 6198 i = 0; 6199 clStatus=clEnv->library->clSetKernelArg(rotationalBlurKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 6200 clStatus|=clEnv->library->clSetKernelArg(rotationalBlurKernel,i++,sizeof(cl_mem),(void *)&filteredImageBuffer); 6201 6202 GetPixelInfo(image,&bias); 6203 biasPixel.s[0] = bias.red; 6204 biasPixel.s[1] = bias.green; 6205 biasPixel.s[2] = bias.blue; 6206 biasPixel.s[3] = bias.alpha; 6207 clStatus|=clEnv->library->clSetKernelArg(rotationalBlurKernel,i++,sizeof(cl_float4), &biasPixel); 6208 clStatus|=clEnv->library->clSetKernelArg(rotationalBlurKernel,i++,sizeof(ChannelType), &image->channel_mask); 6209 6210 matte = (image->alpha_trait > CopyPixelTrait)?1:0; 6211 clStatus|=clEnv->library->clSetKernelArg(rotationalBlurKernel,i++,sizeof(unsigned int), &matte); 6212 6213 clStatus=clEnv->library->clSetKernelArg(rotationalBlurKernel,i++,sizeof(cl_float2), &blurCenter); 6214 6215 clStatus|=clEnv->library->clSetKernelArg(rotationalBlurKernel,i++,sizeof(cl_mem),(void *)&cosThetaBuffer); 6216 clStatus|=clEnv->library->clSetKernelArg(rotationalBlurKernel,i++,sizeof(cl_mem),(void *)&sinThetaBuffer); 6217 clStatus|=clEnv->library->clSetKernelArg(rotationalBlurKernel,i++,sizeof(unsigned int), &cossin_theta_size); 6218 if (clStatus != CL_SUCCESS) 6219 { 6220 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 6221 goto cleanup; 6222 } 6223 6224 6225 global_work_size[0] = image->columns; 6226 global_work_size[1] = image->rows; 6227 /* launch the kernel */ 6228 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, rotationalBlurKernel, 2, NULL, global_work_size, NULL, 0, NULL, &event); 6229 if (clStatus != CL_SUCCESS) 6230 { 6231 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 6232 goto cleanup; 6233 } 6234 clEnv->library->clFlush(queue); 6235 RecordProfileData(clEnv,RotationalBlurKernel,event); 6236 clEnv->library->clReleaseEvent(event); 6237 6238 if (ALIGNED(filteredPixels,CLPixelPacket)) 6239 { 6240 length = image->columns * image->rows; 6241 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 6242 } 6243 else 6244 { 6245 length = image->columns * image->rows; 6246 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 6247 } 6248 if (clStatus != CL_SUCCESS) 6249 { 6250 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 6251 goto cleanup; 6252 } 6253 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 6254 6255cleanup: 6256 OpenCLLogException(__FUNCTION__,__LINE__,exception); 6257 6258 image_view=DestroyCacheView(image_view); 6259 if (filteredImage_view != NULL) 6260 filteredImage_view=DestroyCacheView(filteredImage_view); 6261 6262 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 6263 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 6264 if (sinThetaBuffer!=NULL) clEnv->library->clReleaseMemObject(sinThetaBuffer); 6265 if (cosThetaBuffer!=NULL) clEnv->library->clReleaseMemObject(cosThetaBuffer); 6266 if (rotationalBlurKernel!=NULL) RelinquishOpenCLKernel(clEnv, rotationalBlurKernel); 6267 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 6268 if (outputReady == MagickFalse) 6269 { 6270 if (filteredImage != NULL) 6271 { 6272 DestroyImage(filteredImage); 6273 filteredImage = NULL; 6274 } 6275 } 6276 return filteredImage; 6277} 6278 6279MagickExport Image* AccelerateRotationalBlurImage(const Image *image, 6280 const double angle,ExceptionInfo *exception) 6281{ 6282 Image 6283 *filteredImage; 6284 6285 assert(image != NULL); 6286 assert(exception != (ExceptionInfo *) NULL); 6287 6288 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 6289 (checkOpenCLEnvironment(exception) == MagickFalse)) 6290 return NULL; 6291 6292 filteredImage=ComputeRotationalBlurImage(image,angle,exception); 6293 return filteredImage; 6294} 6295 6296/* 6297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6298% % 6299% % 6300% % 6301% A c c e l e r a t e U n s h a r p M a s k I m a g e % 6302% % 6303% % 6304% % 6305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6306*/ 6307 6308static Image *ComputeUnsharpMaskImage(const Image *image,const double radius, 6309 const double sigma,const double gain,const double threshold, 6310 ExceptionInfo *exception) 6311{ 6312 CacheView 6313 *filteredImage_view, 6314 *image_view; 6315 6316 char 6317 geometry[MagickPathExtent]; 6318 6319 cl_command_queue 6320 queue; 6321 6322 cl_context 6323 context; 6324 6325 cl_int 6326 clStatus; 6327 6328 cl_kernel 6329 blurRowKernel, 6330 unsharpMaskBlurColumnKernel; 6331 6332 cl_event 6333 event; 6334 6335 cl_mem 6336 filteredImageBuffer, 6337 imageBuffer, 6338 imageKernelBuffer, 6339 tempImageBuffer; 6340 6341 cl_mem_flags 6342 mem_flags; 6343 6344 const void 6345 *inputPixels; 6346 6347 float 6348 fGain, 6349 fThreshold, 6350 *kernelBufferPtr; 6351 6352 Image 6353 *filteredImage; 6354 6355 int 6356 chunkSize; 6357 6358 KernelInfo 6359 *kernel; 6360 6361 MagickBooleanType 6362 outputReady; 6363 6364 MagickCLEnv 6365 clEnv; 6366 6367 MagickSizeType 6368 length; 6369 6370 void 6371 *filteredPixels, 6372 *hostPtr; 6373 6374 unsigned int 6375 i, 6376 imageColumns, 6377 imageRows, 6378 kernelWidth; 6379 6380 clEnv = NULL; 6381 filteredImage = NULL; 6382 filteredImage_view = NULL; 6383 kernel = NULL; 6384 context = NULL; 6385 imageBuffer = NULL; 6386 filteredImageBuffer = NULL; 6387 tempImageBuffer = NULL; 6388 imageKernelBuffer = NULL; 6389 blurRowKernel = NULL; 6390 unsharpMaskBlurColumnKernel = NULL; 6391 queue = NULL; 6392 outputReady = MagickFalse; 6393 6394 clEnv = GetDefaultOpenCLEnv(); 6395 context = GetOpenCLContext(clEnv); 6396 queue = AcquireOpenCLCommandQueue(clEnv); 6397 6398 /* Create and initialize OpenCL buffers. */ 6399 { 6400 image_view=AcquireVirtualCacheView(image,exception); 6401 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 6402 if (inputPixels == (const void *) NULL) 6403 { 6404 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 6405 goto cleanup; 6406 } 6407 6408 /* If the host pointer is aligned to the size of CLPixelPacket, 6409 then use the host buffer directly from the GPU; otherwise, 6410 create a buffer on the GPU and copy the data over */ 6411 if (ALIGNED(inputPixels,CLPixelPacket)) 6412 { 6413 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 6414 } 6415 else 6416 { 6417 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 6418 } 6419 /* create a CL buffer from image pixel buffer */ 6420 length = image->columns * image->rows; 6421 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 6422 if (clStatus != CL_SUCCESS) 6423 { 6424 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6425 goto cleanup; 6426 } 6427 } 6428 6429 /* create output */ 6430 { 6431 filteredImage = CloneImage(image,image->columns,image->rows,MagickTrue,exception); 6432 assert(filteredImage != NULL); 6433 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 6434 { 6435 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 6436 goto cleanup; 6437 } 6438 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 6439 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 6440 if (filteredPixels == (void *) NULL) 6441 { 6442 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 6443 goto cleanup; 6444 } 6445 6446 if (ALIGNED(filteredPixels,CLPixelPacket)) 6447 { 6448 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 6449 hostPtr = filteredPixels; 6450 } 6451 else 6452 { 6453 mem_flags = CL_MEM_WRITE_ONLY; 6454 hostPtr = NULL; 6455 } 6456 6457 /* create a CL buffer from image pixel buffer */ 6458 length = image->columns * image->rows; 6459 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 6460 if (clStatus != CL_SUCCESS) 6461 { 6462 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6463 goto cleanup; 6464 } 6465 } 6466 6467 /* create the blur kernel */ 6468 { 6469 (void) FormatLocaleString(geometry,MagickPathExtent,"blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma); 6470 kernel=AcquireKernelInfo(geometry,exception); 6471 if (kernel == (KernelInfo *) NULL) 6472 { 6473 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireKernelInfo failed.","."); 6474 goto cleanup; 6475 } 6476 6477 imageKernelBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY, kernel->width * sizeof(float), NULL, &clStatus); 6478 if (clStatus != CL_SUCCESS) 6479 { 6480 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6481 goto cleanup; 6482 } 6483 6484 6485 kernelBufferPtr = (float*)clEnv->library->clEnqueueMapBuffer(queue, imageKernelBuffer, CL_TRUE, CL_MAP_WRITE, 0, kernel->width * sizeof(float), 0, NULL, NULL, &clStatus); 6486 if (clStatus != CL_SUCCESS) 6487 { 6488 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueMapBuffer failed.","."); 6489 goto cleanup; 6490 } 6491 for (i = 0; i < kernel->width; i++) 6492 { 6493 kernelBufferPtr[i] = (float) kernel->values[i]; 6494 } 6495 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, imageKernelBuffer, kernelBufferPtr, 0, NULL, NULL); 6496 if (clStatus != CL_SUCCESS) 6497 { 6498 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 6499 goto cleanup; 6500 } 6501 } 6502 6503 { 6504 /* create temp buffer */ 6505 { 6506 length = image->columns * image->rows; 6507 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length * 4 * sizeof(float), NULL, &clStatus); 6508 if (clStatus != CL_SUCCESS) 6509 { 6510 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6511 goto cleanup; 6512 } 6513 } 6514 6515 /* get the opencl kernel */ 6516 { 6517 blurRowKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "BlurRow"); 6518 if (blurRowKernel == NULL) 6519 { 6520 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 6521 goto cleanup; 6522 }; 6523 6524 unsharpMaskBlurColumnKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "UnsharpMaskBlurColumn"); 6525 if (unsharpMaskBlurColumnKernel == NULL) 6526 { 6527 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 6528 goto cleanup; 6529 }; 6530 } 6531 6532 { 6533 chunkSize = 256; 6534 6535 imageColumns = (unsigned int) image->columns; 6536 imageRows = (unsigned int) image->rows; 6537 6538 kernelWidth = (unsigned int) kernel->width; 6539 6540 /* set the kernel arguments */ 6541 i = 0; 6542 clStatus=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 6543 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&tempImageBuffer); 6544 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(ChannelType),&image->channel_mask); 6545 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&imageKernelBuffer); 6546 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&kernelWidth); 6547 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 6548 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&imageRows); 6549 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(CLPixelPacket)*(chunkSize+kernel->width),(void *) NULL); 6550 if (clStatus != CL_SUCCESS) 6551 { 6552 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 6553 goto cleanup; 6554 } 6555 } 6556 6557 /* launch the kernel */ 6558 { 6559 size_t gsize[2]; 6560 size_t wsize[2]; 6561 6562 gsize[0] = chunkSize*((image->columns+chunkSize-1)/chunkSize); 6563 gsize[1] = image->rows; 6564 wsize[0] = chunkSize; 6565 wsize[1] = 1; 6566 6567 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurRowKernel, 2, NULL, gsize, wsize, 0, NULL, &event); 6568 if (clStatus != CL_SUCCESS) 6569 { 6570 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 6571 goto cleanup; 6572 } 6573 clEnv->library->clFlush(queue); 6574 RecordProfileData(clEnv,BlurRowKernel,event); 6575 clEnv->library->clReleaseEvent(event); 6576 } 6577 6578 6579 { 6580 chunkSize = 256; 6581 imageColumns = (unsigned int) image->columns; 6582 imageRows = (unsigned int) image->rows; 6583 kernelWidth = (unsigned int) kernel->width; 6584 fGain = (float) gain; 6585 fThreshold = (float) threshold; 6586 6587 i = 0; 6588 clStatus=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 6589 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(cl_mem),(void *)&tempImageBuffer); 6590 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(cl_mem),(void *)&filteredImageBuffer); 6591 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 6592 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(unsigned int),(void *)&imageRows); 6593 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++, (chunkSize+kernelWidth-1)*sizeof(cl_float4),NULL); 6594 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++, kernelWidth*sizeof(float),NULL); 6595 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(ChannelType),&image->channel_mask); 6596 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(cl_mem),(void *)&imageKernelBuffer); 6597 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(unsigned int),(void *)&kernelWidth); 6598 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(float),(void *)&fGain); 6599 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(float),(void *)&fThreshold); 6600 6601 if (clStatus != CL_SUCCESS) 6602 { 6603 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 6604 goto cleanup; 6605 } 6606 } 6607 6608 /* launch the kernel */ 6609 { 6610 size_t gsize[2]; 6611 size_t wsize[2]; 6612 6613 gsize[0] = image->columns; 6614 gsize[1] = chunkSize*((image->rows+chunkSize-1)/chunkSize); 6615 wsize[0] = 1; 6616 wsize[1] = chunkSize; 6617 6618 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, unsharpMaskBlurColumnKernel, 2, NULL, gsize, wsize, 0, NULL, &event); 6619 if (clStatus != CL_SUCCESS) 6620 { 6621 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 6622 goto cleanup; 6623 } 6624 clEnv->library->clFlush(queue); 6625 RecordProfileData(clEnv,UnsharpMaskBlurColumnKernel,event); 6626 clEnv->library->clReleaseEvent(event); 6627 } 6628 6629 } 6630 6631 /* get result */ 6632 if (ALIGNED(filteredPixels,CLPixelPacket)) 6633 { 6634 length = image->columns * image->rows; 6635 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 6636 } 6637 else 6638 { 6639 length = image->columns * image->rows; 6640 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 6641 } 6642 if (clStatus != CL_SUCCESS) 6643 { 6644 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 6645 goto cleanup; 6646 } 6647 6648 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 6649 6650cleanup: 6651 OpenCLLogException(__FUNCTION__,__LINE__,exception); 6652 6653 image_view=DestroyCacheView(image_view); 6654 if (filteredImage_view != NULL) 6655 filteredImage_view=DestroyCacheView(filteredImage_view); 6656 6657 if (kernel != NULL) kernel=DestroyKernelInfo(kernel); 6658 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 6659 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 6660 if (tempImageBuffer!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer); 6661 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer); 6662 if (blurRowKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurRowKernel); 6663 if (unsharpMaskBlurColumnKernel!=NULL) RelinquishOpenCLKernel(clEnv, unsharpMaskBlurColumnKernel); 6664 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 6665 if (outputReady == MagickFalse) 6666 { 6667 if (filteredImage != NULL) 6668 { 6669 DestroyImage(filteredImage); 6670 filteredImage = NULL; 6671 } 6672 } 6673 return(filteredImage); 6674} 6675 6676static Image *ComputeUnsharpMaskImageSection(const Image *image, 6677 const double radius,const double sigma,const double gain, 6678 const double threshold,ExceptionInfo *exception) 6679{ 6680 CacheView 6681 *filteredImage_view, 6682 *image_view; 6683 6684 char 6685 geometry[MagickPathExtent]; 6686 6687 cl_command_queue 6688 queue; 6689 6690 cl_context 6691 context; 6692 6693 cl_int 6694 clStatus; 6695 6696 cl_kernel 6697 blurRowKernel, 6698 unsharpMaskBlurColumnKernel; 6699 6700 cl_event 6701 event; 6702 6703 cl_mem 6704 filteredImageBuffer, 6705 imageBuffer, 6706 imageKernelBuffer, 6707 tempImageBuffer; 6708 6709 cl_mem_flags 6710 mem_flags; 6711 6712 const void 6713 *inputPixels; 6714 6715 float 6716 fGain, 6717 fThreshold, 6718 *kernelBufferPtr; 6719 6720 Image 6721 *filteredImage; 6722 6723 int 6724 chunkSize; 6725 6726 KernelInfo 6727 *kernel; 6728 6729 MagickBooleanType 6730 outputReady; 6731 6732 MagickCLEnv 6733 clEnv; 6734 6735 MagickSizeType 6736 length; 6737 6738 void 6739 *filteredPixels, 6740 *hostPtr; 6741 6742 unsigned int 6743 i, 6744 imageColumns, 6745 imageRows, 6746 kernelWidth; 6747 6748 clEnv = NULL; 6749 filteredImage = NULL; 6750 filteredImage_view = NULL; 6751 kernel = NULL; 6752 context = NULL; 6753 imageBuffer = NULL; 6754 filteredImageBuffer = NULL; 6755 tempImageBuffer = NULL; 6756 imageKernelBuffer = NULL; 6757 blurRowKernel = NULL; 6758 unsharpMaskBlurColumnKernel = NULL; 6759 queue = NULL; 6760 outputReady = MagickFalse; 6761 6762 clEnv = GetDefaultOpenCLEnv(); 6763 context = GetOpenCLContext(clEnv); 6764 queue = AcquireOpenCLCommandQueue(clEnv); 6765 6766 /* Create and initialize OpenCL buffers. */ 6767 { 6768 image_view=AcquireVirtualCacheView(image,exception); 6769 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 6770 if (inputPixels == (const void *) NULL) 6771 { 6772 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 6773 goto cleanup; 6774 } 6775 6776 /* If the host pointer is aligned to the size of CLPixelPacket, 6777 then use the host buffer directly from the GPU; otherwise, 6778 create a buffer on the GPU and copy the data over */ 6779 if (ALIGNED(inputPixels,CLPixelPacket)) 6780 { 6781 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 6782 } 6783 else 6784 { 6785 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 6786 } 6787 /* create a CL buffer from image pixel buffer */ 6788 length = image->columns * image->rows; 6789 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 6790 if (clStatus != CL_SUCCESS) 6791 { 6792 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6793 goto cleanup; 6794 } 6795 } 6796 6797 /* create output */ 6798 { 6799 filteredImage = CloneImage(image,image->columns,image->rows,MagickTrue,exception); 6800 assert(filteredImage != NULL); 6801 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 6802 { 6803 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 6804 goto cleanup; 6805 } 6806 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 6807 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 6808 if (filteredPixels == (void *) NULL) 6809 { 6810 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 6811 goto cleanup; 6812 } 6813 6814 if (ALIGNED(filteredPixels,CLPixelPacket)) 6815 { 6816 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 6817 hostPtr = filteredPixels; 6818 } 6819 else 6820 { 6821 mem_flags = CL_MEM_WRITE_ONLY; 6822 hostPtr = NULL; 6823 } 6824 6825 /* create a CL buffer from image pixel buffer */ 6826 length = image->columns * image->rows; 6827 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 6828 if (clStatus != CL_SUCCESS) 6829 { 6830 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6831 goto cleanup; 6832 } 6833 } 6834 6835 /* create the blur kernel */ 6836 { 6837 (void) FormatLocaleString(geometry,MagickPathExtent,"blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma); 6838 kernel=AcquireKernelInfo(geometry,exception); 6839 if (kernel == (KernelInfo *) NULL) 6840 { 6841 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireKernelInfo failed.","."); 6842 goto cleanup; 6843 } 6844 6845 imageKernelBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY, kernel->width * sizeof(float), NULL, &clStatus); 6846 if (clStatus != CL_SUCCESS) 6847 { 6848 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6849 goto cleanup; 6850 } 6851 6852 6853 kernelBufferPtr = (float*)clEnv->library->clEnqueueMapBuffer(queue, imageKernelBuffer, CL_TRUE, CL_MAP_WRITE, 0, kernel->width * sizeof(float), 0, NULL, NULL, &clStatus); 6854 if (clStatus != CL_SUCCESS) 6855 { 6856 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueMapBuffer failed.","."); 6857 goto cleanup; 6858 } 6859 for (i = 0; i < kernel->width; i++) 6860 { 6861 kernelBufferPtr[i] = (float) kernel->values[i]; 6862 } 6863 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, imageKernelBuffer, kernelBufferPtr, 0, NULL, NULL); 6864 if (clStatus != CL_SUCCESS) 6865 { 6866 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 6867 goto cleanup; 6868 } 6869 } 6870 6871 { 6872 unsigned int offsetRows; 6873 unsigned int sec; 6874 6875 /* create temp buffer */ 6876 { 6877 length = image->columns * (image->rows / 2 + 1 + (kernel->width-1) / 2); 6878 tempImageBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_WRITE, length * 4 * sizeof(float), NULL, &clStatus); 6879 if (clStatus != CL_SUCCESS) 6880 { 6881 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 6882 goto cleanup; 6883 } 6884 } 6885 6886 /* get the opencl kernel */ 6887 { 6888 blurRowKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "BlurRowSection"); 6889 if (blurRowKernel == NULL) 6890 { 6891 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 6892 goto cleanup; 6893 }; 6894 6895 unsharpMaskBlurColumnKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "UnsharpMaskBlurColumnSection"); 6896 if (unsharpMaskBlurColumnKernel == NULL) 6897 { 6898 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 6899 goto cleanup; 6900 }; 6901 } 6902 6903 for (sec = 0; sec < 2; sec++) 6904 { 6905 { 6906 chunkSize = 256; 6907 6908 imageColumns = (unsigned int) image->columns; 6909 if (sec == 0) 6910 imageRows = (unsigned int) (image->rows / 2 + (kernel->width-1) / 2); 6911 else 6912 imageRows = (unsigned int) ((image->rows - image->rows / 2) + (kernel->width-1) / 2); 6913 6914 offsetRows = (unsigned int) (sec * image->rows / 2); 6915 6916 kernelWidth = (unsigned int) kernel->width; 6917 6918 /* set the kernel arguments */ 6919 i = 0; 6920 clStatus=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 6921 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&tempImageBuffer); 6922 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(ChannelType),&image->channel_mask); 6923 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(cl_mem),(void *)&imageKernelBuffer); 6924 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&kernelWidth); 6925 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 6926 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&imageRows); 6927 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(CLPixelPacket)*(chunkSize+kernel->width),(void *) NULL); 6928 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&offsetRows); 6929 clStatus|=clEnv->library->clSetKernelArg(blurRowKernel,i++,sizeof(unsigned int),(void *)&sec); 6930 if (clStatus != CL_SUCCESS) 6931 { 6932 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 6933 goto cleanup; 6934 } 6935 } 6936 /* launch the kernel */ 6937 { 6938 size_t gsize[2]; 6939 size_t wsize[2]; 6940 6941 gsize[0] = chunkSize*((imageColumns+chunkSize-1)/chunkSize); 6942 gsize[1] = imageRows; 6943 wsize[0] = chunkSize; 6944 wsize[1] = 1; 6945 6946 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, blurRowKernel, 2, NULL, gsize, wsize, 0, NULL, &event); 6947 if (clStatus != CL_SUCCESS) 6948 { 6949 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 6950 goto cleanup; 6951 } 6952 clEnv->library->clFlush(queue); 6953 RecordProfileData(clEnv,BlurRowKernel,event); 6954 clEnv->library->clReleaseEvent(event); 6955 } 6956 6957 6958 { 6959 chunkSize = 256; 6960 6961 imageColumns = (unsigned int) image->columns; 6962 if (sec == 0) 6963 imageRows = (unsigned int) (image->rows / 2); 6964 else 6965 imageRows = (unsigned int) (image->rows - image->rows / 2); 6966 6967 offsetRows = (unsigned int) (sec * image->rows / 2); 6968 6969 kernelWidth = (unsigned int) kernel->width; 6970 6971 fGain = (float) gain; 6972 fThreshold = (float) threshold; 6973 6974 i = 0; 6975 clStatus=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 6976 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(cl_mem),(void *)&tempImageBuffer); 6977 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(cl_mem),(void *)&filteredImageBuffer); 6978 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 6979 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(unsigned int),(void *)&imageRows); 6980 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++, (chunkSize+kernelWidth-1)*sizeof(cl_float4),NULL); 6981 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++, kernelWidth*sizeof(float),NULL); 6982 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(ChannelType),&image->channel_mask); 6983 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(cl_mem),(void *)&imageKernelBuffer); 6984 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(unsigned int),(void *)&kernelWidth); 6985 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(float),(void *)&fGain); 6986 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(float),(void *)&fThreshold); 6987 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(unsigned int),(void *)&offsetRows); 6988 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskBlurColumnKernel,i++,sizeof(unsigned int),(void *)&sec); 6989 6990 if (clStatus != CL_SUCCESS) 6991 { 6992 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 6993 goto cleanup; 6994 } 6995 } 6996 6997 /* launch the kernel */ 6998 { 6999 size_t gsize[2]; 7000 size_t wsize[2]; 7001 7002 gsize[0] = imageColumns; 7003 gsize[1] = chunkSize*((imageRows+chunkSize-1)/chunkSize); 7004 wsize[0] = 1; 7005 wsize[1] = chunkSize; 7006 7007 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, unsharpMaskBlurColumnKernel, 2, NULL, gsize, wsize, 0, NULL, &event); 7008 if (clStatus != CL_SUCCESS) 7009 { 7010 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 7011 goto cleanup; 7012 } 7013 clEnv->library->clFlush(queue); 7014 RecordProfileData(clEnv,UnsharpMaskBlurColumnKernel,event); 7015 clEnv->library->clReleaseEvent(event); 7016 } 7017 } 7018 } 7019 7020 /* get result */ 7021 if (ALIGNED(filteredPixels,CLPixelPacket)) 7022 { 7023 length = image->columns * image->rows; 7024 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 7025 } 7026 else 7027 { 7028 length = image->columns * image->rows; 7029 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 7030 } 7031 if (clStatus != CL_SUCCESS) 7032 { 7033 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 7034 goto cleanup; 7035 } 7036 7037 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 7038 7039cleanup: 7040 OpenCLLogException(__FUNCTION__,__LINE__,exception); 7041 7042 image_view=DestroyCacheView(image_view); 7043 if (filteredImage_view != NULL) 7044 filteredImage_view=DestroyCacheView(filteredImage_view); 7045 7046 if (kernel != NULL) kernel=DestroyKernelInfo(kernel); 7047 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 7048 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 7049 if (tempImageBuffer!=NULL) clEnv->library->clReleaseMemObject(tempImageBuffer); 7050 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer); 7051 if (blurRowKernel!=NULL) RelinquishOpenCLKernel(clEnv, blurRowKernel); 7052 if (unsharpMaskBlurColumnKernel!=NULL) RelinquishOpenCLKernel(clEnv, unsharpMaskBlurColumnKernel); 7053 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 7054 if (outputReady == MagickFalse) 7055 { 7056 if (filteredImage != NULL) 7057 { 7058 DestroyImage(filteredImage); 7059 filteredImage = NULL; 7060 } 7061 } 7062 return filteredImage; 7063} 7064 7065static Image *ComputeUnsharpMaskImageSingle(const Image *image, 7066 const double radius,const double sigma,const double gain, 7067 const double threshold,int blurOnly, ExceptionInfo *exception) 7068{ 7069 CacheView 7070 *filteredImage_view, 7071 *image_view; 7072 7073 char 7074 geometry[MagickPathExtent]; 7075 7076 cl_command_queue 7077 queue; 7078 7079 cl_context 7080 context; 7081 7082 cl_int 7083 justBlur, 7084 clStatus; 7085 7086 cl_kernel 7087 unsharpMaskKernel; 7088 7089 cl_event 7090 event; 7091 7092 cl_mem 7093 filteredImageBuffer, 7094 imageBuffer, 7095 imageKernelBuffer; 7096 7097 cl_mem_flags 7098 mem_flags; 7099 7100 const void 7101 *inputPixels; 7102 7103 float 7104 fGain, 7105 fThreshold, 7106 *kernelBufferPtr; 7107 7108 Image 7109 *filteredImage; 7110 7111 KernelInfo 7112 *kernel; 7113 7114 MagickBooleanType 7115 outputReady; 7116 7117 MagickCLEnv 7118 clEnv; 7119 7120 MagickSizeType 7121 length; 7122 7123 void 7124 *filteredPixels, 7125 *hostPtr; 7126 7127 unsigned int 7128 i, 7129 imageColumns, 7130 imageRows, 7131 kernelWidth; 7132 7133 clEnv = NULL; 7134 filteredImage = NULL; 7135 filteredImage_view = NULL; 7136 kernel = NULL; 7137 context = NULL; 7138 imageBuffer = NULL; 7139 filteredImageBuffer = NULL; 7140 imageKernelBuffer = NULL; 7141 unsharpMaskKernel = NULL; 7142 queue = NULL; 7143 outputReady = MagickFalse; 7144 7145 clEnv = GetDefaultOpenCLEnv(); 7146 context = GetOpenCLContext(clEnv); 7147 queue = AcquireOpenCLCommandQueue(clEnv); 7148 7149 /* Create and initialize OpenCL buffers. */ 7150 { 7151 image_view=AcquireVirtualCacheView(image,exception); 7152 inputPixels=GetCacheViewVirtualPixels(image_view,0,0,image->columns,image->rows,exception); 7153 if (inputPixels == (const void *) NULL) 7154 { 7155 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning,"UnableToReadPixelCache.","`%s'",image->filename); 7156 goto cleanup; 7157 } 7158 7159 /* If the host pointer is aligned to the size of CLPixelPacket, 7160 then use the host buffer directly from the GPU; otherwise, 7161 create a buffer on the GPU and copy the data over */ 7162 if (ALIGNED(inputPixels,CLPixelPacket)) 7163 { 7164 mem_flags = CL_MEM_READ_ONLY|CL_MEM_USE_HOST_PTR; 7165 } 7166 else 7167 { 7168 mem_flags = CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR; 7169 } 7170 /* create a CL buffer from image pixel buffer */ 7171 length = image->columns * image->rows; 7172 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 7173 if (clStatus != CL_SUCCESS) 7174 { 7175 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 7176 goto cleanup; 7177 } 7178 } 7179 7180 /* create output */ 7181 { 7182 filteredImage = CloneImage(image,image->columns,image->rows,MagickTrue,exception); 7183 assert(filteredImage != NULL); 7184 if (SetImageStorageClass(filteredImage,DirectClass,exception) != MagickTrue) 7185 { 7186 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 7187 goto cleanup; 7188 } 7189 filteredImage_view=AcquireAuthenticCacheView(filteredImage,exception); 7190 filteredPixels=GetCacheViewAuthenticPixels(filteredImage_view,0,0,filteredImage->columns,filteredImage->rows,exception); 7191 if (filteredPixels == (void *) NULL) 7192 { 7193 (void) OpenCLThrowMagickException(exception,GetMagickModule(),CacheWarning, "UnableToReadPixelCache.","`%s'",filteredImage->filename); 7194 goto cleanup; 7195 } 7196 7197 if (ALIGNED(filteredPixels,CLPixelPacket)) 7198 { 7199 mem_flags = CL_MEM_WRITE_ONLY|CL_MEM_USE_HOST_PTR; 7200 hostPtr = filteredPixels; 7201 } 7202 else 7203 { 7204 mem_flags = CL_MEM_WRITE_ONLY; 7205 hostPtr = NULL; 7206 } 7207 7208 /* create a CL buffer from image pixel buffer */ 7209 length = image->columns * image->rows; 7210 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 7211 if (clStatus != CL_SUCCESS) 7212 { 7213 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 7214 goto cleanup; 7215 } 7216 } 7217 7218 /* create the blur kernel */ 7219 { 7220 (void) FormatLocaleString(geometry,MagickPathExtent,"blur:%.20gx%.20g;blur:%.20gx%.20g+90",radius,sigma,radius,sigma); 7221 kernel=AcquireKernelInfo(geometry,exception); 7222 if (kernel == (KernelInfo *) NULL) 7223 { 7224 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireKernelInfo failed.","."); 7225 goto cleanup; 7226 } 7227 7228 imageKernelBuffer = clEnv->library->clCreateBuffer(context, CL_MEM_READ_ONLY, kernel->width * sizeof(float), NULL, &clStatus); 7229 if (clStatus != CL_SUCCESS) 7230 { 7231 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.","."); 7232 goto cleanup; 7233 } 7234 7235 7236 kernelBufferPtr = (float*)clEnv->library->clEnqueueMapBuffer(queue, imageKernelBuffer, CL_TRUE, CL_MAP_WRITE, 0, kernel->width * sizeof(float), 0, NULL, NULL, &clStatus); 7237 if (clStatus != CL_SUCCESS) 7238 { 7239 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueMapBuffer failed.","."); 7240 goto cleanup; 7241 } 7242 for (i = 0; i < kernel->width; i++) 7243 { 7244 kernelBufferPtr[i] = (float) kernel->values[i]; 7245 } 7246 clStatus = clEnv->library->clEnqueueUnmapMemObject(queue, imageKernelBuffer, kernelBufferPtr, 0, NULL, NULL); 7247 if (clStatus != CL_SUCCESS) 7248 { 7249 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueUnmapMemObject failed.", "'%s'", "."); 7250 goto cleanup; 7251 } 7252 } 7253 7254 { 7255 /* get the opencl kernel */ 7256 { 7257 unsharpMaskKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "UnsharpMask"); 7258 if (unsharpMaskKernel == NULL) 7259 { 7260 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 7261 goto cleanup; 7262 }; 7263 } 7264 7265 { 7266 imageColumns = (unsigned int) image->columns; 7267 imageRows = (unsigned int) image->rows; 7268 kernelWidth = (unsigned int) kernel->width; 7269 fGain = (float) gain; 7270 fThreshold = (float) threshold; 7271 justBlur = blurOnly; 7272 7273 /* set the kernel arguments */ 7274 i = 0; 7275 clStatus=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,sizeof(cl_mem),(void *)&imageBuffer); 7276 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,sizeof(cl_mem),(void *)&filteredImageBuffer); 7277 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,sizeof(cl_mem),(void *)&imageKernelBuffer); 7278 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,sizeof(unsigned int),(void *)&kernelWidth); 7279 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,sizeof(unsigned int),(void *)&imageColumns); 7280 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,sizeof(unsigned int),(void *)&imageRows); 7281 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,sizeof(cl_float4)*(8 * (32 + kernel->width)),(void *) NULL); 7282 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,sizeof(float),(void *)&fGain); 7283 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,sizeof(float),(void *)&fThreshold); 7284 clStatus|=clEnv->library->clSetKernelArg(unsharpMaskKernel,i++,sizeof(cl_uint),(void *)&justBlur); 7285 if (clStatus != CL_SUCCESS) 7286 { 7287 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clSetKernelArg failed.", "'%s'", "."); 7288 goto cleanup; 7289 } 7290 } 7291 7292 /* launch the kernel */ 7293 { 7294 size_t gsize[2]; 7295 size_t wsize[2]; 7296 7297 gsize[0] = ((image->columns + 7) / 8) * 8; 7298 gsize[1] = ((image->rows + 31) / 32) * 32; 7299 wsize[0] = 8; 7300 wsize[1] = 32; 7301 7302 clStatus = clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, unsharpMaskKernel, 2, NULL, gsize, wsize, 0, NULL, &event); 7303 if (clStatus != CL_SUCCESS) 7304 { 7305 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 7306 goto cleanup; 7307 } 7308 clEnv->library->clFlush(queue); 7309 RecordProfileData(clEnv,UnsharpMaskKernel,event); 7310 clEnv->library->clReleaseEvent(event); 7311 } 7312 } 7313 7314 /* get result */ 7315 if (ALIGNED(filteredPixels,CLPixelPacket)) 7316 { 7317 length = image->columns * image->rows; 7318 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ|CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 7319 } 7320 else 7321 { 7322 length = image->columns * image->rows; 7323 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 7324 } 7325 if (clStatus != CL_SUCCESS) 7326 { 7327 (void) OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 7328 goto cleanup; 7329 } 7330 7331 outputReady=SyncCacheViewAuthenticPixels(filteredImage_view,exception); 7332 7333cleanup: 7334 OpenCLLogException(__FUNCTION__,__LINE__,exception); 7335 7336 image_view=DestroyCacheView(image_view); 7337 if (filteredImage_view != NULL) 7338 filteredImage_view=DestroyCacheView(filteredImage_view); 7339 7340 if (kernel != NULL) kernel=DestroyKernelInfo(kernel); 7341 if (imageBuffer!=NULL) clEnv->library->clReleaseMemObject(imageBuffer); 7342 if (filteredImageBuffer!=NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 7343 if (imageKernelBuffer!=NULL) clEnv->library->clReleaseMemObject(imageKernelBuffer); 7344 if (unsharpMaskKernel!=NULL) RelinquishOpenCLKernel(clEnv, unsharpMaskKernel); 7345 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 7346 if (outputReady == MagickFalse) 7347 { 7348 if (filteredImage != NULL) 7349 { 7350 DestroyImage(filteredImage); 7351 filteredImage = NULL; 7352 } 7353 } 7354 return(filteredImage); 7355} 7356 7357MagickExport Image *AccelerateUnsharpMaskImage(const Image *image, 7358 const double radius,const double sigma,const double gain, 7359 const double threshold,ExceptionInfo *exception) 7360{ 7361 Image 7362 *filteredImage; 7363 7364 assert(image != NULL); 7365 assert(exception != (ExceptionInfo *) NULL); 7366 7367 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 7368 (checkOpenCLEnvironment(exception) == MagickFalse)) 7369 return NULL; 7370 7371 if (radius < 12.1) 7372 filteredImage=ComputeUnsharpMaskImageSingle(image,radius,sigma,gain, 7373 threshold,0,exception); 7374 else if (splitImage(image) && (image->rows / 2 > radius)) 7375 filteredImage=ComputeUnsharpMaskImageSection(image,radius,sigma,gain, 7376 threshold,exception); 7377 else 7378 filteredImage=ComputeUnsharpMaskImage(image,radius,sigma,gain,threshold, 7379 exception); 7380 return(filteredImage); 7381} 7382 7383static Image *ComputeWaveletDenoiseImage(const Image *image, 7384 const double threshold,ExceptionInfo *exception) 7385{ 7386 CacheView 7387 *filteredImage_view, 7388 *image_view; 7389 7390 cl_command_queue 7391 queue; 7392 7393 cl_context 7394 context; 7395 7396 cl_int 7397 clStatus; 7398 7399 cl_kernel 7400 denoiseKernel; 7401 7402 cl_event 7403 event; 7404 7405 cl_mem 7406 filteredImageBuffer, 7407 imageBuffer; 7408 7409 cl_mem_flags 7410 mem_flags; 7411 7412 const void 7413 *inputPixels; 7414 7415 Image 7416 *filteredImage; 7417 7418 MagickBooleanType 7419 outputReady; 7420 7421 MagickCLEnv 7422 clEnv; 7423 7424 MagickSizeType 7425 length; 7426 7427 void 7428 *filteredPixels, 7429 *hostPtr; 7430 7431 unsigned int 7432 i; 7433 7434 clEnv = NULL; 7435 filteredImage = NULL; 7436 filteredImage_view = NULL; 7437 context = NULL; 7438 imageBuffer = NULL; 7439 filteredImageBuffer = NULL; 7440 denoiseKernel = NULL; 7441 queue = NULL; 7442 outputReady = MagickFalse; 7443 7444 clEnv = GetDefaultOpenCLEnv(); 7445 context = GetOpenCLContext(clEnv); 7446 queue = AcquireOpenCLCommandQueue(clEnv); 7447 7448 /* Create and initialize OpenCL buffers. */ 7449 image_view = AcquireVirtualCacheView(image, exception); 7450 inputPixels = GetCacheViewVirtualPixels(image_view, 0, 0, image->columns, image->rows, exception); 7451 if (inputPixels == (const void *)NULL) 7452 { 7453 (void)OpenCLThrowMagickException(exception, GetMagickModule(), CacheWarning, "UnableToReadPixelCache.", "`%s'", image->filename); 7454 goto cleanup; 7455 } 7456 7457 /* If the host pointer is aligned to the size of CLPixelPacket, 7458 then use the host buffer directly from the GPU; otherwise, 7459 create a buffer on the GPU and copy the data over */ 7460 if (ALIGNED(inputPixels, CLPixelPacket)) 7461 { 7462 mem_flags = CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR; 7463 } 7464 else 7465 { 7466 mem_flags = CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR; 7467 } 7468 /* create a CL buffer from image pixel buffer */ 7469 length = image->columns * image->rows; 7470 imageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), (void*)inputPixels, &clStatus); 7471 if (clStatus != CL_SUCCESS) 7472 { 7473 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.", "."); 7474 goto cleanup; 7475 } 7476 7477 /* create output */ 7478 filteredImage = CloneImage(image, image->columns, image->rows, MagickTrue, exception); 7479 assert(filteredImage != NULL); 7480 if (SetImageStorageClass(filteredImage, DirectClass, exception) != MagickTrue) 7481 { 7482 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "CloneImage failed.", "'%s'", "."); 7483 goto cleanup; 7484 } 7485 filteredImage_view = AcquireAuthenticCacheView(filteredImage, exception); 7486 filteredPixels = GetCacheViewAuthenticPixels(filteredImage_view, 0, 0, filteredImage->columns, filteredImage->rows, exception); 7487 if (filteredPixels == (void *)NULL) 7488 { 7489 (void)OpenCLThrowMagickException(exception, GetMagickModule(), CacheWarning, "UnableToReadPixelCache.", "`%s'", filteredImage->filename); 7490 goto cleanup; 7491 } 7492 7493 if (ALIGNED(filteredPixels, CLPixelPacket)) 7494 { 7495 mem_flags = CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR; 7496 hostPtr = filteredPixels; 7497 } 7498 else 7499 { 7500 mem_flags = CL_MEM_WRITE_ONLY; 7501 hostPtr = NULL; 7502 } 7503 7504 /* create a CL buffer from image pixel buffer */ 7505 length = image->columns * image->rows; 7506 filteredImageBuffer = clEnv->library->clCreateBuffer(context, mem_flags, length * sizeof(CLPixelPacket), hostPtr, &clStatus); 7507 if (clStatus != CL_SUCCESS) 7508 { 7509 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clCreateBuffer failed.", "."); 7510 goto cleanup; 7511 } 7512 7513 /* get the opencl kernel */ 7514 denoiseKernel = AcquireOpenCLKernel(clEnv, MAGICK_OPENCL_ACCELERATE, "WaveletDenoise"); 7515 if (denoiseKernel == NULL) 7516 { 7517 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "AcquireOpenCLKernel failed.", "'%s'", "."); 7518 goto cleanup; 7519 }; 7520 7521 // Process image 7522 { 7523 const int PASSES = 5; 7524 cl_int width = (cl_int)image->columns; 7525 cl_int height = (cl_int)image->rows; 7526 cl_float thresh = threshold; 7527 7528 /* set the kernel arguments */ 7529 i = 0; 7530 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++, sizeof(cl_mem), (void *)&imageBuffer); 7531 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++, sizeof(cl_mem), (void *)&filteredImageBuffer); 7532 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++, sizeof(cl_float), (void *)&thresh); 7533 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++, sizeof(cl_int), (void *)&PASSES); 7534 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++, sizeof(cl_int), (void *)&width); 7535 clStatus |= clEnv->library->clSetKernelArg(denoiseKernel, i++, sizeof(cl_int), (void *)&height); 7536 7537 { 7538 const int TILESIZE = 64; 7539 const int PAD = 1 << (PASSES - 1); 7540 const int SIZE = TILESIZE - 2 * PAD; 7541 7542 size_t gsize[2]; 7543 size_t wsize[2]; 7544 7545 gsize[0] = ((width + (SIZE - 1)) / SIZE) * TILESIZE; 7546 gsize[1] = ((height + (SIZE - 1)) / SIZE) * 4; 7547 wsize[0] = TILESIZE; 7548 wsize[1] = 4; 7549 7550 clStatus = clEnv->library->clEnqueueNDRangeKernel(queue, denoiseKernel, 2, NULL, gsize, wsize, 0, NULL, &event); 7551 if (clStatus != CL_SUCCESS) 7552 { 7553 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "clEnv->library->clEnqueueNDRangeKernel failed.", "'%s'", "."); 7554 goto cleanup; 7555 } 7556 } 7557 RecordProfileData(clEnv, WaveletDenoiseKernel, event); 7558 clEnv->library->clReleaseEvent(event); 7559 } 7560 7561 7562 /* get result */ 7563 if (ALIGNED(filteredPixels, CLPixelPacket)) 7564 { 7565 length = image->columns * image->rows; 7566 clEnv->library->clEnqueueMapBuffer(queue, filteredImageBuffer, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, length * sizeof(CLPixelPacket), 0, NULL, NULL, &clStatus); 7567 } 7568 else 7569 { 7570 length = image->columns * image->rows; 7571 clStatus = clEnv->library->clEnqueueReadBuffer(queue, filteredImageBuffer, CL_TRUE, 0, length * sizeof(CLPixelPacket), filteredPixels, 0, NULL, NULL); 7572 } 7573 if (clStatus != CL_SUCCESS) 7574 { 7575 (void)OpenCLThrowMagickException(exception, GetMagickModule(), ResourceLimitWarning, "Reading output image from CL buffer failed.", "'%s'", "."); 7576 goto cleanup; 7577 } 7578 7579 outputReady = SyncCacheViewAuthenticPixels(filteredImage_view, exception); 7580 7581cleanup: 7582 OpenCLLogException(__FUNCTION__, __LINE__, exception); 7583 7584 image_view = DestroyCacheView(image_view); 7585 if (filteredImage_view != NULL) 7586 filteredImage_view = DestroyCacheView(filteredImage_view); 7587 7588 if (imageBuffer != NULL) clEnv->library->clReleaseMemObject(imageBuffer); 7589 if (filteredImageBuffer != NULL) clEnv->library->clReleaseMemObject(filteredImageBuffer); 7590 if (denoiseKernel != NULL) RelinquishOpenCLKernel(clEnv, denoiseKernel); 7591 if (queue != NULL) RelinquishOpenCLCommandQueue(clEnv, queue); 7592 if (outputReady == MagickFalse) 7593 { 7594 if (filteredImage != NULL) 7595 { 7596 DestroyImage(filteredImage); 7597 filteredImage = NULL; 7598 } 7599 } 7600 return(filteredImage); 7601} 7602 7603MagickExport Image *AccelerateWaveletDenoiseImage(const Image *image, 7604 const double threshold,ExceptionInfo *exception) 7605{ 7606 Image 7607 *filteredImage; 7608 7609 assert(image != NULL); 7610 assert(exception != (ExceptionInfo *)NULL); 7611 7612 if ((checkAccelerateConditionRGBA(image) == MagickFalse) || 7613 (checkOpenCLEnvironment(exception) == MagickFalse)) 7614 return (Image *) NULL; 7615 7616 filteredImage=ComputeWaveletDenoiseImage(image,threshold,exception); 7617 7618 return(filteredImage); 7619} 7620 7621#else /* MAGICKCORE_OPENCL_SUPPORT */ 7622 7623MagickExport Image *AccelerateAddNoiseImage(const Image *magick_unused(image), 7624 const NoiseType magick_unused(noise_type), 7625 ExceptionInfo *magick_unused(exception)) 7626{ 7627 magick_unreferenced(image); 7628 magick_unreferenced(noise_type); 7629 magick_unreferenced(exception); 7630 return((Image *) NULL); 7631} 7632 7633MagickExport Image *AccelerateBlurImage(const Image *magick_unused(image), 7634 const double magick_unused(radius),const double magick_unused(sigma), 7635 ExceptionInfo *magick_unused(exception)) 7636{ 7637 magick_unreferenced(image); 7638 magick_unreferenced(radius); 7639 magick_unreferenced(sigma); 7640 magick_unreferenced(exception); 7641 7642 return((Image *) NULL); 7643} 7644 7645MagickExport MagickBooleanType AccelerateCompositeImage( 7646 Image *magick_unused(image),const CompositeOperator magick_unused(compose), 7647 const Image *magick_unused(composite), 7648 const float magick_unused(destination_dissolve), 7649 const float magick_unused(source_dissolve), 7650 ExceptionInfo *magick_unused(exception)) 7651{ 7652 magick_unreferenced(image); 7653 magick_unreferenced(compose); 7654 magick_unreferenced(composite); 7655 magick_unreferenced(destination_dissolve); 7656 magick_unreferenced(source_dissolve); 7657 magick_unreferenced(exception); 7658 7659 return(MagickFalse); 7660} 7661 7662MagickExport MagickBooleanType AccelerateContrastImage( 7663 Image* magick_unused(image),const MagickBooleanType magick_unused(sharpen), 7664 ExceptionInfo* magick_unused(exception)) 7665{ 7666 magick_unreferenced(image); 7667 magick_unreferenced(sharpen); 7668 magick_unreferenced(exception); 7669 7670 return(MagickFalse); 7671} 7672 7673MagickExport MagickBooleanType AccelerateContrastStretchImage( 7674 Image *magick_unused(image),const double magick_unused(black_point), 7675 const double magick_unused(white_point), 7676 ExceptionInfo* magick_unused(exception)) 7677{ 7678 magick_unreferenced(image); 7679 magick_unreferenced(black_point); 7680 magick_unreferenced(white_point); 7681 magick_unreferenced(exception); 7682 7683 return(MagickFalse); 7684} 7685 7686MagickExport Image *AccelerateConvolveImage(const Image *magick_unused(image), 7687 const KernelInfo *magick_unused(kernel), 7688 ExceptionInfo *magick_unused(exception)) 7689{ 7690 magick_unreferenced(image); 7691 magick_unreferenced(kernel); 7692 magick_unreferenced(exception); 7693 7694 return((Image *) NULL); 7695} 7696 7697MagickExport MagickBooleanType AccelerateEqualizeImage( 7698 Image* magick_unused(image),ExceptionInfo* magick_unused(exception)) 7699{ 7700 magick_unreferenced(image); 7701 magick_unreferenced(exception); 7702 7703 return(MagickFalse); 7704} 7705 7706MagickExport Image *AccelerateDespeckleImage(const Image* magick_unused(image), 7707 ExceptionInfo* magick_unused(exception)) 7708{ 7709 magick_unreferenced(image); 7710 magick_unreferenced(exception); 7711 7712 return((Image *) NULL); 7713} 7714 7715MagickExport MagickBooleanType AccelerateFunctionImage( 7716 Image *magick_unused(image), 7717 const MagickFunction magick_unused(function), 7718 const size_t magick_unused(number_parameters), 7719 const double *magick_unused(parameters), 7720 ExceptionInfo *magick_unused(exception)) 7721{ 7722 magick_unreferenced(image); 7723 magick_unreferenced(function); 7724 magick_unreferenced(number_parameters); 7725 magick_unreferenced(parameters); 7726 magick_unreferenced(exception); 7727 7728 return(MagickFalse); 7729} 7730 7731MagickExport MagickBooleanType AccelerateGrayscaleImage( 7732 Image *magick_unused(image),const PixelIntensityMethod magick_unused(method), 7733 ExceptionInfo *magick_unused(exception)) 7734{ 7735 magick_unreferenced(image); 7736 magick_unreferenced(method); 7737 magick_unreferenced(exception); 7738 7739 return(MagickFalse); 7740} 7741 7742MagickExport Image *AccelerateLocalContrastImage( 7743 const Image *magick_unused(image),const double magick_unused(radius), 7744 const double magick_unused(strength),ExceptionInfo *magick_unused(exception)) 7745{ 7746 magick_unreferenced(image); 7747 magick_unreferenced(radius); 7748 magick_unreferenced(strength); 7749 magick_unreferenced(exception); 7750 7751 return((Image *) NULL); 7752} 7753 7754MagickExport MagickBooleanType AccelerateModulateImage( 7755 Image *magick_unused(image),const double magick_unused(percent_brightness), 7756 const double magick_unused(percent_hue), 7757 const double magick_unused(percent_saturation), 7758 ColorspaceType magick_unused(colorspace), 7759 ExceptionInfo *magick_unused(exception)) 7760{ 7761 magick_unreferenced(image); 7762 magick_unreferenced(percent_brightness); 7763 magick_unreferenced(percent_hue); 7764 magick_unreferenced(percent_saturation); 7765 magick_unreferenced(colorspace); 7766 magick_unreferenced(exception); 7767 7768 return(MagickFalse); 7769} 7770 7771MagickExport Image *AccelerateMotionBlurImage( 7772 const Image *magick_unused(image),const double *magick_unused(kernel), 7773 const size_t magick_unused(width),const OffsetInfo *magick_unused(offset), 7774 ExceptionInfo *magick_unused(exception)) 7775{ 7776 magick_unreferenced(image); 7777 magick_unreferenced(kernel); 7778 magick_unreferenced(width); 7779 magick_unreferenced(offset); 7780 magick_unreferenced(exception); 7781 7782 return((Image *) NULL); 7783} 7784 7785MagickExport MagickBooleanType AccelerateRandomImage( 7786 Image *magick_unused(image),ExceptionInfo *magick_unused(exception)) 7787{ 7788 magick_unreferenced(image); 7789 magick_unreferenced(exception); 7790 7791 return MagickFalse; 7792} 7793 7794MagickExport Image *AccelerateResizeImage(const Image *magick_unused(image), 7795 const size_t magick_unused(resizedColumns), 7796 const size_t magick_unused(resizedRows), 7797 const ResizeFilter *magick_unused(resizeFilter), 7798 ExceptionInfo *magick_unused(exception)) 7799{ 7800 magick_unreferenced(image); 7801 magick_unreferenced(resizedColumns); 7802 magick_unreferenced(resizedRows); 7803 magick_unreferenced(resizeFilter); 7804 magick_unreferenced(exception); 7805 7806 return((Image *) NULL); 7807} 7808 7809MagickExport Image *AccelerateRotationalBlurImage( 7810 const Image *magick_unused(image),const double magick_unused(angle), 7811 ExceptionInfo *magick_unused(exception)) 7812{ 7813 magick_unreferenced(image); 7814 magick_unreferenced(angle); 7815 magick_unreferenced(exception); 7816 7817 return((Image *) NULL); 7818} 7819 7820MagickExport Image *AccelerateUnsharpMaskImage( 7821 const Image *magick_unused(image),const double magick_unused(radius), 7822 const double magick_unused(sigma),const double magick_unused(gain), 7823 const double magick_unused(threshold), 7824 ExceptionInfo *magick_unused(exception)) 7825{ 7826 magick_unreferenced(image); 7827 magick_unreferenced(radius); 7828 magick_unreferenced(sigma); 7829 magick_unreferenced(gain); 7830 magick_unreferenced(threshold); 7831 magick_unreferenced(exception); 7832 7833 return((Image *) NULL); 7834} 7835 7836MagickExport Image *AccelerateWaveletDenoiseImage( 7837 const Image *magick_unused(image),const double magick_unused(threshold), 7838 ExceptionInfo *magick_unused(exception)) 7839{ 7840 magick_unreferenced(image); 7841 magick_unreferenced(threshold); 7842 magick_unreferenced(exception); 7843 7844 return((Image *)NULL); 7845} 7846#endif /* MAGICKCORE_OPENCL_SUPPORT */ 7847