JavaCL - 翻转输入图像

时间:2014-11-30 18:10:13

标签: java opencl gpu

我正在使用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 );    
}

输入:

Lena 256x256

输出:

Lena 256x256

但是所需的输出是旋转图像(切换每个像素的x和y坐标)。

1 个答案:

答案 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范围。