Java / OpenGL: получение изображения холста в виде BufferedImage - PullRequest
4 голосов
/ 04 ноября 2011

У меня есть код, который инициализирует OpenGL для рендеринга в java.awt.Canvas. Проблема в том, что я не могу понять, как мне получить буфер холста и превратить его в BufferedImage.

Я попытался переопределить getGraphics (), клонировать растр и заменить CanvasPeer на пользовательский.

Полагаю, OpenGL никак не использует графику Java, поэтому как мне получить буфер OpenGL и преобразовать его в BufferedImage?

Я использую код LWJGL для установки родителя:

Display.setParent(display_parent);
Display.create();

Ответы [ 2 ]

5 голосов
/ 04 ноября 2011

Вам необходимо скопировать данные из буфера OpenGL. Я использовал этот метод:

FloatBuffer grabScreen(GL gl) 
{       
    int w = SCREENWITDH;
    int h = SCREENHEIGHT;
    FloatBuffer bufor = FloatBuffer.allocate(w*h*4); // 4 = rgba

    gl.glReadBuffer(GL.GL_FRONT);
    gl.glReadPixels(0, 0, w, h, GL.GL_RGBA, GL.GL_FLOAT, bufor); //Copy the image to the array imageData

    return bufor;
}

Вам нужно использовать что-то подобное в соответствии с вашей оболочкой OpenGL. Это пример JOGL.

А вот для оболочки LWJGL:

private static synchronized byte[] grabScreen()
{
    int w = screenWidth;
    int h = screenHeight;
    ByteBuffer bufor = BufferUtils.createByteBuffer(w * h * 3);

    GL11.glReadPixels(0, 0, w, h, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, bufor); //Copy the image to the array imageData

    byte[] byteimg = new byte[w * h * 3];
    bufor.get(byteimg, 0, byteimg.length);
    return byteimg;
}

EDIT

Это также может быть полезно (оно не полностью мое, его тоже нужно настроить):

BufferedImage toImage(byte[] data, int w, int h)
{
    if (data.length == 0)
        return null;

    DataBuffer buffer = new DataBufferByte(data, w * h);

    int pixelStride = 3; //assuming r, g, b, skip, r, g, b, skip...
    int scanlineStride = 3 * w; //no extra padding   
    int[] bandOffsets = { 0, 1, 2 }; //r, g, b
    WritableRaster raster = Raster.createInterleavedRaster(buffer, w, h, scanlineStride, pixelStride, bandOffsets,
            null);

    ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
    boolean hasAlpha = false;
    boolean isAlphaPremultiplied = true;
    int transparency = Transparency.TRANSLUCENT;
    int transferType = DataBuffer.TYPE_BYTE;
    ColorModel colorModel = new ComponentColorModel(colorSpace, hasAlpha, isAlphaPremultiplied, transparency,
            transferType);

    BufferedImage image = new BufferedImage(colorModel, raster, isAlphaPremultiplied, null);

    AffineTransform flip;
    AffineTransformOp op;
    flip = AffineTransform.getScaleInstance(1, -1);
    flip.translate(0, -image.getHeight());
    op = new AffineTransformOp(flip, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
    image = op.filter(image, null);

    return image;
}
0 голосов
/ 04 ноября 2011

Я не думаю, что это возможно для вашей ситуации, и вот почему:

LWJGL не рисует непосредственно на холст (по крайней мере, в Windows).Холст используется только для получения дескриптора окна для предоставления в качестве родительского окна для OpenGL.Таким образом, холст никогда не обращается непосредственно к.Чтобы захватить содержимое, вам, вероятно, придется прибегнуть к снимку экрана.

...