将2D纹理保存到Android OpenGL ES中的png

时间:2022-01-13 03:04:12

I am new to OpenGL ES in Android. But right now, I need to use OpenGL ES 2.0 to do some photo editing. I found the sample code "Hello-effect" in Android 4.1.2, it complete the work of editing the photo and render it to a window. But right now, I also need to save the edited photo to a local bitmap. I think there maybe some way to get data directly from texture, but the only method I found is glReadPixels(...). So I do some try to use it:

我是Android中OpenGL ES的新手。但是现在,我需要使用OpenGL ES 2.0进行一些照片编辑。我在Android 4.1.2中找到了示例代码“Hello-effect”,它完成了编辑照片并将其渲染到窗口的工作。但是现在,我还需要将编辑过的照片保存到本地位图。我想可能有一些方法可以直接从纹理中获取数据,但我找到的唯一方法是glReadPixels(...)。所以我尝试使用它:

The first test I do:

我做的第一个测试:

  1. I use GLSurfaceView to show the photo that has been edited by android.media.effect API.
  2. 我使用GLSurfaceView显示android.media.effect API编辑的照片。
  3. I add a button in the same layout containing the GLSurfaceView.
  4. 我在包含GLSurfaceView的相同布局中添加了一个按钮。
  5. When click the button, I call glReadPixels(...) to get the photo data. But as the step 3 I only got the botton's data.
  6. 单击按钮时,我调用glReadPixels(...)来获取照片数据。但是作为第3步,我只得到了botton的数据。
I guess that when I click the button the windows' framebuffer has been replaced by the button's content.

The second test I do:

我做的第二个测试:

  1. I create a FBO to save the edited photo and use glReadPixels(...) to get the photo data, but it is a black pic.
  2. 我创建了一个FBO来保存编辑过的照片并使用glReadPixels(...)来获取照片数据,但这是一张黑色照片。

The code looks like this:

代码如下所示:

public void renderTextureOffscreen (int texId) {
    // Bind default FBO
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, offScreenFrameBuffer[0]); 
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,GLES20.GL_COLOR_ATTACHMENT0,GLES20.GL_TEXTURE_2D, texId , 0);

    int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
    if(status == GLES20.GL_FRAMEBUFFER_COMPLETE)
    {
        // Set viewport
        GLES20.glViewport(0, 0, mViewWidth, mViewHeight);
        GLToolbox.checkGlError("glViewport");

        // Disable blending
        GLES20.glDisable(GLES20.GL_BLEND);

        // Set the vertex attributes
        GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false,
            0, mTexVertices);
        GLES20.glEnableVertexAttribArray(mTexCoordHandle);
        GLES20.glVertexAttribPointer(mPosCoordHandle, 2, GLES20.GL_FLOAT, false,
            0, mPosVertices);
        GLES20.glEnableVertexAttribArray(mPosCoordHandle);
        GLToolbox.checkGlError("vertex attribute setup");

        // Set the input texture
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLToolbox.checkGlError("glActiveTexture");
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
        GLToolbox.checkGlError("glBindTexture");
        GLES20.glUniform1i(mTexSamplerHandle, 0);

        // Draw
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    }

My question is that whether my guess is right? And as the FBO method, do I lose some critical step to finish my job.

我的问题是我的猜测是否正确?作为FBO方法,我是否会失去一些关键步骤来完成我的工作。

1 个解决方案

#1


0  

Try reading pixels right after

尝试读取像素

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 

Also make sure that glReadPixels is called from the right thread, i.e. in your renderer subclass.

还要确保从右侧线程调用glReadPixels,即在渲染器子类中调用。

And another thing, i see that you are binding the texture used for the FBO as input to the shader, you cannot do that.

另一件事,我看到你绑定用于FBO的纹理作为着色器的输入,你不能这样做。

I suppose that after RTT, you are rendering the result to a quad or something on screen is that right ?

我想在RTT之后,你将结果渲染到四边形或屏幕上的东西是对的吗?

Can you show the rest of the code that you are using to read the pixels ?

你能展示你用来读取像素的其余代码吗?

#1


0  

Try reading pixels right after

尝试读取像素

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 

Also make sure that glReadPixels is called from the right thread, i.e. in your renderer subclass.

还要确保从右侧线程调用glReadPixels,即在渲染器子类中调用。

And another thing, i see that you are binding the texture used for the FBO as input to the shader, you cannot do that.

另一件事,我看到你绑定用于FBO的纹理作为着色器的输入,你不能这样做。

I suppose that after RTT, you are rendering the result to a quad or something on screen is that right ?

我想在RTT之后,你将结果渲染到四边形或屏幕上的东西是对的吗?

Can you show the rest of the code that you are using to read the pixels ?

你能展示你用来读取像素的其余代码吗?