NOTE: This code was written to be applied in an LWJGL game and as a result, offers very "specific" functionality. Nonetheless I believe it may have other uses as well. I just hope it's going to help some of you...

Some time ago I implemented a screenshot capture method. I used ImageIO to do the screenshot writting. Of course it wasn't good enough for my needs, as it added both memory overhead (more classes loaded, obligatory use of BufferedImage , etc.) and a lot of CPU overhead (in my Athlon 700MHz it took 1.5-2 seconds per capture). It did it's job, but I had to use another method to go at least under 1 sec / capture.

I wanted to have a fast solution (1-3 captures per second), and export a cross-platform loss-less image format. From what ImageIO offers (NOTE: I used the new ImageIO extension, that adds more formats), the only formats that satisfy the cross-platform / loss-less part are .PNG and .TIFF (maybe .BMP too? I have never touched a Mac...). I tried both, using ImageIO and although the new extension adds some native code for read/write acceleration, the results were unsatisfactory when it came to speed. I even tried some other formats, with no luck

Finally I decided to implement my own writer. I chose .TIFF, as it is the "most" cross-platform of all the others, it supports uncompressed data (no need for time consuming compression algos), and is easy to write .

So, here it is, for you to use and enjoy! Overall, I got a ten-fold(!) speed increase, grabbing ~5 screenshots / second. It's not a complete .TIFF writer, you can just write 3 bytes/pixel RGB images. If you want other types, feel free to extend it's functionality .

Memory.getByteDataBuffer() is just a method that grabs a ByteBuffer from another huge ByteBuffer. Saves a lot of overhead ( Cas, thanks for your precious tips ;-). Always helpful. ). Memory.releaseDataBuffer() releases the allocated memory. I strongly suggest you go implement sth like this (for those who haven't yet). Otherwise, all you have to do is provide a direct ByteBuffer to put the pixel data from the Frame Buffer.

After grabbing the pixels, the image rows get inverted (0,0 coordinate bottom-left ? What were they thinking?? Just kidding, I've gotten used to it...) and then we give the data to the TIFFWriter.

NOTE: I've used Display.WIDTH and Display.HEIGHT. This is the screen resolution. Modify according to your design.

/** This ByteBuffer will hold the TIFF header, the IFD and some of the other metadata (>4 bytes values) */privatefinalstaticByteBuffermetadata = ByteBuffer.allocate(HEADER_SIZE + IFD_SIZE + LONG_VARIABLES_SIZE).order(ByteOrder.nativeOrder());

/** A Calendar instance that gets update on every capture */privatefinalstaticCalendarcalendar = Calendar.getInstance();

/** A buffer to hold the formatted current date & time */privatefinalstaticbyte[] dateTime = newbyte[20];

This code writes the .TIFF image according to the specification. It puts 3 more entries to the image meta-data, although not necessary at all, just for fun. These are SOFTWARE, which is the name of the program used to write the image, IMAGE DESCRIPTION, which is a description of the image content and DATE_TIME, which is the date and time of the image writting. You can put anything you like as SOFTWARE and IMAGE DESCRIPTION. The updateTime method gets the current date and time from a Calendar and formats the result as the .TIFF specification dictates (don't modify). If anyone wants to modify this code, I strongly urge him/her to download the spec, as I've hard-coded many byte offsets that will mess up if something gets changed. As I said in my previous post, this is a very "specific" implementation...

Please let me know if it was of any use to you. And I'd appreciate any optimization suggestions...

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org