diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com/jogamp/opencl/demos/gamma/CLSimpleGammaCorrection.java | 178 | ||||
-rw-r--r-- | src/com/jogamp/opencl/demos/gamma/Gamma.cl | 10 | ||||
-rw-r--r-- | src/com/jogamp/opencl/demos/gamma/lena.png | bin | 0 -> 476248 bytes |
3 files changed, 188 insertions, 0 deletions
diff --git a/src/com/jogamp/opencl/demos/gamma/CLSimpleGammaCorrection.java b/src/com/jogamp/opencl/demos/gamma/CLSimpleGammaCorrection.java new file mode 100644 index 0000000..1845cbc --- /dev/null +++ b/src/com/jogamp/opencl/demos/gamma/CLSimpleGammaCorrection.java @@ -0,0 +1,178 @@ +/* + * Copyright 2009 - 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +/* + * Created on Monday, December 13 2010 17:43 + */ + +package com.jogamp.opencl.demos.gamma; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opencl.CLBuffer; +import com.jogamp.opencl.CLCommandQueue; +import com.jogamp.opencl.CLCommandQueue.Mode; +import com.jogamp.opencl.CLContext; +import com.jogamp.opencl.CLKernel; +import com.jogamp.opencl.CLPlatform; +import com.jogamp.opencl.CLProgram; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.nio.FloatBuffer; +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; + +import static com.jogamp.opencl.CLProgram.*; + +/** + * Computes the classical gamma correction for a given image. + * http://en.wikipedia.org/wiki/Gamma_correction + * @author Michael Bien + */ +public class CLSimpleGammaCorrection { + + private static InputStream getStreamFor(String filename) { + return CLSimpleGammaCorrection.class.getResourceAsStream(filename); + } + + public static BufferedImage readImage(String filename) throws IOException { + return ImageIO.read(getStreamFor(filename)); + } + + private static BufferedImage createImage(int width, int height, CLBuffer<FloatBuffer> buffer) { + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + float[] pixels = new float[buffer.getBuffer().capacity()]; + buffer.getBuffer().get(pixels).rewind(); + image.getRaster().setPixels(0, 0, width, height, pixels); + return image; + } + + public static void main(String[] args) throws IOException { + + // find a CL implementation + CLPlatform platform = CLPlatform.getDefault(/*type(CPU)*/); + + CLContext context = CLContext.create(platform.getMaxFlopsDevice()); + + try{ + //load and compile program for the chosen device + CLProgram program = context.createProgram(getStreamFor("Gamma.cl")); + program.build(CompilerOptions.FAST_RELAXED_MATH); + assert program.isExecutable(); + + // load image + BufferedImage image = readImage("lena.png"); + assert image.getColorModel().getNumComponents() == 3; + + float[] pixels = image.getRaster().getPixels(0, 0, image.getWidth(), image.getHeight(), (float[])null); + + // copy to direct float buffer + FloatBuffer fb = Buffers.newDirectFloatBuffer(pixels); + + // allocate a OpenCL buffer using the direct fb as working copy + CLBuffer<FloatBuffer> buffer = context.createBuffer(fb, CLBuffer.Mem.READ_WRITE); + + // creade a command queue with benchmarking flag set + CLCommandQueue queue = context.getDevices()[0].createCommandQueue(Mode.PROFILING_MODE); + + int localWorkSize = queue.getDevice().getMaxWorkGroupSize(); // Local work size dimensions + int globalWorkSize = roundUp(localWorkSize, fb.capacity()); // rounded up to the nearest multiple of the localWorkSize + + // create kernel and set function parameters + CLKernel kernel = program.createCLKernel("gamma"); + + // original lenna + show(image, 0, 50, "reference"); + + // a few gamma corrected versions + float gamma = 0.5f; + gammaCorrection(gamma, queue, kernel, buffer, localWorkSize, globalWorkSize); + show(createImage(image.getWidth(), image.getHeight(), buffer), image.getWidth()/2, 50, "corrected with gama="+gamma); + + gamma = 1.5f; + gammaCorrection(gamma, queue, kernel, buffer, localWorkSize, globalWorkSize); + show(createImage(image.getWidth(), image.getHeight(), buffer), image.getWidth()/2*2, 50, "corrected with gama="+gamma); + + gamma = 2.0f; + gammaCorrection(gamma, queue, kernel, buffer, localWorkSize, globalWorkSize); + show(createImage(image.getWidth(), image.getHeight(), buffer), image.getWidth()/2*3, 50, "corrected with gama="+gamma); + + }finally{ + context.release(); + } + + } + + private static void gammaCorrection(float gamma, CLCommandQueue queue, CLKernel kernel, CLBuffer<FloatBuffer> buffer, int localWorkSize, int globalWorkSize) { + + float scaleFactor = (float) Math.pow(255, 1.0f-gamma); + + // setup kernel + kernel.putArg(buffer).putArg(gamma).putArg(scaleFactor).putArg(buffer.getNIOSize()).rewind(); + +// CLEventList list = new CLEventList(1); + + queue.putWriteBuffer(buffer, false); // upload image + queue.put1DRangeKernel(kernel, 0, globalWorkSize, localWorkSize/*, list*/); // execute program + queue.putReadBuffer(buffer, true); // read results back (blocking read) + +// CLEvent event = list.getEvent(0); +// System.out.println((event.getProfilingInfo(END) +// - event.getProfilingInfo(START))/1000000.0); +// +// long res = queue.getDevice().getProfilingTimerResolution(); +// System.out.println(res); + + } + + private static void show(final BufferedImage image, final int x, final int y, final String title) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JFrame frame = new JFrame("gamma correction example ["+title+"]"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.add(new JLabel(new ImageIcon(image))); + frame.pack(); + frame.setLocation(x, y); + frame.setVisible(true); + } + }); + } + + private static int roundUp(int groupSize, int globalSize) { + int r = globalSize % groupSize; + if (r == 0) { + return globalSize; + } else { + return globalSize + groupSize - r; + } + } + +} diff --git a/src/com/jogamp/opencl/demos/gamma/Gamma.cl b/src/com/jogamp/opencl/demos/gamma/Gamma.cl new file mode 100644 index 0000000..69b0618 --- /dev/null +++ b/src/com/jogamp/opencl/demos/gamma/Gamma.cl @@ -0,0 +1,10 @@ + /** + * gamma correction kernel + */ + kernel void gamma(global float* image, const float gamma, const float scale, const int max) { + int index = get_global_id(0); + if (index >= max) { + return; + } + image[index] = pow(image[index], gamma) * scale; + }
\ No newline at end of file diff --git a/src/com/jogamp/opencl/demos/gamma/lena.png b/src/com/jogamp/opencl/demos/gamma/lena.png Binary files differnew file mode 100644 index 0000000..508a066 --- /dev/null +++ b/src/com/jogamp/opencl/demos/gamma/lena.png |