繁体   English   中英

在Android中使用Open GL Framebuffer时如何变换图像

[英]How do I transform an image when using Open GL Framebuffer in Android

我正在使用一个名为Cine.io的实时流媒体库将流中的帧保存到Android的外部存储中。

该库本身使用Google的Grafika资源。

当我简单地设置一个ByteBuffer,然后使用GLReadPixel读取它时,图像将正确保存,但由于GL图像具有BMP坐标的反向坐标,因此图像被反转了。

为了解决此问题,我认为最有效的解决方案是使用开放的GL帧缓冲区来渲染传入的帧,使用正交矩阵翻转它,然后使用GLReadPixel读取它以将其保存到磁盘。

我相信这是可以实现此目标的代码:

   int width = getWidth();
    int height = getHeight();
    ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
    buf.order(ByteOrder.LITTLE_ENDIAN);


    int[] fboId = new int[1];
    int[] rendId = new int[1];
    float[] projMatrix = new float[16];

    GLES20.glGenFramebuffers(1, fboId, 0);
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId[0]);

         GLES20.glGenRenderbuffers(1, rendId, 0);
    GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, rendId[0]);
    GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,GLES20.GL_RGBA4, width, height);


    switch(GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER)){
        case GLES20.GL_FRAMEBUFFER_COMPLETE:
            Log.i(TAG, "Is Complete");
            break;
        case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
            Log.i(TAG, "Incomplete Attachment");
            break;
        case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
            Log.i(TAG, "Missing Attachment");
            break;
        default: Log.i(TAG, "Something else is going on");

    }
    GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_RENDERBUFFER,rendId[0] );
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId[0]);
    GLES20.glViewport(0,0,width, height);
    android.opengl.Matrix.orthoM(projMatrix, 0, 0, width, height, 0, -1, 1);


  GLES20.glReadPixels(0, 0, width, height,
            GLES20.GL_RGBA4, GLES20.GL_UNSIGNED_BYTE, buf);

    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);




    GlUtil.checkGlError("glReadPixels");
    buf.rewind();

但是,该代码只是生成一个空白图像文件,该文件为空(大小为3.6kb)。 此外,变量“ buff”的块在调用GLreadpixels方法后仅包含0。

最后,如果我将BindFramebuffer设置为0(默认绑定)并将其放置在GLReadPixels调用之前,则图像会显示出来但仍然反转-就像Framebuffer命令从未与之交互。

我该如何解决?

PS:很多人都在尝试回答下面这个问题的先前版本,但是这个问题仍然很棘手。

您始终可以手动翻转缓冲区。 我尚未使用Java的ByteBuffer因此以下代码可能无法正常工作,但主要只是作为示例。

//num channels being the amount of channels per pixel, 4 representing r, g, b, a
int num_channels = 4;
//allocate buffer size
ByteBuffer new_buf = ByteBuffer.allocateDirect(width * height * num_channels);
buf.order(ByteOrder.LITTLE_ENDIAN);

//calculate row size of image
int row_size = width * num_channels
//loop through the contents of the buffer and flip it
for (int y = 0; y < height; ++y) {
    for (int x = 0; x < row_size; ++x) {
        //put a row of bytes starting from the end of the buffer into the start of the new buffer
        new_buf.put(buf.get(((height - (y + 1)) - x) * row_size));
    }
}

但是,这非常慢,在更新循环中绝对不理想。 相反,在渲染代码中,您可以更改使用矩阵将纹理投影到屏幕上的方式。 尝试像这样使用glOrtho

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, window_width, window_height, 0.0f, -1.0f, 1.0f);

渲染时应该翻转纹理。 尝试进行实验并弄乱不同的值以获得一种感觉。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM