OpenGL ES 实现bitmap组合滤镜渲染生成图片可以点击连接查看
下面介绍直接从EGLContext上下文中获取当前渲染的图片数据然后保存为图片。
其实很简单我们在渲染的时候每次都是在GLSurfaceView.Renderer接口中的
这个方法中去处理自己的数据渲染,这里使用的是GLSurfaceView已经自己初始化并处理了Opengl es环境可以直接使用。如果不使用GLSurfaceView也可以,自己在新的线程中单独的初始化OpenGL ES 环境,具体代码可以参考GLSurfaceView,网上也很多这介绍的教程这里不多说。
因为每一帧都会回调onDrawFrame(GL10 gl)这个方法,那么做滤镜处理也是在这里完成的,这样我们就可以直接在这里渲染完之后直接回去当前帧数据保存就能得到渲染后的图片了,比之前在bitmap上去渲染是不是方便很多了。
这里有两种方式获取bitmap
方式一
if(isTakePicture){
int width = getWidth();
int height = getHeight();
GLES20.glViewport(0,0,width,height);
IntBuffer ib = IntBuffer.allocate(width * height);
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, ib);
Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
result.copyPixelsFromBuffer(IntBuffer.wrap(ib.array()));
new SavePictureTask(getOutputMediaFile(),null).execute(result);
isTakePicture = false;
}
方式二
private Bitmap createBitmapFromGLSurface(int x, int y, int w, int h, GL10 gl)
throws OutOfMemoryError {
if(gl == null) return null;
int bitmapBuffer[] = new int[w * h];
int bitmapSource[] = new int[w * h];
IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer);
intBuffer.position(0);
try {
gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, intBuffer);
int offset1, offset2;
for (int i = 0; i < h; i++) {
offset1 = i * w;
offset2 = (h - i - 1) * w;
for (int j = 0; j < w; j++) {
int texturePixel = bitmapBuffer[offset1 + j];
int blue = (texturePixel >> 16) & 0xff;
int red = (texturePixel << 16) & 0x00ff0000;
int pixel = (texturePixel & 0xff00ff00) | red | blue;
bitmapSource[offset2 + j] = pixel;
}
}
} catch (GLException e) {
return null;
}
return Bitmap.createBitmap(bitmapSource, w, h, Bitmap.Config.ARGB_8888);
}
这两种方式读取数据都是通过
gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, intBuffer);
这个来读取的图像数据到缓冲区的,方式一拍照的图像会颠倒过来,需要进一步旋转处理,方式二直接对图像旋转后创建新的bitmap保存,显示正常。