Renderer.takeScreenShot()

ScreenShot image  -> ".png" but not include alpha value

so modify LWJGLRenderer and JOGLRenderer .class



Index: src/com/jme/renderer/lwjgl/LWJGLRenderer.java
===================================================================
--- src/com/jme/renderer/lwjgl/LWJGLRenderer.java   (revision 4087)
+++ src/com/jme/renderer/lwjgl/LWJGLRenderer.java   (working copy)
@@ -615,10 +615,10 @@
 
         // Create a pointer to the image info and create a buffered image to
         // hold it.
-        ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 3);
-        grabScreenContents(buff, Image.Format.RGB8, 0, 0, width, height);
+        ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 4);
+        grabScreenContents(buff, Image.Format.RGBA8, 0, 0, width, height);
         BufferedImage img = new BufferedImage(width, height,
-                BufferedImage.TYPE_INT_RGB);
+                BufferedImage.TYPE_INT_ARGB);
 
         // Grab each pixel information and set it to the BufferedImage info.
         for (int x = 0; x < width; x++) {
@@ -624,10 +624,16 @@
         for (int x = 0; x < width; x++) {
             for (int y = 0; y < height; y++) {
                
-                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
+                int index = 4 * ((height - y - 1) * width + x);
+                int r = ((int) (buff.get(index+0)));
+                int g = ((int) (buff.get(index+1)));
+                int b = ((int) (buff.get(index+2)));
+                int a = ((int) (buff.get(index+3)));
+               
+                int argb = ((a & 0xFF) << 24) //a
+                       | ((r & 0xFF) << 16) //r
+                         | ((g & 0xFF) << 8)  //g
+                         | ((b & 0xFF));      //b
 
                 img.setRGB(x, y, argb);
             }




Index: src/com/jme/renderer/jogl/JOGLRenderer.java
===================================================================
--- src/com/jme/renderer/jogl/JOGLRenderer.java   (revision 4087)
+++ src/com/jme/renderer/jogl/JOGLRenderer.java   (working copy)
@@ -636,10 +636,10 @@
 
         // Create a pointer to the image info and create a buffered image to
         // hold it.
-        ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 3);
-        grabScreenContents(buff, Image.Format.RGB8, 0, 0, width, height);
+        ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 4);
+        grabScreenContents(buff, Image.Format.RGBA8, 0, 0, width, height);
         BufferedImage img = new BufferedImage(width, height,
-                BufferedImage.TYPE_INT_RGB);
+                BufferedImage.TYPE_INT_ARGB);
 
         // Grab each pixel information and set it to the BufferedImage info.
         for (int x = 0; x < width; x++) {
@@ -645,10 +645,16 @@
         for (int x = 0; x < width; x++) {
             for (int y = 0; y < height; y++) {
 
-                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
+               int index = 4 * ((height - y - 1) * width + x);
+                int r = ((int) (buff.get(index+0)));
+                int g = ((int) (buff.get(index+1)));
+                int b = ((int) (buff.get(index+2)));
+                int a = ((int) (buff.get(index+3)));
+               
+                int argb = ((a & 0xFF) << 24) //a
+                       | ((r & 0xFF) << 16) //r
+                         | ((g & 0xFF) << 8)  //g
+                         | ((b & 0xFF));      //b
 
                 img.setRGB(x, y, argb);
             }



This seems fine. What made you need the alpha channel?

Actually, I don't see any need for the alpha channel; the openGL background will always fill the image, so there can never be alpha levels other than 1.0.



(unless someone develops a non-rectangular viewport  XD)

basixs said:

Actually, I don't see any need for the alpha channel; the openGL background will always fill the image, so there can never be alpha levels other than 1.0.

(unless someone develops a non-rectangular viewport  XD)

My thoughts too, but the change doesn't seem to hurt anything. That's why I asked why.

I made dashboard by jme



Attach is screenshot







Designer making background-space demo movie by 3d max,  screenshot fill render-ortho

and what exactly is being rendered in the alpha area? nothing?



(and whats up w/ the non-square corners?)





(although I am inclined to agree w/ nymon, no point in not having it since it doesn't hurt anything…)

Thats a cool looking dashboard! What is it used for?

In most cases when taking a screenshot you don't need alpha. Perhaps it should take a boolean argument? Also you wouldn't get any alpha unless the display was initialized with an alpha buffer.

I also think this should be a different function or accept a parameter to allow users to choose if Alpha should be there.

how about having a boolean argument, but also have:


public static void takeScreenShot() {
    takeScreenShot( false );
}


so there is no 'visible' changes but one can have alpha if one wants..

ok.



So Renderer, LWJGLRenderer, JOGLRenderer  modify, method add parameter (boolean useAlpha)



Index: src/com/jme/renderer/Renderer.java
===================================================================
--- src/com/jme/renderer/Renderer.java   (revision 4089)
+++ src/com/jme/renderer/Renderer.java   (working copy)
@@ -418,7 +418,22 @@
      *            the name of the screenshot file.
      * @return true if the screen capture was successful, false otherwise.
      */
-    public abstract boolean takeScreenShot(String filename);
+    public boolean takeScreenShot(String filename){
+       return takeScreenShot(filename, false);
+    }
+   
+    /**
+     *
+     * <code>takeScreenShot</code> saves the current buffer to a png file. The
+     * filename is provided, .png will be appended to the end of the name.
+     *
+     * @param filename
+     *            the name of the screenshot file.
+     * @param useAlpha
+     *            true - rgba, false - rgb
+     * @return true if the screen capture was successful, false otherwise.
+     */
+    public abstract boolean takeScreenShot(String filename, boolean useAlpha);
 
     /**
      * <code>grabScreenContents</code> reads a block of data as bytes from the




Index: src/com/jme/renderer/lwjgl/LWJGLRenderer.java
===================================================================
--- src/com/jme/renderer/lwjgl/LWJGLRenderer.java   (revision 4089)
+++ src/com/jme/renderer/lwjgl/LWJGLRenderer.java   (working copy)
@@ -604,9 +604,11 @@
      *
      * @param filename
      *            the name of the file to save.
+     * @param useAlpha
+     *            true - rgba, false - rgb
      * @return true if successful, false otherwise.
      */
-    public boolean takeScreenShot(String filename) {
+    public boolean takeScreenShot(String filename, boolean useAlpha) {
         if (null == filename) {
             throw new JmeException("Screenshot filename cannot be null");
         }
@@ -613,7 +615,26 @@
         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
+        BufferedImage img=null;
+        if(useAlpha)   img = grabScreenUseAlpha();
+        else   img = grabScreen();
+       
+        // 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;
+        }
+    }
+     
+    /**
+     * <code>grabScreen</code> saves the current buffer to a bufferedImage.
+     *
+     * @return BuffredImage in rgb
+     */
+    public BufferedImage grabScreen(){
+       // Create a pointer to the image info and create a buffered image to
         // hold it.
         ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 3);
         grabScreenContents(buff, Image.Format.RGB8, 0, 0, width, height);
@@ -625,21 +646,50 @@
             for (int y = 0; y < height; y++) {
                 
                 int index = 3 * ((height - y - 1) * width + x);
-                int argb = (((int) (buff.get(index+0)) & 0xFF) << 16) //r
+                int rgb = (((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, rgb);
             }
         }
+       
+        return img;
+    }
+   
+    /**
+     * <code>grabScreenUseAlpha</code> saves the current buffer to a bufferedImage.
+     *
+     * @return BuffredImage in argb
+     */
+    public BufferedImage grabScreenUseAlpha(){
+       // Create a pointer to the image info and create a buffered image to
+        // hold it.
+       ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 4);
+        grabScreenContents(buff, Image.Format.RGBA8, 0, 0, width, height);
+        BufferedImage img = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_ARGB);
 
-        // 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;
+        // 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++) {
+               
+                int index = 4 * ((height - y - 1) * width + x);
+                int r = ((int) (buff.get(index+0)));
+                int g = ((int) (buff.get(index+1)));
+                int b = ((int) (buff.get(index+2)));
+                int a = ((int) (buff.get(index+3)));
+               
+                int argb = ((a & 0xFF) << 24) //a
+                       | ((r & 0xFF) << 16) //r
+                         | ((g & 0xFF) << 8)  //g
+                         | ((b & 0xFF));      //b
+
+                img.setRGB(x, y, argb);
+            }
         }
+       
+        return img;
     }
 
     /**




Index: src/com/jme/renderer/jogl/JOGLRenderer.java
===================================================================
--- src/com/jme/renderer/jogl/JOGLRenderer.java   (revision 4089)
+++ src/com/jme/renderer/jogl/JOGLRenderer.java   (working copy)
@@ -622,12 +622,14 @@
      * <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.
+     * @param useAlpha
+     *            true - rgba, false - rgb
      * @return true if successful, false otherwise.
      */
-    public boolean takeScreenShot(String filename) {
+    public boolean takeScreenShot(String filename, boolean useAlpha) {
         if (null == filename) {
             throw new JmeException("Screenshot filename cannot be null");
         }
@@ -632,9 +634,28 @@
             throw new JmeException("Screenshot filename cannot be null");
         }
         File out = new File(filename + ".png");
-        logger.info("Taking screenshot: " + out.getAbsolutePath());
+        logger.info("Taking screenshot: " + out.getAbsolutePath() );
 
-        // Create a pointer to the image info and create a buffered image to
+        BufferedImage img=null;
+        if(useAlpha)   img = grabScreenUseAlpha();
+        else   img = grabScreen();
+       
+        // 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;
+        }
+    }
+     
+    /**
+     * <code>grabScreen</code> saves the current buffer to a bufferedImage.
+     *
+     * @return BuffredImage in rgb
+     */
+    public BufferedImage grabScreen(){
+       // Create a pointer to the image info and create a buffered image to
         // hold it.
         ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 3);
         grabScreenContents(buff, Image.Format.RGB8, 0, 0, width, height);
@@ -644,23 +665,52 @@
         // 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++) {
-
+               
                 int index = 3 * ((height - y - 1) * width + x);
-                int argb = (((int) (buff.get(index+0)) & 0xFF) << 16) //r
+                int rgb = (((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, rgb);
             }
         }
+       
+        return img;
+    }
+   
+    /**
+     * <code>grabScreenUseAlpha</code> saves the current buffer to a bufferedImage.
+     *
+     * @return BuffredImage in argb
+     */
+    public BufferedImage grabScreenUseAlpha(){
+       // Create a pointer to the image info and create a buffered image to
+        // hold it.
+       ByteBuffer buff = BufferUtils.createByteBuffer(width * height * 4);
+        grabScreenContents(buff, Image.Format.RGBA8, 0, 0, width, height);
+        BufferedImage img = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_ARGB);
 
-        // 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;
+        // 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++) {
+               
+                int index = 4 * ((height - y - 1) * width + x);
+                int r = ((int) (buff.get(index+0)));
+                int g = ((int) (buff.get(index+1)));
+                int b = ((int) (buff.get(index+2)));
+                int a = ((int) (buff.get(index+3)));
+               
+                int argb = ((a & 0xFF) << 24) //a
+                       | ((r & 0xFF) << 16) //r
+                         | ((g & 0xFF) << 8)  //g
+                         | ((b & 0xFF));      //b
+
+                img.setRGB(x, y, argb);
+            }
         }
+       
+        return img;
     }
 
     /**



How about this ? :D

Well, my personal preference in a situation like this would be to have all the identical logic in the super class once.  I see 2 classes each w/ 2 methods that could be solved with a single method in the renderer,  and actually since grabScreenContents is an abstract method anyway; why not have the implementation in the renderer class?



(Although, I see from the code that the old bears didn't seem to have the same opinion…)





Regardless, instead of having 2 different methods (alpha/non-alpha), why not just get a non-alpha or alpha image and then not OR the alpha when needed?

Why don't we use the class com.sun.opengl.util.Screenshot in the JOGL renderer? It is faster  :smiley:

Actually, I guess the readToBufferedImage() method would work. (But then again, our grabScreenContents() method in renderer sends in the ByteBuffer for the image stream). 



Take a look at this helper method from JOGL though:


  private static void checkExtABGR() {
    GL gl = GLU.getCurrentGL();
    if (!gl.isExtensionAvailable("GL_EXT_abgr")) {
      throw new IllegalArgumentException("Saving alpha channel requires GL_EXT_abgr");
    }
  }



(They test that anytime they are saving w/ alpha ;))