Java-Gaming.org Java4K winners: [ by our judges | by the community ]         
Featured games (67)
games approved by the League of Dukes
Games in Showcase (∞)
games submitted by our members



News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  Print  
  a fast screenshot function  (Read 4152 times)
0 Members and 1 Guest are viewing this topic.
Offline cwei

JGO n00b
*

Posts: 25


Let the robots do.


« on: 2005-05-06 09:13:33 »

Hello together,

here is an example to make screenshots from OpenGL context very quickly. The file is written in uncompressed TARGA (*.tga) format.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
public static final int TARGA_HEADER_SIZE = 18;

void screenshot(GL gl, int width, int, height, File file) {
  try {
    RandomAccessFile out = new RandomAccessFile(file, "rw");
    FileChannel ch = out.getChannel();
    int fileLength = TARGA_HEADER_SIZE + width * height * 3;
    out.setLength(fileLength);
    MappedByteBuffer image = ch.map(FileChannel.MapMode.READ_WRITE, 0, fileLength);

    // write the TARGA header
  image.put(0, (byte) 0).put(1, (byte) 0);
   image.put(2, (byte) 2); // uncompressed type
  image.put(12, (byte) (width & 0xFF)); // width
  image.put(13, (byte) (width >> 8)); // width
  image.put(14, (byte) (height & 0xFF)); height
   image.put(15, (byte) (height >> 8)); height
   image.put(16, (byte) 24); // pixel size
             
   // go to image data position
  image.position(TARGA_HEADER_SIZE);
   // jogl needs a sliced buffer
  ByteBuffer bgr = image.slice();
   // read the BGR values into the image buffer
  gl.glReadPixels(0, 0, width, height, GL.GL_BGR,
                      GL.GL_UNSIGNED_BYTE, bgr);

   // close the file channel
  ch.close();
  } catch (Exception e) {
     e.printStackTrace();
  }
}


I think it is useful.

bye
Carsten
Offline Ken Russell

JGO Kernel
*****

Posts: 3446
Medals: 3


Java games rock!


« Reply #1 on: 2005-05-06 09:30:32 »

Thanks for the code. I've added it to JOGL Issue 131. We need to add a bunch of utility classes to JOGL to make it more useful.
Offline ozak

Full Member
**

Posts: 222


Java demon has no respect for bad code!!!


« Reply #2 on: 2005-05-08 02:53:14 »

Why not use ImageIO instead? That way you can save to all supported formats from the bytebuffer. Or perhaps even print it too Smiley

Want to do multiplayer? Why not try my free Socky socket server?
It's scriptable through JavaScript!
Check it out at http://www.furi.dk/socky
Games published by our own members! Go get 'em!
Offline cwei

JGO n00b
*

Posts: 25


Let the robots do.


« Reply #3 on: 2005-05-08 05:52:37 »

Quote
Why not use ImageIO instead? That way you can save to all supported formats from the bytebuffer. Or perhaps even print it too Smiley


The ImageIO class is ok, but much slower. I've used this function to make screenshots on the fly in Jake2. I've tested ImageIO too and the Quake2 game loop hangs a little bit on saving an image.

The trick in this example is to bypass the CPU for image writing. This function copies the graphics memory (AGP) to a memory mapped file.
I think only the DMA contoller has a lot to do :-)

An other fact is, that you don't need extra memory allocation like int[].
There is no extra runtime (dynamic) garbage. And the MappedByteBuffer will be collected by GC after closing the file channel.  

try it and you will see what I mean.

bye
Carsten
Offline ryanm
« League of Dukes »

JGO Strike Force
*****

Posts: 788
Medals: 4


Used to be bleb


« Reply #4 on: 2005-05-11 06:31:39 »

First of all, thanks for the amazing code snippet. Using ImageIO, i was getting pauses ~1 second for each snapshot, with this method there is no appreciable delay Cheesy

Unfortunately, there seems to be a problem with the resultant images. What should look something like

comes out like


I'm calling it with
1  
screenshot( canvas.getGL(), canvas.getWidth(), canvas.getHeight(), imageFile );

where canvas is my GLCanvas.

Where am i going wrong?

Offline keving

JGO n00b
*

Posts: 39


Java games rock!


« Reply #5 on: 2005-05-11 12:01:29 »

Hi,

To fix this, either make sure your image width will always be a multiple of 4, or add the line

   gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);

before your call to gl.glReadPixels()

Thanks for the tip on using file channels!  I have just finished implementing code to capture directly to an AVI file (with sound). Anyone interested?

Kevin
Offline ryanm
« League of Dukes »

JGO Strike Force
*****

Posts: 788
Medals: 4


Used to be bleb


« Reply #6 on: 2005-05-11 13:35:36 »

Awesome, that's got it. Grin
Offline cwei

JGO n00b
*

Posts: 25


Let the robots do.


« Reply #7 on: 2005-05-11 14:52:46 »

Thanks you for the test and for the hint with pixel alignment.
I had forgotten this issue.

Keving, I'm interested in your AVI tool.

bye
Carsten
Offline ryanm
« League of Dukes »

JGO Strike Force
*****

Posts: 788
Medals: 4


Used to be bleb


« Reply #8 on: 2005-05-11 16:46:46 »

I too am interested in encoding directly to a video file. Currently i'm using this screenshot code to capture a whole crapload of frames, which i then encode with other tools.
Skipping this step and encoding directly would be ideal.

Incidentally -as I understand it- avi is a container for various video and audio formats. What video format would be used?
Offline Vorax

JGO Ninja
***

Posts: 666
Medals: 1


System shutting down in 5..4..3...


« Reply #9 on: 2005-05-11 19:27:47 »

Me too please Smiley

Games published by our own members! Go get 'em!
Offline Louis

JGO n00b
*

Posts: 17


Dis-member


« Reply #10 on: 2005-05-18 06:56:24 »

I noticed you do not specify which color buffer the glreadpixels should capture the pix info from. On prompting of a screengrab I usually render the final pass of my app into an Auxilary Buffer and then dump the color information from the Aux buffer to file. That way your app doesn't not have to be showing on the screen for the screendump to be successful.
Offline jensall

JGO n00b
*

Posts: 11



« Reply #11 on: 2006-04-28 05:20:55 »

I suppose, the code resulted in the Screenshot Class of JSR-231.
How about adding something like the AVI tool, too?

I have just finished implementing code to capture directly to an AVI file (with sound). Anyone interested?
Could you send me the code for the AVI capturing, please?

Jens
Offline emzic

JGO Ninja
***

Posts: 506



« Reply #12 on: 2006-05-02 04:03:41 »

how do you get the GLCanvas outside one of the jogl functions (init,display,reshape) ?

www.embege.com - personal website
webstart blendinspect - OpenGL BlendingModes visualization.
Offline Ken Russell

JGO Kernel
*****

Posts: 3446
Medals: 3


Java games rock!


« Reply #13 on: 2006-05-02 12:17:33 »

You shouldn't really need to. The work you need to do to capture the screen contents should typically be called from within your GLEventListener.display() method.
Offline invictus

JGO n00b
*

Posts: 31



« Reply #14 on: 2006-05-03 07:20:32 »

I have just finished implementing code to capture directly to an AVI file (with sound). Anyone interested?

Kevin

I am Smiley
Pages: [1]
  Print  
 
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.16 | SMF © 2011, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.167 seconds with 21 queries.