捕获GLSurfaceView的屏幕到位图

Sam*_*ley 33 java android screen-capture glsurfaceview

我需要能够GLSurfaceView在特定时刻捕捉到某个时刻的图像.我有以下代码:

relative.setDrawingCacheEnabled(true);
screenshot = Bitmap.createBitmap(relative.getDrawingCache());
relative.setDrawingCacheEnabled(false);
Log.v(TAG, "Screenshot height: " + screenshot.getHeight());
image.setImageBitmap(screenshot); 
Run Code Online (Sandbox Code Playgroud)

GLSurfaceView包含内的RelativeLayout,但我也尝试它直接使用GLSurfaceView,试图捕捉图像.有了这个,我认为屏幕捕获透明图像,即没有任何东西.任何帮助将不胜感激.

Dal*_*aum 46

SurfaceViewGLSurfaceView在其窗口打孔以允许其表面显示.换句话说,他们有透明的区域.

因此,您无法通过调用捕获图像GLSurfaceView.getDrawingCache().

如果你想从一个图像GLSurfaceView,你应该调用gl.glReadPixels()GLSurfaceView.onDrawFrame().

我修补了createBitmapFromGLSurface方法并将其调用onDrawFrame().

(原始代码可能来自skuld的代码.)

private Bitmap createBitmapFromGLSurface(int x, int y, int w, int h, GL10 gl)
        throws OutOfMemoryError {
    int bitmapBuffer[] = new int[w * h];
    int bitmapSource[] = new int[w * h];
    IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer);
    intBuffer.position(0);

    try {
        gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, intBuffer);
        int offset1, offset2;
        for (int i = 0; i < h; i++) {
            offset1 = i * w;
            offset2 = (h - i - 1) * w;
            for (int j = 0; j < w; j++) {
                int texturePixel = bitmapBuffer[offset1 + j];
                int blue = (texturePixel >> 16) & 0xff;
                int red = (texturePixel << 16) & 0x00ff0000;
                int pixel = (texturePixel & 0xff00ff00) | red | blue;
                bitmapSource[offset2 + j] = pixel;
            }
        }
    } catch (GLException e) {
        return null;
    }

    return Bitmap.createBitmap(bitmapSource, w, h, Bitmap.Config.ARGB_8888);
}
Run Code Online (Sandbox Code Playgroud)

  • (6分钟后)我会回答自己,这个方法应该是从渲染onDrawFrame()不从的onDraw()调用,.您可以在这里找到实现:https://github.com/Cyber​​Agent/android-gpuimage (2认同)

aar*_*gas 18

如果您使用的第三方库只是"传入"布局中定义的GLSurfaceView,那么这是一个完整的解决方案.您将无法处理渲染器的onDrawFrame(),这可能是一个问题......

要执行此操作,您需要将其排队以便GLSurfaceView进行处理.

private GLSurfaceView glSurfaceView; // findById() in onCreate
private Bitmap snapshotBitmap;

private interface BitmapReadyCallbacks {
    void onBitmapReady(Bitmap bitmap);
}

/* Usage code
   captureBitmap(new BitmapReadyCallbacks() {

        @Override
        public void onBitmapReady(Bitmap bitmap) {
            someImageView.setImageBitmap(bitmap);
        }
   });
*/

// supporting methods
private void captureBitmap(final BitmapReadyCallbacks bitmapReadyCallbacks) {
    glSurfaceView.queueEvent(new Runnable() {
        @Override
        public void run() {
            EGL10 egl = (EGL10) EGLContext.getEGL();
            GL10 gl = (GL10)egl.eglGetCurrentContext().getGL();
            snapshotBitmap = createBitmapFromGLSurface(0, 0, glSurfaceView.getWidth(), glSurfaceView.getHeight(), gl);

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    bitmapReadyCallbacks.onBitmapReady(snapshotBitmap);
                }
            });

        }
    });

}

// from other answer in this question
private Bitmap createBitmapFromGLSurface(int x, int y, int w, int h, GL10 gl) {

    int bitmapBuffer[] = new int[w * h];
    int bitmapSource[] = new int[w * h];
    IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer);
    intBuffer.position(0);

    try {
        gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, intBuffer);
        int offset1, offset2;
        for (int i = 0; i < h; i++) {
            offset1 = i * w;
            offset2 = (h - i - 1) * w;
            for (int j = 0; j < w; j++) {
                int texturePixel = bitmapBuffer[offset1 + j];
                int blue = (texturePixel >> 16) & 0xff;
                int red = (texturePixel << 16) & 0x00ff0000;
                int pixel = (texturePixel & 0xff00ff00) | red | blue;
                bitmapSource[offset2 + j] = pixel;
            }
        }
    } catch (GLException e) {
        Log.e(TAG, "createBitmapFromGLSurface: " + e.getMessage(), e);
        return null;
    }

    return Bitmap.createBitmap(bitmapSource, w, h, Config.ARGB_8888);
}
Run Code Online (Sandbox Code Playgroud)