001package org.openimaj.image.processing.convolution; 002 003import java.io.IOException; 004import java.nio.ByteBuffer; 005import java.nio.FloatBuffer; 006 007import org.openimaj.image.Image; 008import org.openimaj.image.processing.CLImageProcessor; 009 010import com.nativelibs4java.opencl.CLBuffer; 011import com.nativelibs4java.opencl.CLContext; 012import com.nativelibs4java.opencl.CLMem.Usage; 013 014/** 015 * Simple 2D convolution. Note that this implementation is just a proof of 016 * concept and behaves in a really dumb/slow fashion. 017 * 018 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 019 * 020 * @param <I> 021 * Type of image 022 */ 023public class CLConvolve2D<I extends Image<?, I>> extends CLImageProcessor<I> { 024 private CLBuffer<Float> floatData; 025 026 /** 027 * Construct the convolution operator with the given kernel and OpenCL 028 * context 029 * 030 * @param context 031 * the OpenCL context 032 * @param kernel 033 * the convolution kernel 034 * @throws IOException 035 * if an error occurs 036 */ 037 public CLConvolve2D(CLContext context, float[][] kernel) throws IOException { 038 super(context, CLConvolve2D.class.getResource("Convolve.cl")); 039 040 final ByteBuffer bb = ByteBuffer.allocateDirect(kernel.length * kernel.length * 4); 041 bb.order(context.getByteOrder()); 042 final FloatBuffer fb = bb.asFloatBuffer(); 043 044 for (int y = 0; y < kernel.length; y++) 045 for (int x = 0; x < kernel.length; x++) 046 fb.put(kernel[y][x]); 047 048 // Note: the buffer needs to be an ivar as it seems to 049 // get garbage collected (the setArg line below internally 050 // just grabs the native pointer to the buffer; java has no 051 // way of knowing that we still need the data...) 052 floatData = context.createFloatBuffer(Usage.Input, fb, true); 053 054 this.kernel.setArg(2, floatData); 055 this.kernel.setArg(3, kernel.length); 056 } 057}