How can I get a BufferedImage from an OpenGL window?

I am coding a Java LWJGL game and everything is going fine except when I try to figure out a way to create a BufferedImage of the current area of ​​the game. I searched on the Internet, looked through all opengl functions, and I have nobody ... Does anyone have any ideas? Here is all that I have so far, but this only makes an empty .png:

if(Input.getKeyDown(Input.KEY_F2)) {
    try {
        String fileName = "screenshot-" + Util.getSystemTime(false);
        File imageToSave = new File(MainComponent.screenshotsFolder, fileName + ".png");
        int duplicate = 0;
        while(true) {
            duplicate++;
            if(imageToSave.exists() == false) {
                imageToSave.createNewFile();
                break;
            }
            imageToSave = new File(MainComponent.screenshotsFolder, fileName + "_" + duplicate + ".png");
        }
        imageToSave.createNewFile();

        // Create a buffered image:
        BufferedImage image = new BufferedImage(MainComponent.WIDTH, MainComponent.HEIGHT, BufferedImage.TYPE_INT_ARGB);
        //Wrtie the new buffered image to file:
        ImageIO.write(image, "png", imageToSave);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
+3
source share
1 answer

You never write something in your BufferedImage.

Read buffer

You can use glReadPixels to access the selected buffer. (I assume WIDTH and HEIGHT as your OpenGLContext sizes.)

FloatBuffer imageData = BufferUtils.createFloatBuffer(WIDTH * HEIGHT * 3); 
GL11.glReadPixels(0, 0, WIDTH, HEIGHT, GL11.GL_RGB, GL11.GL_FLOAT, imageData);
imageData.rewind();

Use any parameters that are best suited to your needs, I just accidentally chose floats.

, , . BufferedImage(). SetRGB() ( , , , .)

// create image
BufferedImage image = new BufferedImage(
     WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB
);

// set content
image.setRGB(0, 0, WIDTH, HEIGHT, rgbArray, 0, WIDTH);

// save it
File outputfile = new File("Screenshot.png");
try {
    ImageIO.write(image, "png", outputfile);
} catch (IOException e) {
    e.printStackTrace();
}

rgbArray. ,

  • OpenGL ( , GL11.GL_RGB), BufferedImage .
  • OpenGL , BufferedImage - .

, , , .
: , (1.0f, 0.0f, 0.0f) FloatBuffer.

, CSS, . #ff0000 CSS Java, , 0xff0000.

RGB 0 255 ( 00 ff ), 0 1 . , 255 :

int r = (int)(fR * 255);

, :

rgb = 255 0 0 = ff 00 00

, . (0-f) 4 , 8 ( ) 16 . .

int rgb = (r << 16) + (g << 8) + b;

BottomUp TopDown

, → , .

1D-, ( ),

int index = offset + (y - yOffset) * stride + (x - xOffset);

, ,

int index = y * stride + x;

, stride - WIDTH, x (, , ).

, , , OpenGL 0, BufferedImage 0. , y:

int index = ((HEIGHT - 1) - y) * WIDTH + x;

int [] -

, rgb, , , . int [] - .

int[] rgbArray = new int[WIDTH * HEIGHT];
for(int y = 0; y < HEIGHT; ++y) {
    for(int x = 0; x < WIDTH; ++x) {
        int r = (int)(imageData.get() * 255) << 16;
        int g = (int)(imageData.get() * 255) << 8;
        int b = (int)(imageData.get() * 255);
        int i = ((HEIGHT - 1) - y) * WIDTH + x;
        rgbArray[i] = r + g + b;
    }
}

.

  • . , WIDTH * HEIGHT, WIDTH * HEIGHT * 3 .
  • OpenGL , (x) 2D- (, , , ).
  • imageData imageData.get(), , , , , . flip() rewind() get() !

, saveScreenshot().

private void saveScreenshot() {
    // read current buffer
    FloatBuffer imageData = BufferUtils.createFloatBuffer(WIDTH * HEIGHT * 3); 
    GL11.glReadPixels(
        0, 0, WIDTH, HEIGHT, GL11.GL_RGB, GL11.GL_FLOAT, imageData
    );
    imageData.rewind();

    // fill rgbArray for BufferedImage
    int[] rgbArray = new int[WIDTH * HEIGHT];
    for(int y = 0; y < HEIGHT; ++y) {
        for(int x = 0; x < WIDTH; ++x) {
            int r = (int)(imageData.get() * 255) << 16;
            int g = (int)(imageData.get() * 255) << 8;
            int b = (int)(imageData.get() * 255);
            int i = ((HEIGHT - 1) - y) * WIDTH + x;
            rgbArray[i] = r + g + b;
        }
    }

    // create and save image
    BufferedImage image = new BufferedImage(
         WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB
    );
    image.setRGB(0, 0, WIDTH, HEIGHT, rgbArray, 0, WIDTH);
    File outputfile = getNextScreenFile();
    try {
        ImageIO.write(image, "png", outputfile);
    } catch (IOException e) {
        e.printStackTrace();
        System.err.println("Can not save screenshot!");
    }
}

private File getNextScreenFile() {
    // create image name
    String fileName = "screenshot_" + getSystemTime(false);
    File imageToSave = new File(fileName + ".png");

    // check for duplicates
    int duplicate = 0;
    while(imageToSave.exists()) {
        imageToSave = new File(fileName + "_" + ++duplicate + ".png");
    }

    return imageToSave;
}

// format the time
public static String getSystemTime(boolean getTimeOnly) {
    SimpleDateFormat dateFormat = new SimpleDateFormat(
      getTimeOnly?"HH-mm-ss":"yyyy-MM-dd'T'HH-mm-ss"
    );
    return dateFormat.format(new Date());
}

.

+4

All Articles