Question

I'm trying to read directly from the frame buffer via glReadPixels() so that I can take a screenshot from whatever is on my screen.
I'm not using a GUI, instead it should print the raw content of the screen whenever I touch the screen (which is sufficient for the beginning).

I'm now stuck in getting the right context for my gl.glReadPixels() function.
Because I think the context I get at the moment has nothing to do with what is actually on the screen.

When I run the application it prints an libEGL error which says

call to OpenGL ES API with no current context (logged once per thread)

and afterwards I get my array filled with zeros.

To hide my application I'm using the following line in my manifest.

android:theme="@android:style/Theme.Translucent.NoTitleBar" 

And here is the code:

public class ScreenshotActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {   
                savePixels();
        }
        return true;
    }


    EGL10 egl = (EGL10) EGLContext.getEGL();
    GL10 gl = (GL10) egl.eglGetCurrentContext().getGL();

    public void savePixels() {
         w= getWidth(this);
         h= getHeight(this);
         int b[] = new int[w * h];
         int bt[] = new int[w * h];
         IntBuffer ib = IntBuffer.wrap(b);
         ib.position(0);

         gl.glReadPixels(0, 0, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ib);


         for (int i = 0; i < h; i++) {
             for (int j = 0; j < w; j++) {
                 int pix = b[i * w + j];
                 int pb = (pix >> 16) & 0xff;
                 int pr = (pix << 16) & 0x00ff0000;
                 int pix1 = (pix & 0xff00ff00) | pr | pb;
                 bt[(h - i - 1) * w + j] = pix1;
                 }
             }

             Log.w("debug", Arrays.toString(bt));
             moveTaskToBack(true);
    }
}

Help is highly appreciated :)

Was it helpful?

Solution 3

Finally found an open source program which is not using /dev/graphics/fb0 to capture the framebuffer.

The package fb2png includes a C program and a python script which are both working perfectly.

OTHER TIPS

Could people please stop trying to abuse OpenGL for taking screenshots? It's fine if you want to capture the rendering output of the the program that did the glReadPixels call, but as soon as other programs are the intended pixel source it becomes highly unreliable.

The only reliable way to take full screen screenshots is to directly read from the GPUs videobuffer memory. Android is based on Linux and Linux offers the fbdev device for this. Since working with all those ioctls is a bit cumbersome some tested library should be used. There's a library for Android that offers a dedicated API for taking screenshots: http://code.google.com/p/android-screenshot-library/wiki/DeveloperGuide

mGLSurfaceView.queueEvent(new Runnable() {
  public void run() {
    savePixels();
  }
});

you have to change mGLSurfaceView to your SurfaceView Instance.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top