I have this simple block of OpenCL
code, and I am getting unexpected results. The parameters image
is an array of floats and value
is a number from -255 to +255. Using java I use a JSlider to change the value
. The default value is 0 and the problem is when I move the slider more than 0 the image is black, if I move it less than 0 the image is white, which shouldn't happen. This should be checking each pixel individually and adjusting that pixel. It doesn't seem to be for some reason.
This block of code should change the threshold of an image. Which is any pixel that's Red Green and Blue is greater than the threshold should be white otherwise it should be black.
kernel void threshold(global float* image, const float value, const int max){
int index = get_global_id(0);
if (index >= max){
return;
}
int color = image[index];
int red = color >> 16 & 0x0FF;
int green = color >> 8 & 0x0FF;
int blue = color & 0x0FF;
if(red > value && green > value && blue > value){
red = 255;
green = 255;
blue = 255;
}else{
red = 0;
green = 0;
blue = 0;
}
int rgba = 255;
rgba = (rgba << 8) + red;
rgba = (rgba << 8) + green;
rgba = (rgba << 8) + blue;
image[index] = rgba;
}
If I replace the if/else
statement in the middle with this:
red += value;
if(red > 255){red = 255;}
else if(red < 0){red = 0;}
green += value;
if(green > 255){green = 255;}
else if(green < 0){green = 0;}
blue += value;
if(blue > 255){blue = 255;}
else if(blue < 0){blue = 0;}
I get the result I am looking for, for that operation, which this is to adjust the brightness of an image.
I'm I using OpenCL
wrong? From what I understand, is kernel
will be called until the return is hit. I am using JOCL in java to do this, here is the code I am using to call it:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package pocketshop.graphics;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opencl.CLBuffer;
import com.jogamp.opencl.CLCommandQueue;
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 pocketshop.Canvas;
import pocketshop.dialogs.BrightnessContrastDialog;
/**
*
* @author Ryan
*/
public class CL {
protected static CLBuffer<FloatBuffer> buffer;
protected static float[] pixels;
public static CLBuffer<FloatBuffer> getBuffer() {
return buffer;
}
public static float[] getPixels() {
return pixels;
}
public static void start(String script, float val) {
CLPlatform platform = CLPlatform.getDefault(/*type(CPU)*/);
CLContext context = CLContext.create(platform.getMaxFlopsDevice());
try {
CLProgram program = context.createProgram(getStreamFor("../scripts/" + script + ".cl"));
program.build(CLProgram.CompilerOptions.FAST_RELAXED_MATH);
assert program.isExecutable();
BufferedImage image = Canvas.image;
assert image.getColorModel().getNumComponents() == 3;
pixels = image.getRaster().getPixels(0, 0, image.getWidth(), image.getHeight(), (float[]) null);
FloatBuffer fb = Buffers.newDirectFloatBuffer(pixels);
// allocate a OpenCL buffer using the direct fb as working copy
buffer = context.createBuffer(fb, CLBuffer.Mem.READ_WRITE);
// creade a command queue with benchmarking flag set
CLCommandQueue queue = context.getDevices()[0].createCommandQueue(CLCommandQueue.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(script.toLowerCase());
//adjustment(val, queue, kernel, buffer, localWorkSize, globalWorkSize);
kernel.putArg(buffer).putArg((float) val).putArg(buffer.getNIOSize()).rewind();
queue.putWriteBuffer(buffer, false);
queue.put1DRangeKernel(kernel, 0, globalWorkSize, localWorkSize);
queue.putReadBuffer(buffer, true);
} catch (IOException e) {
}
context.release();
}
private static InputStream getStreamFor(String filename) {
return BrightnessContrastDialog.class.getResourceAsStream(filename);
}
private static int roundUp(int groupSize, int globalSize) {
int r = globalSize % groupSize;
if (r == 0) {
return globalSize;
} else {
return globalSize + groupSize - r;
}
}
}
I found out after many trial and error tests, that int color = image[index];
is actually a Red Green or Blue color not an int of the 3.
so,
image[0] = Red;
image[1] = Green;
image[2] = Blue;
image[3] = Red;
image[4] = Green;
image[5] = Blue;
etc