A good friend has spent his lunch time to create a new page header for my new site. You can already see it - I hope you like it.


How do you like JDK6 ?
Home arrow Java Code arrow OpenGL related arrow Creating screenshots
Creating screenshots PDF Print
Written by Matthias Mann   
Getting the content of the OpenGL backbuffer is simple - writing it to a file is also simple - but why does it always take so long ? This snippet will show you a way how to save the screenshot in a background thread with only a few lines of code. It uses the java.util.concurrent package.

We start with the easy part - getting the back buffer from OpenGL: 

public Texture2D takeScreenShot() {
  int width = getWidth();
  int height = getHeight();
  ByteBuffer bb = ByteBuffer.allocateDirect(width*height*3);
  GL11.glReadPixels(0, 0, width, height, GL12.GL_BGR, GL11.GL_UNSIGNED_BYTE, bb);
  Texture2D t = new Texture2D(TextureFormat.BGR, width, height);
  return t;

Now we need to get an ExecutorService - this class is used to execute the file writing in a seperate background thread. Be sure to only create one ExecutorService. I put this into the a screenshot action class.

if(execService == null) {
  execService = Executors.newSingleThreadExecutor();

This class has a submit(Runnable) method that allows us to queue our TGAWriter class.

execService.submit(new TGAWriter(file, t));

The TGAWriter class implements the Runnable interface and performs the write in it's run() method. 

public class TGAWriter implements Runnable {
    final File file;
    final Texture2D t;
    public TGAWriter(File file, Texture2D t) {
        this.file = file;
        this.t = t;
    public static void write(FileOutputStream os, Texture2D t) throws IOException {
        if(t.getFormat() != TextureFormat.BGR) {
            throw new UnsupportedOperationException("Not yet implemented");
        // duplicate the ByteBuffer to preserve position in case of concurent access
        ByteBuffer bb = t.getData()[0].duplicate();
        byte[] header = new byte[18];
        header[2] = 2;  // TGA file version
        header[12] = (byte)(t.getWidth()     ); // 16 bit width, little endian
        header[13] = (byte)(t.getWidth() >> 8);
        header[14] = (byte)(t.getHeight()     ); // 16 bit heigth, little endian
        header[15] = (byte)(t.getHeight() >> 8);
        header[16] = 24;  // 24 bit color bit depth, little endian
    public static void write(File file, Texture2D t) throws IOException {
        FileOutputStream fos = new FileOutputStream(file);
        try {
            write(fos, t);
        } finally {
    public void run() {
        try {
            write(file, t);
        } catch (IOException ex) {

So I hope this snippet is useful for you.

Add NewSearch
Only registered users can write comments!
Last Updated ( Sunday, 29 April 2007 )
< Prev
2016 Matthias Mann,
Joomla! is Free Software released under the GNU/GPL License.