我通过OpenGL ES 2.0的片段着色器修改了某些图像的亮度,对比度和饱和度。并且......为了保存修改后的图像,我使用了这种方法。
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;
}
但是,此方法返回原始图像,而不是修改。怎么了? 请告诉我如何解决这个问题。 :/
我添加了更多信息。 这段代码是我的GLSurfaceView.Renderer的代码。
@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类中的代码。
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
的参数(亮度,对比度和饱和度),它会实时显示。但是,当我触摸保存按钮时,更改的参数不会应用于保存的图像。我想用更改的参数保存图像。
答案 0 :(得分:0)
您将原始纹理句柄作为texture
参数输入到saveTexture()
,因此毫不奇怪这是您要保存回磁盘的数据。
您实际上并不想保存纹理 - 您希望保存活动帧缓冲区的内容 - 因此该功能不是您的代码所需的功能。试试这个:
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;
}