|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % AAA CCCC CCCC EEEEE L EEEEE RRRR AAA TTTTT EEEEE % 00007 % A A C C E L E R R A A T E % 00008 % AAAAA C C EEE L EEE RRRR AAAAA T EEE % 00009 % A A C C E L E R R A A T E % 00010 % A A CCCC CCCC EEEEE LLLLL EEEEE R R A A T EEEEE % 00011 % % 00012 % % 00013 % MagickCore Acceleration Methods % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % January 2010 % 00018 % % 00019 % % 00020 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.imagemagick.org/script/license.php % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % Morphology is the the application of various kernals, of any size and even 00037 % shape, to a image in various ways (typically binary, but not always). 00038 % 00039 % Convolution (weighted sum or average) is just one specific type of 00040 % accelerate. Just one that is very common for image bluring and sharpening 00041 % effects. Not only 2D Gaussian blurring, but also 2-pass 1D Blurring. 00042 % 00043 % This module provides not only a general accelerate function, and the ability 00044 % to apply more advanced or iterative morphologies, but also functions for the 00045 % generation of many different types of kernel arrays from user supplied 00046 % arguments. Prehaps even the generation of a kernel from a small image. 00047 */ 00048 00049 /* 00050 Include declarations. 00051 */ 00052 #include "MagickCore/studio.h" 00053 #include "MagickCore/accelerate.h" 00054 #include "MagickCore/artifact.h" 00055 #include "MagickCore/cache.h" 00056 #include "MagickCore/cache-private.h" 00057 #include "MagickCore/cache-view.h" 00058 #include "MagickCore/color-private.h" 00059 #include "MagickCore/enhance.h" 00060 #include "MagickCore/exception.h" 00061 #include "MagickCore/exception-private.h" 00062 #include "MagickCore/gem.h" 00063 #include "MagickCore/hashmap.h" 00064 #include "MagickCore/image.h" 00065 #include "MagickCore/image-private.h" 00066 #include "MagickCore/list.h" 00067 #include "MagickCore/memory_.h" 00068 #include "MagickCore/monitor-private.h" 00069 #include "MagickCore/accelerate.h" 00070 #include "MagickCore/option.h" 00071 #include "MagickCore/pixel-accessor.h" 00072 #include "MagickCore/prepress.h" 00073 #include "MagickCore/quantize.h" 00074 #include "MagickCore/registry.h" 00075 #include "MagickCore/semaphore.h" 00076 #include "MagickCore/splay-tree.h" 00077 #include "MagickCore/statistic.h" 00078 #include "MagickCore/string_.h" 00079 #include "MagickCore/string-private.h" 00080 #include "MagickCore/token.h" 00081 00082 /* 00083 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00084 % % 00085 % % 00086 % % 00087 % A c c e l e r a t e C o n v o l v e I m a g e % 00088 % % 00089 % % 00090 % % 00091 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00092 % 00093 % AccelerateConvolveImage() applies a custom convolution kernel to the image. 00094 % It is accelerated by taking advantage of speed-ups offered by executing in 00095 % concert across heterogeneous platforms consisting of CPUs, GPUs, and other 00096 % processors. 00097 % 00098 % The format of the AccelerateConvolveImage method is: 00099 % 00100 % Image *AccelerateConvolveImage(const Image *image, 00101 % const KernelInfo *kernel,Image *convolve_image, 00102 % ExceptionInfo *exception) 00103 % 00104 % A description of each parameter follows: 00105 % 00106 % o image: the image. 00107 % 00108 % o kernel: the convolution kernel. 00109 % 00110 % o convole_image: the convoleed image. 00111 % 00112 % o exception: return any errors or warnings in this structure. 00113 % 00114 */ 00115 00116 #if defined(MAGICKCORE_OPENCL_SUPPORT) 00117 00118 #if defined(MAGICKCORE_HDRI_SUPPORT) 00119 #define CLOptions "-DMAGICKCORE_HDRI_SUPPORT=1 -DCLQuantum=float " \ 00120 "-DCLPixelType=float4 -DQuantumRange=%g -DMagickEpsilon=%g" 00121 #define CLPixelInfo cl_float4 00122 #else 00123 #if (MAGICKCORE_QUANTUM_DEPTH == 8) 00124 #define CLOptions "-DCLQuantum=uchar -DCLPixelType=uchar4 " \ 00125 "-DQuantumRange=%g -DMagickEpsilon=%g" 00126 #define CLPixelInfo cl_uchar4 00127 #elif (MAGICKCORE_QUANTUM_DEPTH == 16) 00128 #define CLOptions "-DCLQuantum=ushort -DCLPixelType=ushort4 " \ 00129 "-DQuantumRange=%g -DMagickEpsilon=%g" 00130 #define CLPixelInfo cl_ushort4 00131 #elif (MAGICKCORE_QUANTUM_DEPTH == 32) 00132 #define CLOptions "-DCLQuantum=uint -DCLPixelType=uint4 " \ 00133 "-DQuantumRange=%g -DMagickEpsilon=%g" 00134 #define CLPixelInfo cl_uint4 00135 #elif (MAGICKCORE_QUANTUM_DEPTH == 64) 00136 #define CLOptions "-DCLQuantum=ussize_t -DCLPixelType=ussize_t4 " \ 00137 "-DQuantumRange=%g -DMagickEpsilon=%g" 00138 #define CLPixelInfo cl_ulong4 00139 #endif 00140 #endif 00141 00142 typedef struct _ConvolveInfo 00143 { 00144 cl_context 00145 context; 00146 00147 cl_device_id 00148 *devices; 00149 00150 cl_command_queue 00151 command_queue; 00152 00153 cl_kernel 00154 kernel; 00155 00156 cl_program 00157 program; 00158 00159 cl_mem 00160 pixels, 00161 convolve_pixels; 00162 00163 cl_ulong 00164 width, 00165 height; 00166 00167 cl_uint 00168 matte; 00169 00170 cl_mem 00171 filter; 00172 } ConvolveInfo; 00173 00174 static const char 00175 *ConvolveKernel = 00176 "static inline long ClampToCanvas(const long offset,const unsigned long range)\n" 00177 "{\n" 00178 " if (offset < 0L)\n" 00179 " return(0L);\n" 00180 " if (offset >= range)\n" 00181 " return((long) (range-1L));\n" 00182 " return(offset);\n" 00183 "}\n" 00184 "\n" 00185 "static inline CLQuantum ClampToQuantum(const float value)\n" 00186 "{\n" 00187 "#if defined(MAGICKCORE_HDRI_SUPPORT)\n" 00188 " return((CLQuantum) value);\n" 00189 "#else\n" 00190 " if (value < 0.0)\n" 00191 " return((CLQuantum) 0);\n" 00192 " if (value >= (float) QuantumRange)\n" 00193 " return((CLQuantum) QuantumRange);\n" 00194 " return((CLQuantum) (value+0.5));\n" 00195 "#endif\n" 00196 "}\n" 00197 "\n" 00198 "__kernel void Convolve(const __global CLPixelType *input,\n" 00199 " __constant float *filter,const unsigned long width,const unsigned long height,\n" 00200 " const unsigned int matte,__global CLPixelType *output)\n" 00201 "{\n" 00202 " const unsigned long columns = get_global_size(0);\n" 00203 " const unsigned long rows = get_global_size(1);\n" 00204 "\n" 00205 " const long x = get_global_id(0);\n" 00206 " const long y = get_global_id(1);\n" 00207 "\n" 00208 " const float scale = (1.0/QuantumRange);\n" 00209 " const long mid_width = (width-1)/2;\n" 00210 " const long mid_height = (height-1)/2;\n" 00211 " float4 sum = { 0.0, 0.0, 0.0, 0.0 };\n" 00212 " float gamma = 0.0;\n" 00213 " register unsigned long i = 0;\n" 00214 "\n" 00215 " int method = 0;\n" 00216 " if (matte != false)\n" 00217 " method=1;\n" 00218 " if ((x >= width) && (x < (columns-width-1)) &&\n" 00219 " (y >= height) && (y < (rows-height-1)))\n" 00220 " {\n" 00221 " method=2;\n" 00222 " if (matte != false)\n" 00223 " method=3;\n" 00224 " }\n" 00225 " switch (method)\n" 00226 " {\n" 00227 " case 0:\n" 00228 " {\n" 00229 " for (long v=(-mid_height); v <= mid_height; v++)\n" 00230 " {\n" 00231 " for (long u=(-mid_width); u <= mid_width; u++)\n" 00232 " {\n" 00233 " const long index=ClampToCanvas(y+v,rows)*columns+\n" 00234 " ClampToCanvas(x+u,columns);\n" 00235 " sum.x+=filter[i]*input[index].x;\n" 00236 " sum.y+=filter[i]*input[index].y;\n" 00237 " sum.z+=filter[i]*input[index].z;\n" 00238 " gamma+=filter[i];\n" 00239 " i++;\n" 00240 " }\n" 00241 " }\n" 00242 " break;\n" 00243 " }\n" 00244 " case 1:\n" 00245 " {\n" 00246 " for (long v=(-mid_height); v <= mid_height; v++)\n" 00247 " {\n" 00248 " for (long u=(-mid_width); u <= mid_width; u++)\n" 00249 " {\n" 00250 " const unsigned long index=ClampToCanvas(y+v,rows)*columns+\n" 00251 " ClampToCanvas(x+u,columns);\n" 00252 " const float alpha=scale*input[index].w;\n" 00253 " sum.x+=alpha*filter[i]*input[index].x;\n" 00254 " sum.y+=alpha*filter[i]*input[index].y;\n" 00255 " sum.z+=alpha*filter[i]*input[index].z;\n" 00256 " sum.w+=filter[i]*input[index].w;\n" 00257 " gamma+=alpha*filter[i];\n" 00258 " i++;\n" 00259 " }\n" 00260 " }\n" 00261 " break;\n" 00262 " }\n" 00263 " case 2:\n" 00264 " {\n" 00265 " for (long v=(-mid_height); v <= mid_height; v++)\n" 00266 " {\n" 00267 " for (long u=(-mid_width); u <= mid_width; u++)\n" 00268 " {\n" 00269 " const unsigned long index=(y+v)*columns+(x+u);\n" 00270 " sum.x+=filter[i]*input[index].x;\n" 00271 " sum.y+=filter[i]*input[index].y;\n" 00272 " sum.z+=filter[i]*input[index].z;\n" 00273 " gamma+=filter[i];\n" 00274 " i++;\n" 00275 " }\n" 00276 " }\n" 00277 " break;\n" 00278 " }\n" 00279 " case 3:\n" 00280 " {\n" 00281 " for (long v=(-mid_height); v <= mid_height; v++)\n" 00282 " {\n" 00283 " for (long u=(-mid_width); u <= mid_width; u++)\n" 00284 " {\n" 00285 " const unsigned long index=(y+v)*columns+(x+u);\n" 00286 " const float alpha=scale*input[index].w;\n" 00287 " sum.x+=alpha*filter[i]*input[index].x;\n" 00288 " sum.y+=alpha*filter[i]*input[index].y;\n" 00289 " sum.z+=alpha*filter[i]*input[index].z;\n" 00290 " sum.w+=filter[i]*input[index].w;\n" 00291 " gamma+=alpha*filter[i];\n" 00292 " i++;\n" 00293 " }\n" 00294 " }\n" 00295 " break;\n" 00296 " }\n" 00297 " }\n" 00298 " gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);\n" 00299 " const unsigned long index = y*columns+x;\n" 00300 " output[index].x=ClampToQuantum(gamma*sum.x);\n" 00301 " output[index].y=ClampToQuantum(gamma*sum.y);\n" 00302 " output[index].z=ClampToQuantum(gamma*sum.z);\n" 00303 " if (matte == false)\n" 00304 " output[index].w=input[index].w;\n" 00305 " else\n" 00306 " output[index].w=ClampToQuantum(sum.w);\n" 00307 "}\n"; 00308 00309 static void ConvolveNotify(const char *message,const void *data,size_t length, 00310 void *user_context) 00311 { 00312 ExceptionInfo 00313 *exception; 00314 00315 (void) data; 00316 (void) length; 00317 exception=(ExceptionInfo *) user_context; 00318 (void) ThrowMagickException(exception,GetMagickModule(),DelegateWarning, 00319 "DelegateFailed","`%s'",message); 00320 } 00321 00322 static MagickBooleanType BindConvolveParameters(ConvolveInfo *convolve_info, 00323 const Image *image,const void *pixels,float *filter,const size_t width, 00324 const size_t height,void *convolve_pixels) 00325 { 00326 cl_int 00327 status; 00328 00329 register cl_uint 00330 i; 00331 00332 size_t 00333 length; 00334 00335 /* 00336 Allocate OpenCL buffers. 00337 */ 00338 length=image->columns*image->rows; 00339 convolve_info->pixels=clCreateBuffer(convolve_info->context,(cl_mem_flags) 00340 (CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR),length*sizeof(CLPixelInfo), 00341 (void *) pixels,&status); 00342 if ((convolve_info->pixels == (cl_mem) NULL) || (status != CL_SUCCESS)) 00343 return(MagickFalse); 00344 length=width*height; 00345 convolve_info->filter=clCreateBuffer(convolve_info->context,(cl_mem_flags) 00346 (CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR),length*sizeof(cl_float),filter, 00347 &status); 00348 if ((convolve_info->filter == (cl_mem) NULL) || (status != CL_SUCCESS)) 00349 return(MagickFalse); 00350 length=image->columns*image->rows; 00351 convolve_info->convolve_pixels=clCreateBuffer(convolve_info->context, 00352 (cl_mem_flags) (CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR),length* 00353 sizeof(CLPixelInfo),convolve_pixels,&status); 00354 if ((convolve_info->convolve_pixels == (cl_mem) NULL) || 00355 (status != CL_SUCCESS)) 00356 return(MagickFalse); 00357 /* 00358 Bind OpenCL buffers. 00359 */ 00360 i=0; 00361 status=clSetKernelArg(convolve_info->kernel,i++,sizeof(cl_mem),(void *) 00362 &convolve_info->pixels); 00363 if (status != CL_SUCCESS) 00364 return(MagickFalse); 00365 status=clSetKernelArg(convolve_info->kernel,i++,sizeof(cl_mem),(void *) 00366 &convolve_info->filter); 00367 if (status != CL_SUCCESS) 00368 return(MagickFalse); 00369 convolve_info->width=(cl_ulong) width; 00370 status=clSetKernelArg(convolve_info->kernel,i++,sizeof(cl_ulong),(void *) 00371 &convolve_info->width); 00372 if (status != CL_SUCCESS) 00373 return(MagickFalse); 00374 convolve_info->height=(cl_ulong) height; 00375 status=clSetKernelArg(convolve_info->kernel,i++,sizeof(cl_ulong),(void *) 00376 &convolve_info->height); 00377 if (status != CL_SUCCESS) 00378 return(MagickFalse); 00379 convolve_info->matte=(cl_uint) image->matte; 00380 status=clSetKernelArg(convolve_info->kernel,i++,sizeof(cl_uint),(void *) 00381 &convolve_info->matte); 00382 if (status != CL_SUCCESS) 00383 return(MagickFalse); 00384 status=clSetKernelArg(convolve_info->kernel,i++,sizeof(cl_mem),(void *) 00385 &convolve_info->convolve_pixels); 00386 if (status != CL_SUCCESS) 00387 return(MagickFalse); 00388 status=clFinish(convolve_info->command_queue); 00389 if (status != CL_SUCCESS) 00390 return(MagickFalse); 00391 return(MagickTrue); 00392 } 00393 00394 static void DestroyConvolveBuffers(ConvolveInfo *convolve_info) 00395 { 00396 cl_int 00397 status; 00398 00399 status=0; 00400 if (convolve_info->convolve_pixels != (cl_mem) NULL) 00401 status=clReleaseMemObject(convolve_info->convolve_pixels); 00402 if (convolve_info->pixels != (cl_mem) NULL) 00403 status=clReleaseMemObject(convolve_info->pixels); 00404 if (convolve_info->filter != (cl_mem) NULL) 00405 status=clReleaseMemObject(convolve_info->filter); 00406 (void) status; 00407 } 00408 00409 static ConvolveInfo *DestroyConvolveInfo(ConvolveInfo *convolve_info) 00410 { 00411 cl_int 00412 status; 00413 00414 status=0; 00415 if (convolve_info->kernel != (cl_kernel) NULL) 00416 status=clReleaseKernel(convolve_info->kernel); 00417 if (convolve_info->program != (cl_program) NULL) 00418 status=clReleaseProgram(convolve_info->program); 00419 if (convolve_info->command_queue != (cl_command_queue) NULL) 00420 status=clReleaseCommandQueue(convolve_info->command_queue); 00421 if (convolve_info->context != (cl_context) NULL) 00422 status=clReleaseContext(convolve_info->context); 00423 (void) status; 00424 convolve_info=(ConvolveInfo *) RelinquishMagickMemory(convolve_info); 00425 return(convolve_info); 00426 } 00427 00428 static MagickBooleanType EnqueueConvolveKernel(ConvolveInfo *convolve_info, 00429 const Image *image,const void *pixels,float *filter,const size_t width, 00430 const size_t height,void *convolve_pixels) 00431 { 00432 cl_int 00433 status; 00434 00435 size_t 00436 global_work_size[2], 00437 length; 00438 00439 length=image->columns*image->rows; 00440 status=clEnqueueWriteBuffer(convolve_info->command_queue, 00441 convolve_info->pixels,CL_TRUE,0,length*sizeof(CLPixelInfo),pixels,0,NULL, 00442 NULL); 00443 length=width*height; 00444 status=clEnqueueWriteBuffer(convolve_info->command_queue, 00445 convolve_info->filter,CL_TRUE,0,length*sizeof(cl_float),filter,0,NULL, 00446 NULL); 00447 if (status != CL_SUCCESS) 00448 return(MagickFalse); 00449 global_work_size[0]=image->columns; 00450 global_work_size[1]=image->rows; 00451 status=clEnqueueNDRangeKernel(convolve_info->command_queue, 00452 convolve_info->kernel,2,NULL,global_work_size,NULL,0,NULL,NULL); 00453 if (status != CL_SUCCESS) 00454 return(MagickFalse); 00455 length=image->columns*image->rows; 00456 status=clEnqueueReadBuffer(convolve_info->command_queue, 00457 convolve_info->convolve_pixels,CL_TRUE,0,length*sizeof(CLPixelInfo), 00458 convolve_pixels,0,NULL,NULL); 00459 if (status != CL_SUCCESS) 00460 return(MagickFalse); 00461 status=clFinish(convolve_info->command_queue); 00462 if (status != CL_SUCCESS) 00463 return(MagickFalse); 00464 return(MagickTrue); 00465 } 00466 00467 static ConvolveInfo *GetConvolveInfo(const Image *image,const char *name, 00468 const char *source,ExceptionInfo *exception) 00469 { 00470 char 00471 options[MaxTextExtent]; 00472 00473 cl_context_properties 00474 context_properties[3]; 00475 00476 cl_int 00477 status; 00478 00479 cl_platform_id 00480 platforms[1]; 00481 00482 cl_uint 00483 number_platforms; 00484 00485 ConvolveInfo 00486 *convolve_info; 00487 00488 size_t 00489 length, 00490 lengths[] = { strlen(source) }; 00491 00492 /* 00493 Create OpenCL info. 00494 */ 00495 convolve_info=(ConvolveInfo *) AcquireMagickMemory(sizeof(*convolve_info)); 00496 if (convolve_info == (ConvolveInfo *) NULL) 00497 { 00498 (void) ThrowMagickException(exception,GetMagickModule(), 00499 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 00500 return((ConvolveInfo *) NULL); 00501 } 00502 (void) ResetMagickMemory(convolve_info,0,sizeof(*convolve_info)); 00503 /* 00504 Create OpenCL context. 00505 */ 00506 status=clGetPlatformIDs(0,(cl_platform_id *) NULL,&number_platforms); 00507 if ((status == CL_SUCCESS) && (number_platforms > 0)) 00508 status=clGetPlatformIDs(1,platforms,NULL); 00509 if (status != CL_SUCCESS) 00510 { 00511 (void) ThrowMagickException(exception,GetMagickModule(),DelegateWarning, 00512 "failed to create OpenCL context","`%s' (%d)",image->filename,status); 00513 convolve_info=DestroyConvolveInfo(convolve_info); 00514 return((ConvolveInfo *) NULL); 00515 } 00516 context_properties[0]=CL_CONTEXT_PLATFORM; 00517 context_properties[1]=(cl_context_properties) platforms[0]; 00518 context_properties[2]=0; 00519 convolve_info->context=clCreateContextFromType(context_properties, 00520 (cl_device_type) CL_DEVICE_TYPE_GPU,ConvolveNotify,exception,&status); 00521 if ((convolve_info->context == (cl_context) NULL) || (status != CL_SUCCESS)) 00522 convolve_info->context=clCreateContextFromType(context_properties, 00523 (cl_device_type) CL_DEVICE_TYPE_CPU,ConvolveNotify,exception,&status); 00524 if ((convolve_info->context == (cl_context) NULL) || (status != CL_SUCCESS)) 00525 convolve_info->context=clCreateContextFromType(context_properties, 00526 (cl_device_type) CL_DEVICE_TYPE_DEFAULT,ConvolveNotify,exception,&status); 00527 if ((convolve_info->context == (cl_context) NULL) || (status != CL_SUCCESS)) 00528 { 00529 (void) ThrowMagickException(exception,GetMagickModule(),DelegateWarning, 00530 "failed to create OpenCL context","`%s' (%d)",image->filename,status); 00531 convolve_info=DestroyConvolveInfo(convolve_info); 00532 return((ConvolveInfo *) NULL); 00533 } 00534 /* 00535 Detect OpenCL devices. 00536 */ 00537 status=clGetContextInfo(convolve_info->context,CL_CONTEXT_DEVICES,0,NULL, 00538 &length); 00539 if ((status != CL_SUCCESS) || (length == 0)) 00540 { 00541 convolve_info=DestroyConvolveInfo(convolve_info); 00542 return((ConvolveInfo *) NULL); 00543 } 00544 convolve_info->devices=(cl_device_id *) AcquireMagickMemory(length); 00545 if (convolve_info->devices == (cl_device_id *) NULL) 00546 { 00547 (void) ThrowMagickException(exception,GetMagickModule(), 00548 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 00549 convolve_info=DestroyConvolveInfo(convolve_info); 00550 return((ConvolveInfo *) NULL); 00551 } 00552 status=clGetContextInfo(convolve_info->context,CL_CONTEXT_DEVICES,length, 00553 convolve_info->devices,NULL); 00554 if (status != CL_SUCCESS) 00555 { 00556 convolve_info=DestroyConvolveInfo(convolve_info); 00557 return((ConvolveInfo *) NULL); 00558 } 00559 if (image->debug != MagickFalse) 00560 { 00561 char 00562 attribute[MaxTextExtent]; 00563 00564 size_t 00565 length; 00566 00567 clGetDeviceInfo(convolve_info->devices[0],CL_DEVICE_NAME, 00568 sizeof(attribute),attribute,&length); 00569 (void) LogMagickEvent(AccelerateEvent,GetMagickModule(),"Name: %s", 00570 attribute); 00571 clGetDeviceInfo(convolve_info->devices[0],CL_DEVICE_VENDOR, 00572 sizeof(attribute),attribute,&length); 00573 (void) LogMagickEvent(AccelerateEvent,GetMagickModule(),"Vendor: %s", 00574 attribute); 00575 clGetDeviceInfo(convolve_info->devices[0],CL_DEVICE_VERSION, 00576 sizeof(attribute),attribute,&length); 00577 (void) LogMagickEvent(AccelerateEvent,GetMagickModule(), 00578 "Driver Version: %s",attribute); 00579 clGetDeviceInfo(convolve_info->devices[0],CL_DEVICE_PROFILE, 00580 sizeof(attribute),attribute,&length); 00581 (void) LogMagickEvent(AccelerateEvent,GetMagickModule(),"Profile: %s", 00582 attribute); 00583 clGetDeviceInfo(convolve_info->devices[0],CL_DRIVER_VERSION, 00584 sizeof(attribute),attribute,&length); 00585 (void) LogMagickEvent(AccelerateEvent,GetMagickModule(),"Driver: %s", 00586 attribute); 00587 clGetDeviceInfo(convolve_info->devices[0],CL_DEVICE_EXTENSIONS, 00588 sizeof(attribute),attribute,&length); 00589 (void) LogMagickEvent(AccelerateEvent,GetMagickModule(),"Extensions: %s", 00590 attribute); 00591 } 00592 /* 00593 Create OpenCL command queue. 00594 */ 00595 convolve_info->command_queue=clCreateCommandQueue(convolve_info->context, 00596 convolve_info->devices[0],0,&status); 00597 if ((convolve_info->command_queue == (cl_command_queue) NULL) || 00598 (status != CL_SUCCESS)) 00599 { 00600 convolve_info=DestroyConvolveInfo(convolve_info); 00601 return((ConvolveInfo *) NULL); 00602 } 00603 /* 00604 Build OpenCL program. 00605 */ 00606 convolve_info->program=clCreateProgramWithSource(convolve_info->context,1, 00607 &source,lengths,&status); 00608 if ((convolve_info->program == (cl_program) NULL) || (status != CL_SUCCESS)) 00609 { 00610 convolve_info=DestroyConvolveInfo(convolve_info); 00611 return((ConvolveInfo *) NULL); 00612 } 00613 (void) FormatLocaleString(options,MaxTextExtent,CLOptions,(float) 00614 QuantumRange,MagickEpsilon); 00615 status=clBuildProgram(convolve_info->program,1,convolve_info->devices,options, 00616 NULL,NULL); 00617 if ((convolve_info->program == (cl_program) NULL) || (status != CL_SUCCESS)) 00618 { 00619 char 00620 *log; 00621 00622 status=clGetProgramBuildInfo(convolve_info->program, 00623 convolve_info->devices[0],CL_PROGRAM_BUILD_LOG,0,NULL,&length); 00624 log=(char *) AcquireMagickMemory(length); 00625 if (log == (char *) NULL) 00626 { 00627 convolve_info=DestroyConvolveInfo(convolve_info); 00628 return((ConvolveInfo *) NULL); 00629 } 00630 status=clGetProgramBuildInfo(convolve_info->program, 00631 convolve_info->devices[0],CL_PROGRAM_BUILD_LOG,length,log,&length); 00632 (void) ThrowMagickException(exception,GetMagickModule(),DelegateWarning, 00633 "failed to build OpenCL program","`%s' (%s)",image->filename,log); 00634 log=DestroyString(log); 00635 convolve_info=DestroyConvolveInfo(convolve_info); 00636 return((ConvolveInfo *) NULL); 00637 } 00638 /* 00639 Get a kernel object. 00640 */ 00641 convolve_info->kernel=clCreateKernel(convolve_info->program,name,&status); 00642 if ((convolve_info->kernel == (cl_kernel) NULL) || (status != CL_SUCCESS)) 00643 { 00644 convolve_info=DestroyConvolveInfo(convolve_info); 00645 return((ConvolveInfo *) NULL); 00646 } 00647 return(convolve_info); 00648 } 00649 00650 #endif 00651 00652 MagickExport MagickBooleanType AccelerateConvolveImage(const Image *image, 00653 const KernelInfo *kernel,Image *convolve_image,ExceptionInfo *exception) 00654 { 00655 assert(image != (Image *) NULL); 00656 assert(image->signature == MagickSignature); 00657 if (image->debug != MagickFalse) 00658 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 00659 assert(kernel != (KernelInfo *) NULL); 00660 assert(kernel->signature == MagickSignature); 00661 assert(convolve_image != (Image *) NULL); 00662 assert(convolve_image->signature == MagickSignature); 00663 assert(exception != (ExceptionInfo *) NULL); 00664 assert(exception->signature == MagickSignature); 00665 if ((image->storage_class != DirectClass) || 00666 (image->colorspace == CMYKColorspace)) 00667 return(MagickFalse); 00668 if ((GetImageVirtualPixelMethod(image) != UndefinedVirtualPixelMethod) && 00669 (GetImageVirtualPixelMethod(image) != EdgeVirtualPixelMethod)) 00670 return(MagickFalse); 00671 if (GetPixelChannels(image) != 4) 00672 return(MagickFalse); 00673 #if !defined(MAGICKCORE_OPENCL_SUPPORT) 00674 return(MagickFalse); 00675 #else 00676 { 00677 const void 00678 *pixels; 00679 00680 float 00681 *filter; 00682 00683 ConvolveInfo 00684 *convolve_info; 00685 00686 MagickBooleanType 00687 status; 00688 00689 MagickSizeType 00690 length; 00691 00692 register ssize_t 00693 i; 00694 00695 void 00696 *convolve_pixels; 00697 00698 convolve_info=GetConvolveInfo(image,"Convolve",ConvolveKernel,exception); 00699 if (convolve_info == (ConvolveInfo *) NULL) 00700 return(MagickFalse); 00701 pixels=AcquirePixelCachePixels(image,&length,exception); 00702 if (pixels == (const void *) NULL) 00703 { 00704 convolve_info=DestroyConvolveInfo(convolve_info); 00705 (void) ThrowMagickException(exception,GetMagickModule(),CacheError, 00706 "UnableToReadPixelCache","`%s'",image->filename); 00707 return(MagickFalse); 00708 } 00709 convolve_pixels=GetPixelCachePixels(convolve_image,&length,exception); 00710 if (convolve_pixels == (void *) NULL) 00711 { 00712 convolve_info=DestroyConvolveInfo(convolve_info); 00713 (void) ThrowMagickException(exception,GetMagickModule(),CacheError, 00714 "UnableToReadPixelCache","`%s'",image->filename); 00715 return(MagickFalse); 00716 } 00717 filter=(float *) AcquireQuantumMemory(kernel->width,kernel->height* 00718 sizeof(*filter)); 00719 if (filter == (float *) NULL) 00720 { 00721 DestroyConvolveBuffers(convolve_info); 00722 convolve_info=DestroyConvolveInfo(convolve_info); 00723 (void) ThrowMagickException(exception,GetMagickModule(), 00724 ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 00725 return(MagickFalse); 00726 } 00727 for (i=0; i < (ssize_t) (kernel->width*kernel->height); i++) 00728 filter[i]=(float) kernel->values[i]; 00729 status=BindConvolveParameters(convolve_info,image,pixels,filter, 00730 kernel->width,kernel->height,convolve_pixels); 00731 if (status == MagickFalse) 00732 { 00733 filter=(float *) RelinquishMagickMemory(filter); 00734 DestroyConvolveBuffers(convolve_info); 00735 convolve_info=DestroyConvolveInfo(convolve_info); 00736 return(MagickFalse); 00737 } 00738 status=EnqueueConvolveKernel(convolve_info,image,pixels,filter, 00739 kernel->width,kernel->height,convolve_pixels); 00740 filter=(float *) RelinquishMagickMemory(filter); 00741 if (status == MagickFalse) 00742 { 00743 DestroyConvolveBuffers(convolve_info); 00744 convolve_info=DestroyConvolveInfo(convolve_info); 00745 return(MagickFalse); 00746 } 00747 DestroyConvolveBuffers(convolve_info); 00748 convolve_info=DestroyConvolveInfo(convolve_info); 00749 return(MagickTrue); 00750 } 00751 #endif 00752 }