Camera Api 2 和 OPEN GL ES 使用(显示滤镜效果)

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) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值