Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/180.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
android OpenGL ES应用程序屏幕截图_Android_Opengl Es 2.0_Screenshot - Fatal编程技术网

android OpenGL ES应用程序屏幕截图

android OpenGL ES应用程序屏幕截图,android,opengl-es-2.0,screenshot,Android,Opengl Es 2.0,Screenshot,我有一个基本的openGL ES 20应用程序,在添加了以下内容的GLSURFACHEVIEW上运行: GLSurfaceView view = new GLSurfaceView(this); view.setRenderer(new OpenGLRenderer()); setContentView(view); 基本上,我正在尝试使用以下方法获取屏幕截图: private static Bitmap getScreenshot(View v) {

我有一个基本的openGL ES 20应用程序,在添加了以下内容的GLSURFACHEVIEW上运行:

    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()渲染位图


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

如果不读取像素,您就无法从GPU将缓冲区数据获取到CPU。您应该了解,这与视图的管道不同,缓冲区中的数据在GPU上填充,然后直接发送到显示器或其他地方

所以说答案是否定的。你不能简单地得到截图,因为截图的概念在这件事上根本不存在。GPU缓冲区上只有原始(通常为RGBA)数据。这些数据必须用你所画的东西来填充,才能得到你所画的所有东西,如果你只是在任何时候读取这些数据,缓冲区可能会被清空,它可能是半张,或者如果你幸运地画满了

这就是为什么要在绘图管道中创建这些屏幕截图,因为必须确保缓冲区中充满数据

通常有两种截取图形管道的智能方法,最好在显示缓冲区之前完成。一种是传递一个特定的标志,即屏幕截图应该完成,然后引擎本身创建一个屏幕截图,这很好,因为它动态地拥有缓冲区的所有数据。第二个是创建一个回调句柄,引擎将在每一帧完全绘制时通知所有者,在这种情况下,所有者可以进行一些额外的绘制,或者创建一个屏幕截图,或者每秒计算帧数。。。这同样有很多好处,但您至少需要传递缓冲区维度才能对缓冲区执行任何操作

还要注意的是,读取像素的速度非常慢,在某些情况下,您将接收到的图像会颠倒。

您可以通过以下方式获得屏幕截图:

@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...
    }
}
@覆盖
公共框架(GL10 gl){
GLES20.glClear(GLES20.GLU颜色缓冲位);
//画。。。
如果(截图){
int屏幕快照大小=宽度*高度;
ByteBuffer bb=ByteBuffer.allocateDirect(屏幕快照大小*4);
bb.order(ByteOrder.nativeOrder());
GLES20.glReadPixels(0,0,宽度,高度,GLES20.GL_RGBA,GLES20.GL_无符号字节,bb);
int pixelsBuffer[]=新的int[screenshotSize];
bb.asIntBuffer().get(像素缓冲);
bb=零;
对于(int i=0;i16);
}
位图Bitmap=Bitmap.createBitmap(宽度、高度、Bitmap.Config.ARGB_8888);
设置像素(像素缓冲,屏幕快照大小宽度,-宽度,0,0,宽度,高度);
//保存位图。。。
}
}

非常奇怪,您可以通过硬件按钮来捕捉图像。我同意,但这似乎是在硬件层面截取数据,而您根本无法访问这些数据。