我正在使用JavaCL,我想旋转图像并将图像保存回“out.png”。 不幸的是代码行:
write_imagef(output, (int2){coords.y, coords.x}, pixel );
(切换x和y坐标)似乎没有任何影响。我可以做任何我想做的事,但结果仍然是原始图像! 为什么输出不受影响?
CopyImagesExample.java
import static java.lang.Math.cos;
import static java.lang.Math.sin;
import static org.bridj.Pointer.allocateFloats;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteOrder;
import javax.imageio.ImageIO;
import org.bridj.Pointer;
import com.nativelibs4java.opencl.CLBuffer;
import com.nativelibs4java.opencl.CLContext;
import com.nativelibs4java.opencl.CLDevice;
import com.nativelibs4java.opencl.CLEvent;
import com.nativelibs4java.opencl.CLImage2D;
import com.nativelibs4java.opencl.CLKernel;
import com.nativelibs4java.opencl.CLMem.Usage;
import com.nativelibs4java.opencl.CLSampler;
import com.nativelibs4java.opencl.CLSampler.AddressingMode;
import com.nativelibs4java.opencl.CLSampler.FilterMode;
import com.nativelibs4java.opencl.CLProgram;
import com.nativelibs4java.opencl.CLQueue;
import com.nativelibs4java.opencl.JavaCL;
import com.nativelibs4java.util.IOUtils;
public class CopyImagesExample {
public static void main(String[] args) throws IOException {
CLContext context = JavaCL.createBestContext();
CLQueue queue = context.createDefaultQueue();
ByteOrder byteOrder = context.getByteOrder();
CLDevice[] devices = context.getDevices();
System.out.println("Devices count " + context.getDeviceCount());
System.out.println(devices[0].getMaxComputeUnits());
System.out.println(devices[0].getOpenCLVersion());
int n = 1024;
Pointer<Float> aPtr = allocateFloats(n).order(byteOrder);
Pointer<Float> bPtr = allocateFloats(n).order(byteOrder);
Pointer<Float> oPtr = allocateFloats(n).order(byteOrder);
for (int i = 0; i < n; i++) {
aPtr.set(i, (float) cos(i));
bPtr.set(i, (float) sin(i));
}
// Create OpenCL input buffers (using the native memory pointers aPtr
// and bPtr) :
BufferedImage img = ImageIO.read(new FileInputStream("images/lena256.png"));
CLImage2D inputImage = context.createImage2D(Usage.Input, img, false);
// Create an OpenCL output buffer :
CLImage2D outImage = context.createImage2D(Usage.Output, img, false);
CLSampler sampler = context.createSampler(false, AddressingMode.ClampToEdge, FilterMode.Nearest);
// Read the program sources and compile them :
String src = IOUtils.readText(CopyImagesExample.class
.getResource("CopyImage.cl"));
CLProgram program = context.createProgram(devices, src);
// Get and call the kernel :
CLKernel nnKernel = program.createKernel("rotate_image");
nnKernel.setArgs(inputImage, outImage, sampler);
CLEvent addEvt = nnKernel.enqueueNDRange(queue, new int[] { img.getWidth()*img.getHeight() });
BufferedImage outPtr = outImage.read(queue, addEvt); // blocks until
// add_floats
// finished
ImageIO.write(outPtr, "png", new File("out.png"));
}
}
CopyImage.cl
__kernel void rotate_image(
__read_only image2d_t input,
__write_only image2d_t output,
sampler_t sampler)
{
// Store each work-items unique row and column
int2 coords = (int2){get_global_id(0), get_global_id(1)};
float4 pixel = read_imagef(input, sampler, coords);
write_imagef(output, (int2){coords.y, coords.x}, pixel );
}
输入:
输出:
但是所需的输出是旋转图像(切换每个像素的x和y坐标)。
答案 0 :(得分:0)
快速修复:替换代码:
CLEvent addEvt = nnKernel.enqueueNDRange(queue, new int[] { img.getWidth()*img.getHeight() });
使用:
CLEvent addEvt = nnKernel.enqueueNDRange(queue, new int[] { img.getWidth(), img.getHeight() });
原因是,我在OpenCL代码中使用
get_global_id(0)
和
get_global_id(1)
所以我需要排队2D范围。