Taking Screen Shots

Jump to: navigation, search

Taking screen shots is actually very easy in LWJGL, all it takes is a few lines of code. So, without further ado, let's get cracking!

Getting the Screen's Pixel Data

First off, we need to access the pixel data of the Display. Without this, we don't know what to save!

int width = Display.getDisplayMode().getWidth();
int height= Display.getDisplayMode().getHeight();
int bpp = 4; // Assuming a 32-bit display with a byte each for red, green, blue, and alpha.
ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * bpp);
GL11.glReadPixels(0, 0, width, height, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer );

In order, this is what the above code does:

  1. Directs glReadPixels to read from the framebuffer currently being displayed.
  2. Creates a ByteBuffer to hold all pixel data from the screen.
  3. Causes OpenGL to copy the contents of the screen buffer into the created ByteBuffer.

Saving the Screen Image

Now that we have the screen data, we need to save it! To do this, we'll create a BufferedImage and save it with Java's ImageIO functions. While this is perhaps not the most efficient method, it is very flexible and allows you to have full image-saving functionality working with minimal effort.

Here's how we create and save an image from our ByteBuffer:

File file = ...; // The file to save to.
String format = ...; // Example: "PNG" or "JPG"
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for(int x = 0; x < width; x++) 
	for(int y = 0; y < height; y++)
		int i = (x + (width * y)) * bpp;
		int r = buffer.get(i) & 0xFF;
		int g = buffer.get(i + 1) & 0xFF;
		int b = buffer.get(i + 2) & 0xFF;
		image.setRGB(x, height - (y + 1), (0xFF << 24) | (r << 16) | (g << 8) | b);
try {
	ImageIO.write(image, format, file);
} catch (IOException e) { e.printStackTrace(); }

In order, this is what the above code does:

  1. Determines the file to save to and the format to encode in. (These are entirely up to the user and are not based on LWJGL.)
  2. Creates a BufferedImage with the correct dimensions of type RGB (we probably don't want alpha in the image we save).
  3. Copies the contents of the ByteBuffer into the pixel data of the BufferedImage.
  4. Saves the image.

Voila! You just saved a screen shot!

Tips and Tricks

There are a couple of additional things that can be done to improve this method:

  1. It is possible to take a snapshot of a section of the screen, instead of the whole thing. Look up glReadPixels for more information.
  2. Once the screen's pixel data is in the JVM (a.k.a. once we have finished with part A), we don't need to perform the given code in the main game loop. We can actually create a new Thread and do it in there to shave off a bit of the time taken up. Experiment!

Other methods

Other means of saving screenshots exist. Two such examples are [1] and [2].