在 Android 中创建位图之前从 Bytebuffer 翻转 openGL 纹理

Lau*_*ent 4 android opengl-es bitmap grafika

我正在使用依赖于 Google 的 Grafika 存储库的实时流 API。我使用 Grafika EGLSurfaceBase 的 saveFrame 方法来允许用户在流式传输时捕获视频的静态图像。

https://github.com/google/grafika/blob/master/src/com/android/grafika/gles/EglSurfaceBase.java

实际捕获有效,但显然在某些相机方向上图像会翻转。

我发现了很多与从 OpenGL 纹理获取的倒置位图相关的问题 - 但大多数似乎是指绘制的图像并依赖于:

a) 在 OpenG 中翻转纹理。但就我而言,我正在使用实时流 API,因此翻转纹理来捕获图像实际上可能也会翻转视频流上的图像捕获。

或者

b) 在基于资源生成位图后翻转位图。就我而言,我没有资源,我正在从字节缓冲区创建位图,并且不想复制它来翻转它。

这是 API 具有的基本 EGLSurfaceBase 方法 - 我将把相机方向传递给它,但我的问题是:

        String filename = file.toString();

    int width = getWidth();
    int height = getHeight();
    ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
    buf.order(ByteOrder.LITTLE_ENDIAN);
    GLES20.glReadPixels(0, 0, width, height,
            GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);
    GlUtil.checkGlError("glReadPixels");
    buf.rewind();

    BufferedOutputStream bos = null;
    try {
        bos = new BufferedOutputStream(new FileOutputStream(filename));
        Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bmp.copyPixelsFromBuffer(buf);
        bmp.compress(Bitmap.CompressFormat.PNG, 90, bos);
        bmp.recycle();
    } finally {
        if (bos != null) bos.close();
    }
    Log.d(TAG, "Saved " + width + "x" + height + " frame as '" + filename + "'");
}
Run Code Online (Sandbox Code Playgroud)

我的首选解决方案是找到一种在 BMP.createbitmap 之前(或同时)翻转图像的方法。例如,我可以使用矩阵来翻转 glReadPixels 对像素的读取吗?

另一个注释/想法:也许创建后翻转位图的成本微不足道,因为这依赖于用户交互,所以它不会经常发生而导致内存错误?

dra*_*fly 8

您可以在 glReadPixels 之后反转 ByteBuffer。它非常快,因为它只是内存复制。我的测试表明反向操作花费了不到10ms。

这是一个没问题的实现:

    private void reverseBuf(ByteBuffer buf, int width, int height)
{
    long ts = System.currentTimeMillis();
    int i = 0;
    byte[] tmp = new byte[width * 4];
    while (i++ < height / 2)
    {
        buf.get(tmp);
        System.arraycopy(buf.array(), buf.limit() - buf.position(), buf.array(), buf.position() - width * 4, width * 4);
        System.arraycopy(tmp, 0, buf.array(), buf.limit() - buf.position(), width * 4);
    }
    buf.rewind();
    Log.d(TAG, "reverseBuf took " + (System.currentTimeMillis() - ts) + "ms");
}
Run Code Online (Sandbox Code Playgroud)