[committed] taking screenshot with new thread

Current LWJGLRenderer.grabScreenContents() method takes long time to execute.

When the method is called, the rendering and update is blocked for a while.



So I just moved image processing & saving code to a new thread.

To be asynchronous method, the boolean return value is removed from Renderer.grabScreenContents() method.

I think the method parameter should be 'File' instead of 'String' because we can't get error if no file is created.



Index: src/com/jme/renderer/lwjgl/LWJGLRenderer.java
===================================================================
--- src/com/jme/renderer/lwjgl/LWJGLRenderer.java   (revision 4418)
+++ src/com/jme/renderer/lwjgl/LWJGLRenderer.java   (working copy)
@@ -622,42 +622,50 @@
      *
      * @param filename
      *            the name of the file to save.
-     * @return true if successful, false otherwise.
      */
-    public boolean takeScreenShot(String filename) {
+    public void takeScreenShot(final String filename) {
         if (null == filename) {
             throw new JmeException("Screenshot filename cannot be null");
         }
-        File out = new File(filename + ".png");
-        logger.log(Level.INFO, "Taking screenshot: {0}", out.getAbsolutePath());
-
         // Create a pointer to the image info and create a buffered image to
         // hold it.
-        ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 3);
+        final ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 3);
         grabScreenContents(buff, Image.Format.RGB8, 0, 0, width, height);
-        BufferedImage img = new BufferedImage(width, height,
-                BufferedImage.TYPE_INT_RGB);
-
-        // Grab each pixel information and set it to the BufferedImage info.
-        for (int x = 0; x < width; x++) {
-            for (int y = 0; y < height; y++) {
+        final int w = width;
+        final int h = height;
                
-                int index = 3 * ((height - y - 1) * width + x);
-                int argb = (((int) (buff.get(index+0)) & 0xFF) << 16) //r
-                         | (((int) (buff.get(index+1)) & 0xFF) << 8)  //g
-                         | (((int) (buff.get(index+2)) & 0xFF));      //b
+        Thread saveThread = new Thread() {
+            
+            public void run() {
+                BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
 
-                img.setRGB(x, y, argb);
-            }
-        }
+                // Grab each pixel information and set it to the BufferedImage info.
+                for (int x = 0; x < w; x++) {
+                    for (int y = 0; y < h; y++) {
+                        
+                        int index = 3 * ((h- y - 1) * w + x);
+                        int argb = (((int) (buff.get(index+0)) & 0xFF) << 16) //r
+                                 | (((int) (buff.get(index+1)) & 0xFF) << 8)  //g
+                                 | (((int) (buff.get(index+2)) & 0xFF));      //b
 
-        // write out the screenshot image to a file.
-        try {
-            return ImageIO.write(img, "png", out);
-        } catch (IOException e) {
-            logger.warning("Could not create file: " + filename + ".png");
-            return false;
-        }
+                        img.setRGB(x, y, argb);
+                    }
+                }
+
+                // write out the screenshot image to a file.
+                try {
+                    File out = new File(filename + ".png");
+                    logger.log(Level.INFO, "Taking screenshot: {0}", out.getAbsolutePath());
+                    ImageIO.write(img, "png", out);
+                } catch (IOException e) {
+                    logger.warning("Could not create file: " + filename + ".png");
+                }
+            }
+        };
+        saveThread.start();
     }
 
     /**
Index: src/com/jme/renderer/Renderer.java
===================================================================
--- src/com/jme/renderer/Renderer.java   (revision 4418)
+++ src/com/jme/renderer/Renderer.java   (working copy)
@@ -427,7 +427,7 @@
      *            the name of the screenshot file.
      * @return true if the screen capture was successful, false otherwise.
      */
-    public abstract boolean takeScreenShot(String filename);
+    public abstract void takeScreenShot(String filename);
 
     /**
      * <code>grabScreenContents</code> reads a block of data as bytes from the
Index: src/com/jme/renderer/jogl/JOGLRenderer.java
===================================================================
--- src/com/jme/renderer/jogl/JOGLRenderer.java   (revision 4418)
+++ src/com/jme/renderer/jogl/JOGLRenderer.java   (working copy)
@@ -40,6 +40,7 @@
 import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
 import java.util.Arrays;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.imageio.ImageIO;
@@ -637,45 +638,53 @@
      * <code>takeScreenShot</code> saves the current buffer to a file. The
      * file name is provided, and .png will be appended. True is returned if the
      * capture was successful, false otherwise.
-     *
+     *
      * @param filename
      *            the name of the file to save.
-     * @return true if successful, false otherwise.
      */
-    public boolean takeScreenShot(String filename) {
+    public void takeScreenShot(final String filename) {
         if (null == filename) {
             throw new JmeException("Screenshot filename cannot be null");
         }
-        File out = new File(filename + ".png");
-        logger.info("Taking screenshot: " + out.getAbsolutePath());
-
         // Create a pointer to the image info and create a buffered image to
         // hold it.
-        ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 3);
+        final ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 3);
         grabScreenContents(buff, Image.Format.RGB8, 0, 0, width, height);
-        BufferedImage img = new BufferedImage(width, height,
-                BufferedImage.TYPE_INT_RGB);
+        final int w = width;
+        final int h = height;
+                
+        Thread saveThread = new Thread() {
+            
+            public void run() {
+                BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
 
-        // Grab each pixel information and set it to the BufferedImage info.
-        for (int x = 0; x < width; x++) {
-            for (int y = 0; y < height; y++) {
+                // Grab each pixel information and set it to the BufferedImage info.
+                for (int x = 0; x < w; x++) {
+                    for (int y = 0; y < h; y++) {
+                        
+                        int index = 3 * ((h- y - 1) * w + x);
+                        if (index < 0) {
+                            System.out.println();
+                        }
+                        int argb = (((int) (buff.get(index+0)) & 0xFF) << 16) //r
+                                 | (((int) (buff.get(index+1)) & 0xFF) << 8)  //g
+                                 | (((int) (buff.get(index+2)) & 0xFF));      //b
 
-                int index = 3 * ((height - y - 1) * width + x);
-                int argb = (((int) (buff.get(index+0)) & 0xFF) << 16) //r
-                         | (((int) (buff.get(index+1)) & 0xFF) << 8)  //g
-                         | (((int) (buff.get(index+2)) & 0xFF));      //b
+                        img.setRGB(x, y, argb);
+                    }
+                }
 
-                img.setRGB(x, y, argb);
+                // write out the screenshot image to a file.
+                try {
+                    File out = new File(filename + ".png");
+                    logger.log(Level.INFO, "Taking screenshot: {0}", out.getAbsolutePath());
+                    ImageIO.write(img, "png", out);
+                } catch (IOException e) {
+                    logger.warning("Could not create file: " + filename + ".png");
+                }
             }
-        }
-
-        // write out the screenshot image to a file.
-        try {
-            return ImageIO.write(img, "png", out);
-        } catch (IOException e) {
-            logger.warning("Could not create file: " + filename + ".png");
-            return false;
-        }
+        };
+        saveThread.start();
     }
 
     /**

Good idea. :slight_smile: