Author Topic: Basic Question: Capturing the FrameBuffer  (Read 6477 times)

Offline Babu

  • int
  • **
  • Posts: 71
    • View Profile
Basic Question: Capturing the FrameBuffer
« on: June 22, 2011, 09:02:15 am »
Hi,

Is it possible to capture the FrameBuffer(i.e. a snapshot of what user sees) and save it as JPG/PNG?

Regards

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Basic Question: Capturing the FrameBuffer
« Reply #1 on: June 22, 2011, 09:06:40 am »
Yes, you can get the rendered image by calling FrameBuffer.getOutputBuffer(); and save it using the normal ImageIO ways.

Offline Babu

  • int
  • **
  • Posts: 71
    • View Profile
Re: Basic Question: Capturing the FrameBuffer
« Reply #2 on: June 22, 2011, 05:55:15 pm »
thanks, Egon. 
But I forgot to mention that I am using jpct-ae and I don't find that API in the ae version  :(.  Is there any workaround that I can use for capturing the snapshot in ae?

P.S. sorry for not posting this query in the 'ae' forum  :-[

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Basic Question: Capturing the FrameBuffer
« Reply #3 on: June 22, 2011, 06:05:34 pm »

Offline Babu

  • int
  • **
  • Posts: 71
    • View Profile
Re: Basic Question: Capturing the FrameBuffer
« Reply #4 on: June 23, 2011, 07:53:18 am »
thanks, Egon.  I will check that out and get back to you.

Offline Nemetz

  • int
  • **
  • Posts: 53
    • View Profile
Re: Basic Question: Capturing the FrameBuffer
« Reply #5 on: June 24, 2011, 08:36:34 am »
Have a look here: http://www.jpct.net/forum2/index.php/topic,2088.0.html
Good, but it's to slow method, as i saw it in API description of this method.
Maybe  native methods with ndk will be much faster?

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Basic Question: Capturing the FrameBuffer
« Reply #6 on: June 24, 2011, 08:41:11 am »
Too slow for what?

Offline Nemetz

  • int
  • **
  • Posts: 53
    • View Profile
Re: Basic Question: Capturing the FrameBuffer
« Reply #7 on: June 24, 2011, 08:49:35 am »
Too slow for what?
I mean what getPixels(); method to slow, for example, for a taking snapshot in real game process, or smth like that.
In emulator it works ~ 2800 ms(

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Basic Question: Capturing the FrameBuffer
« Reply #8 on: June 24, 2011, 09:57:14 am »
You might want to profile which operation (getPixels(), updating the int[]-array or creating the new image) is actually slow.

Consider that:
  • the emulator is slower than any current device anyway
  • getting pixels from the gl framebuffer isn't very fast and the NDK can't help there
  • maybe getting the pixels from the buffer isn't the right solution for the problem (...which is?)



Offline Babu

  • int
  • **
  • Posts: 71
    • View Profile
Re: Basic Question: Capturing the FrameBuffer
« Reply #9 on: June 26, 2011, 10:34:21 am »
hi Egon,

I tried the solution mentioned in the forum topic that you pointed me to.  I did this.
I introduced a new method called getBitmap() in my Renderer.
Code: [Select]
public Bitmap getBitmap()
{
int[] tmpPixels = mFrameBuffer.getPixels();
        for (int i = 0; i < tmpPixels.length; i++){
            int tmpInt = tmpPixels[i] + 0xff000000;
            int red = (tmpInt & 0x00ff0000)>>16;
            int blue = (tmpInt & 0x000000ff)<<16;
            tmpInt &= 0xff00ff00;
            tmpInt += red + blue;
            tmpPixels[i] = tmpInt;
        }
        Bitmap lastImage = Bitmap.createBitmap(tmpPixels,
        mFrameBufferWidth, mFrameBufferHeight, Bitmap.Config.ARGB_8888);
       
        return lastImage;
}

Then called this method from my Activity's onButtonClickListener.
Code: [Select]
mBtnDone.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v)
    {
        Bitmap bmp = mRenderer.getBitmap();
        ...............
        ................
     }
});

Then when the button is clicked... i got the following exception.  :(
Code: [Select]
06-26 12:23:39.069: ERROR/AndroidRuntime(340): FATAL EXCEPTION: main
06-26 12:23:39.069: ERROR/AndroidRuntime(340): java.lang.ClassCastException: com.threed.jpct.World
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at com.threed.jpct.GLRenderer.execute(GLRenderer.java:1721)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at com.threed.jpct.FrameBuffer.getPixels(FrameBuffer.java:449)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at com.goora.ams.model.AMSRenderer.getBitmap(FMSRenderer.java:438)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at com.goora.ams.ui.ModelMain$11.onClick(AvatarMain.java:634)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at android.view.View.performClick(View.java:2485)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at android.view.View$PerformClick.run(View.java:9080)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at android.os.Handler.handleCallback(Handler.java:587)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at android.os.Handler.dispatchMessage(Handler.java:92)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at android.os.Looper.loop(Looper.java:123)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at android.app.ActivityThread.main(ActivityThread.java:3683)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at java.lang.reflect.Method.invokeNative(Native Method)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at java.lang.reflect.Method.invoke(Method.java:507)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
06-26 12:23:39.069: ERROR/AndroidRuntime(340):     at dalvik.system.NativeStart.main(Native Method)

I am not sure if it has got anything to do with the communication between the UI thread (Activity) and the Renderer thread  ::).  Any idea what's going wrong?  Meanwhile I'll do more analysis in parallel.

- Thanks...

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Basic Question: Capturing the FrameBuffer
« Reply #10 on: June 26, 2011, 10:54:30 am »
You can't call gl related stuff from inside the ui thread without asking for trouble. I'm not sure why it throws a class cast in this particular case, but its not supposed to work anyway.  Let the ui thread set a flag instead and do the actual call in the gl thread.

Offline raft

  • quad
  • ******
  • Posts: 1993
    • View Profile
    • http://www.aptalkarga.com
Re: Basic Question: Capturing the FrameBuffer
« Reply #11 on: June 29, 2011, 06:11:05 pm »
alternatively you can use GLSurfaceView.queueEvent(..) method to run code in GL thread.

Offline Babu

  • int
  • **
  • Posts: 71
    • View Profile
Re: Basic Question: Capturing the FrameBuffer
« Reply #12 on: June 29, 2011, 07:14:40 pm »
thanks, raft. That's exactly how I resolved it.   8)

Also, I needed to save the bitmap as a png file.  I didn't want to do file operations in my renderer and so needed to pass the bitmap back to UI thread (activity) and also I needed the UI-Thread to have complete knowledge on the completion of file operations. 

So I created a 'Handler' in my UI-Thread and passed it to the renderer (constructor parameter). 
Once Renderer completes the queued operation, i.e. creation of the bitmap, it will post a 'Message' back to the UI-Thread, using the 'Handler'.  The bitmap goes back to the UI-Thread as 'Message.obj'

Sorry, I wanted to share this with the community, but got sucked into pose animation issues.... and you know that  ;D