Camera Api 2 和 OPEN GL ES 使用(显示滤镜效果)
相机预览和open GL 使用实现滤镜效果
代码 https://github.com/loggerBill/camera

相机预览
1.相机动态权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
android.Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
}
2.打开相机
private void openCamera() {
...
manager.openCamera(cameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreviewSession();
}
...
}
3.创建session和CaptureRequest
private void createCameraPreviewSession() {
...
try {
final CaptureRequest.Builder previewRequestBuilder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewRequestBuilder.addTarget(previewSurface);
cameraDevice.createCaptureSession(
Arrays.asList(previewSurface),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
captureSession = session;
try {
// 设置重复请求
captureSession.setRepeatingRequest(
previewRequestBuilder.build(),
null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
...
}
创建需要告诉相机有那些可以输出的surface,和CaptureRequest 中addTarget surface.
surface 中会带有size。
要是正常使用TextureView 显示预览代码:
public class CameraPreview extends TextureView implements TextureView.SurfaceTextureListener {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
openCamera(width, height);
}
private void openCamera(int width, int height) {
...
texture.setDefaultBufferSize(largest.getWidth(), largest.getHeight());
Surface surface = new Surface(texture);
previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewRequestBuilder.addTarget(surface);
...
}
这样创建surface 并且与Request绑定等待预览上来就会显示到TextureView中。
但我们相实现滤镜效果,TextureView 做不到修改效果。
所以我们用到了GLSurfaceView。
OPENGL
GLSurfaceView
1.创建自定义view 继承自GLSurfaceView。
public class CameraGLSurfaceView extends GLSurfaceView {
private final CameraGLRenderer renderer;
public CameraGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
setEGLContextClientVersion(2); // 使用 OpenGL ES 2.0
renderer = new CameraGLRenderer(context,this);
setRenderer(renderer);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); // 有帧时渲染,需要手动调用requestRender
}
public Surface getSurface() {
return renderer.getSurface();
}
public void setPreviewSize(Size size) {
renderer.setPreviewSize(size);
}
public CameraGLRenderer getRenderer(){
return renderer;
}
}
setEGLContextClientVersion(2); // 使用 OpenGL ES 2.0
- OpenGL ES 2.0 支持可编程渲染管线(使用 GLSL 着色器),而 1.x 是固定管线。
- 2.0 版本提供更灵活的图形控制(如自定义滤镜、特效等),适合相机图像处理。
创建自定义渲染器
- 作用:实例化自定义渲染器
CameraGLRenderer。 - 参数:
context:传递上下文给渲染器(可能用于资源加载)。this:将当前GLSurfaceView实例传给渲染器(便于渲染器与视图交互)。
- 渲染器职责:
- 实现
GLSurfaceView.Renderer接口。 - 重写
onSurfaceCreated(),onSurfaceChanged(),onDrawFrame()方法。 - 处理 OpenGL 初始化、相机帧绘制等逻辑。
- 实现
setRenderer(renderer);
- 作用:将自定义渲染器绑定到
GLSurfaceView。 - 触发行为:
- 系统自动创建 OpenGL ES 上下文和渲染线程。
- 首次调用渲染器的
onSurfaceCreated()和onSurfaceChanged()。 - 启动渲染循环(根据渲染模式触发
onDrawFrame())。
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); // 有帧时渲染
- 作用:设置为 按需渲染 模式(仅在主动请求时重绘)。
- 对比默认模式:
- 默认模式
RENDERMODE_CONTINUOUSLY:连续渲染(60 FPS),浪费资源。 WHEN_DIRTY模式:仅在调用requestRender()时渲染。
- 默认模式
- 适用场景:
- 相机预览:当新帧到达时手动调用
requestRender()。 - 节省 CPU/GPU 资源,避免无效渲染。
- 相机预览:当新帧到达时手动调用
自定义渲染器–>CameraGLRenderer
实现自定义渲染器需要继承GLSurfaceView.Renderer。
public class CameraGLRenderer implements GLSurfaceView.Renderer {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//首次回调 onSurfaceCreated()
// 此处执行一次性初始化操作
// 例如:设置清屏颜色、编译着色器、创建纹理等
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// 响应视图尺寸变化
gl.glViewport(0, 0, width, height); // 必须设置视口
// 可在此处更新投影矩阵等
}
@Override
public void onDrawFrame(GL10 gl) {
// 每帧重复执行
}
}
大致明白渲染器的功能,下面我们来实现预览功能。
1.创建纹理对象。
OpenGL ES 2.0 中生成纹理对象 的标准操作
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
textureId = textures[0];
- 创建一个长度为1的整型数组
textures - 作用:作为容器接收 OpenGL 生成的纹理 ID
- 为什么需要数组:因为
glGenTextures方法需要传入数组来接收生成的纹理 ID(支持一次性生成多个纹理)
2.创建 SurfaceTexture 和 Surface
surfaceTexture = new SurfaceTexture(textureId);
surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
glSurfaceView.requestRender();
}
});
...
if (preViewSize != null)

&spm=1001.2101.3001.5002&articleId=148866491&d=1&t=3&u=9d9e048950e3460387cbf0950f857c7f)
1608

被折叠的 条评论
为什么被折叠?



