Is it possible to take screenshots when using LWJGL?
Thanks in advance, Adam.
Is it possible to take screenshots when using LWJGL?
Thanks in advance, Adam.
got the same trouble on Linux … strange I was able to with gl4java
I thought about an screencapture-button in my program to save screenshots directly to disk…
But your suggestion will fit my needs for now, too
Thanks, Adam.
It’s really, really, easy to do a gl.readPixels() call as well and write out images directly, which is what I do. I save them as raw format and convert them in PSP to jpegs, but you can just as easily use some AWT/ImageIO to write them out directly in the format you want.
Cas
Speed doesn’t matter, so readPixels() would be good enough for now.
I found this in the JavaDocs:
void readPixels (int x, int y, int width, int height, int format, int type, int pixels)
But I don’t know how I could use this to get all pixel values, since return type is void.
The “int pixels” at the end is a ByteBuffer pointer where OpenGL will store the grabbed data.
Try something like the following:
// Buffer size is width * height * 4 colour components (for GL.RGBA) * size of int (4 bytes)
IntBuffer buff = ByteBuffer.allocateDirect(width * height * 4 * 4).order(ByteOrder.nativeOrder()).asIntBuffer() ;
int buffh = Sys.getDirectBufferAddress(buff) ;
gl.readPixels(0, 0, width, height, GL.RGBA, GL.INT, buffh)
I haven’t tested this, so there’s probably something wrong with it, but you get the idea!
I just downloaded the OpenGL specification, there it’s documented
a little bit clearer than in the JavaDocs of LWJGL.
Thanks for your help, I’m going to test it…
Adam.
Quick Hack ;D
BTW java.nio look like an island in middle of the API, it’s useless with other java function, no way for create a BufferedImage from a nio Buffer ?
// Buffer size is width * height * 4 colour components (for GL.RGBA) * size of int (4 bytes)
IntBuffer buff = ByteBuffer.allocateDirect(Display.getWidth() * Display.getHeight() * 4).order(ByteOrder.nativeOrder()).asIntBuffer();
int buffh = Sys.getDirectBufferAddress(buff) ;
_gl.readPixels(0, 0, Display.getWidth(), Display.getHeight(), GL.BGRA, GL.BYTE, buffh);
BufferedImage img = new BufferedImage(Display.getWidth(), Display.getHeight(), BufferedImage.TYPE_INT_RGB);
for( int ix=0;ix<Display.getWidth();ix++)
for( int iy=0;iy<Display.getHeight();iy++)
{
img.setRGB(ix,iy,buff.get((Display.getHeight()-iy-1)*Display.getWidth()+ix));
}
try
{
File out=new File("sc.png");
ImageIO.write(img,"png",out);
}
catch(Exception e)
{
e.printStackTrace();
}
look like I need to add a gamma correction …
Alternatively you can use temporary int array as a middle layer between java.nio and java.awt… IntBuffer.get(int[] dst) and BufferedImage.setRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize) methods…
No that I implemented a simple skybox it was worth it to add
a screen capture method - thanks for all you help!
It works just fine, but the pictures don’t have the right
contrast… how can I solve this (without a paint program)?
Adam.
Use
gl.readPixels(0, 0, Display.getWidth(), Display.getHeight(), GL.BGRA, GL.UNSIGNED_BYTE, buffh);
instead and the colors will be fine. When using GL.BYTE it does a strange / 2 when grabbing the colors from the buffer and converting them to GL.BYTE. I don’t know why. You can check out the exact conversions of every format in the OpenGL specification. For GL.UNSIGNED_BYTE it just grabs the exact values.
Spasi
Grabbing the pixels to the buffer, converting the buffer to an array and creating a BufferedImage from it, sure is fast enough for a fullscreen capture, but saving this image as a .png (my favorite) takes much time. In my machine about 3-4 seconds. I would recommend using the new ImageIO formats released recently as an external API (you can find it at java.sun.com). I had some problems with it (it’s still RC), but it’s worth trying. It also supports some new kind of native stuff, accelerating IO (especially for PNGs).
That is if you want to provide easy capturing for your users. If you want it just for yourself, a raw format would be just fine, as princec suggests.
Spasi
I already use ImageIO and save the screenshots as
JPEG and also use GL.BGRA in the readPixels command.
But I used GL.BYTE instead of GL_UNSIGNED_BYTE.
It works fine now, thanks for your help…
Adam.
I’ve got mine to the point where it only take 1-1.2 seconds per screenshot on a 2000+ Athlon.
Whaaaaaat! My screenshots take 1-2 milliseconds!!
(But then I don’t save them as JPEGs )
Cas
I could dump the raw pixel buffer to disk but I wanted them to be in a format that was immediately viewable.
TGA?
Cas
JPEG and PNG. I would have to resample Targa files to make them suitable for a website.