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}