Android OpenGL ES应用程序的屏幕截图

时间:2014-11-07 19:20:24

标签: android opengl-es-2.0 screenshot

我在已添加的GLSurfaceView上运行了一个基本的openGL ES 20应用程序:

    GLSurfaceView view = new GLSurfaceView(this);
    view.setRenderer(new OpenGLRenderer());
    setContentView(view);

基本上我正在尝试使用以下方法获取屏幕截图:

private static Bitmap getScreenshot(View v)
    {
        Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(),
                Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(b);
        v.draw(c);
        return b;
    }

但似乎位图是透明的。我传递的观点是:

View content = m_rootActivity.getWindow().getDecorView().getRootView();

任何人都有解决方案如何在openGL ES上获取屏幕截图,而无需使用我在其他解决方案中看到的DrawFrame方法。

也许传递渲染器的引用?任何帮助将不胜感激。

更新: 我正在探索从onDrawFrame(Display black screen while capture screenshot of GLSurfaceView

渲染位图

然而,我想知道是否有更好的解决方案,因为我无法访问渲染器或surfaceview。我可以传递他们的参考,但想要一个解决方案,我们可以像前面提到的那样捕获整个视图。

2 个答案:

答案 0 :(得分:5)

See this question

您可以通过以下网址获取屏幕截图:

@Override
public void onDrawFrame(GL10 gl) {

    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    // draw ...

    if (takeScreenshot) {

        int screenshotSize = width * height;
        ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
        bb.order(ByteOrder.nativeOrder());
        GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, bb);
        int pixelsBuffer[] = new int[screenshotSize];
        bb.asIntBuffer().get(pixelsBuffer);
        bb = null;

        for (int i = 0; i < screenshotSize; ++i) {
            // The alpha and green channels' positions are preserved while the      red and blue are swapped
            pixelsBuffer[i] = ((pixelsBuffer[i] & 0xff00ff00)) |    ((pixelsBuffer[i] & 0x000000ff) << 16) | ((pixelsBuffer[i] & 0x00ff0000) >> 16);
        }

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bitmap.setPixels(pixelsBuffer, screenshotSize-width, -width, 0, 0, width, height);
        // save bitmap...
    }
}

答案 1 :(得分:1)

根本不可能在没有读取像素的情况下从GPU获取缓冲区数据到CPU。您应该了解这与视图的管道不同,缓冲区中的数据填充在GPU上,然后直接发送到显示器或无处。

所以说答案是否定的。您不能简单地获取屏幕截图,因为屏幕截图的概念甚至不存在于此问题中。 GPU缓冲区上只有原始(通常是RGBA)数据。这些数据必须填写你绘制的内容以获得所有绘制的内容,如果你只是简单地读取这些数据,那么缓冲区可能只是被清除,它可能是半绘制的,或者你是否幸运完全绘制。

这就是你在绘图管道中制作这些截图的原因,因为你必须确保缓冲区充满了数据。

通常有2种智能方法可以在呈现缓冲区之前最好地拦截绘图管道。一个是通过一个标志,应该完成屏幕截图,然后引擎本身创建一个很好的屏幕截图,因为它具有动态缓冲区的所有数据。第二个是创建一个回调句柄,引擎会在每个完全绘制的帧上通知所有者,在这种情况下,所有者可以做一些额外的绘图或创建一个屏幕截图或每秒计算帧数......这又有很多奖金但是你需要至少传递缓冲区维度来对缓冲区做任何事情。

另请注意,读取像素非常慢,在某些情况下,您将收到的图像会颠倒。