Newsflash

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.
 

Polls

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.glReadBuffer(GL11.GL_BACK);
  GL11.glReadPixels(0, 0, width, height, GL12.GL_BGR, GL11.GL_UNSIGNED_BYTE, bb);
  Texture2D t = new Texture2D(TextureFormat.BGR, width, height);
  t.setData(bb);
  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
        os.write(header);
        os.getChannel().write(bb);
    }
    
    public static void write(File file, Texture2D t) throws IOException {
        FileOutputStream fos = new FileOutputStream(file);
        try {
            write(fos, t);
        } finally {
            fos.close();
        }
    }
 
    public void run() {
        try {
            write(file, t);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

So I hope this snippet is useful for you.

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