GLES20.glReadPixel太慢了

时间:2017-05-22 22:10:31

标签: android opencv opengl-es vuforia opentok

这是一个老问题,但我想回复一段代码。

以下对于实时来说太慢了。我打算稍后使用它与OpenTOK屏幕共享。任何快速替代?

ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
bb.order(ByteOrder.nativeOrder());
GLES20.glReadPixels(0, 0, width, height, GL_RGBA,
        GL10.GL_UNSIGNED_BYTE, bb);

int pixelsBuffer[] = new int[screenshotSize];
bb.asIntBuffer().get(pixelsBuffer);
final Bitmap bitmap = Bitmap.createBitmap(width, height,
        Bitmap.Config.RGB_565);
bitmap.setPixels(pixelsBuffer, screenshotSize - width, -width,
        0, 0, width, height);
pixelsBuffer = null;

short sBuffer[] = new short[screenshotSize];
ShortBuffer sb = ShortBuffer.wrap(sBuffer);
bitmap.copyPixelsToBuffer(sb);

for (int i = 0; i < screenshotSize; ++i) {
    short v = sBuffer[i];
    sBuffer[i] = (short) (((v & 0x1f) << 11) | (v & 0x7e0) | ((v & 0xf800) >> 11));
}
sb.rewind();
bitmap.copyPixelsFromBuffer(sb);

PS:我已经尝试了GL_RGB和GL_BGRA,但它仍然很慢,我只是黑屏。

1 个答案:

答案 0 :(得分:0)

首先,glReadPixels并不是导致代码速度变慢的原因。所有缓冲区的分配和将图像转换为另一种格式都是。

重用缓冲区。分配一次并重复使用它们。

ByteBuffer bb = ByteBuffer.allocateDirect(screenshotSize * 4);
bb.order(ByteOrder.nativeOrder());

这个位没问题。

GLES20.glReadPixels(0, 0, width, height, GL_RGBA,
        GL10.GL_UNSIGNED_BYTE, bb);

现在您正准备转换为另一种具有大量开销的格式。坚持使用您收到的格式。而且,您再次分配缓冲区而不是重用。

但是,Bitmap可以分配一次并重复使用。

int pixelsBuffer[] = new int[screenshotSize];
bb.asIntBuffer().get(pixelsBuffer);
final Bitmap bitmap = Bitmap.createBitmap(width, height,
        Bitmap.Config.RGB_565);
bitmap.setPixels(pixelsBuffer, screenshotSize - width, -width,
        0, 0, width, height);
pixelsBuffer = null;

short sBuffer[] = new short[screenshotSize];
ShortBuffer sb = ShortBuffer.wrap(sBuffer);
bitmap.copyPixelsToBuffer(sb);

然后你不需要这种不必要的转换。

for (int i = 0; i < screenshotSize; ++i) {
    short v = sBuffer[i];
    sBuffer[i] = (short) (((v & 0x1f) << 11) | (v & 0x7e0) | ((v & 0xf800) >> 11));
}

只要您的Bitmap格式相同,就可以使用copyPixelsFromBuffer()。

bitmap.copyPixelsFromBuffer(bb);

通常,Android位图与GL_RGBA的格式相同,因此您不太可能需要转换。以上内容将所有内容简化为只读和复制。