问题描述
我通过OpenGL ES 2.0的片段着色器修改了某些图像的亮度,对比度和饱和度.还有...为了保存修改后的图像,我使用了这种方法.
I modified brightness, contrast, and saturation of some image by fragment shader of OpenGL ES 2.0. And... to save modified image, I used this method.
public static Bitmap saveTexture(int texture, int width, int height) {
int[] frame = new int[1];
GLES20.glGenFramebuffers(1, frame, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frame[0]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texture, 0);
ByteBuffer buffer = ByteBuffer.allocate(width * height * 4);
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glDeleteFramebuffers(1, frame, 0);
return bitmap;
}
但是,此方法返回原始图像,未修改.怎么了?请告诉我如何解决此问题.:/
But, this method return the original image, not modified. What is wrong?Please advise me how to resolve this. :/
我添加了更多信息.这段代码是我的GLSurfaceView.Renderer的代码.
I added more information.This code is my GLSurfaceView.Renderer's code.
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
mTextureID = OpenGLTools.loadImageTexture(mBitmap, true);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
mProgram = OpenGLTools.loadProgram(VERTEX_SHADER, FRAGMENT_SHADER);
}
@Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame(GL10 gl10) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
draw();
}
public void draw() {
if (!GLES20.glIsProgram(mProgram)) OpenGLTools.loadProgram(VERTEX_SHADER, FRAGMENT_SHADER);
GLES20.glUseProgram(mProgram);
int positionHandle = GLES20.glGetAttribLocation(mProgram, "position");
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, mVertexBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
int textureCoordinateHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
GLES20.glVertexAttribPointer(textureCoordinateHandle, 2, GLES20.GL_FLOAT, false, 0, mTexCoordBuffer);
GLES20.glEnableVertexAttribArray(textureCoordinateHandle);
int brightness = GLES20.glGetUniformLocation(mProgram, "brightness");
GLES20.glUniform1f(brightness, mEditParams.mBrightness / 200.0f);
int contrast = GLES20.glGetUniformLocation(mProgram, "contrast");
GLES20.glUniform1f(contrast, mEditParams.mContrast / 200.0f);
int saturation = GLES20.glGetUniformLocation(mProgram, "saturation");
GLES20.glUniform1f(saturation, (mEditParams.mSaturation + 100) / 100.0f);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer);
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(textureCoordinateHandle);
}
public Bitmap getBitmap() {
return OpenGLTools.saveTexture(mTextureID, mBitmap.getWidth(), mBitmap.getHeight());
}
而且...这是OpenGLTools类中的代码.
And... this is the code in OpenGLTools class.
public static int loadImageTexture(final Bitmap bitmap, final boolean recycle) {
int[] textureNames = new int[1];
GLES20.glGenTextures(1, textureNames, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureNames[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
if (recycle) {
bitmap.recycle();
}
return textureNames[0];
}
public static int loadProgram(final String vsc, final String fsc) {
int[] success = new int[1];
int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vshader, vsc);
GLES20.glCompileShader(vshader);
GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, success, 0);
if (success[0] == 0) {
Log.e("CheckLog", "Could not compile vertex shader : " + GLES20.glGetShaderInfoLog(vshader));
GLES20.glDeleteShader(vshader);
return 0;
}
int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fshader, fsc);
GLES20.glCompileShader(fshader);
GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, success, 0);
if (success[0] == 0) {
Log.e("CheckLog", "Could not compile fragment shader : " + GLES20.glGetShaderInfoLog(fshader));
GLES20.glDeleteShader(fshader);
return 0;
}
int program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vshader);
GLES20.glAttachShader(program, fshader);
GLES20.glLinkProgram(program);
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, success, 0);
if (success[0] <= 0) {
Log.e("CheckLog", "Could not link OpenGLES program :" + GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
return 0;
} else {
Log.i("CheckLog", "Linked OpenGLES program");
}
return program;
}
public static Bitmap saveTexture(int texture, int width, int height) {
int[] frame = new int[1];
GLES20.glGenFramebuffers(1, frame, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frame[0]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texture, 0);
ByteBuffer buffer = ByteBuffer.allocate(width * height * 4);
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glDeleteFramebuffers(1, frame, 0);
return bitmap;
}
如果我触摸保存"按钮,则会在OpenGLES上下文中调用 getBitmap
方法.我可以更改 Bitmap
的参数(亮度,对比度和饱和度),并实时显示在显示屏上.但是,当我触摸保存按钮时,更改的参数不会应用到保存的图像.我想使用更改后的参数保存图像.
If I touch save button, getBitmap
method is called in the OpenGLES context. I can change the Bitmap
's parameters(brightness, contrast and saturation) and it shows up on display in real time. However, changed parameters are not applied the saved image when I touch the save button. I want to save the image with changed parameters.
推荐答案
您要将原始纹理句柄作为输入 saveTexture()
的 texture
参数传递,因此毫不奇怪,这就是您要保存回磁盘的数据.
You're passing the original texture handle as the texture
parameter input into saveTexture()
, so it's no surprise that that is the data you are saving back to disk.
您实际上并不想保存纹理-您想要保存活动帧缓冲区的内容-因此该功能不是您的代码所需要的.试试这个:
You don't actually want to save a texture - you want to save the contents of the active framebuffer - so that function isn't what your code needs. Try this one:
public static Bitmap saveTexture(int width, int height) {
ByteBuffer buffer = ByteBuffer.allocate(width * height * 4);
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
return bitmap;
}
这篇关于如何获得“渲染"?调用glDrawElements之后从FrameBuffer用glReadPixels生成图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!