使用Camera2和GLsurface实现相机预览

本文介绍了使用Camera2 API和OpenGL ES实现相机预览的方法。通过CameraManager获取摄像头特性,创建CameraDevice和CameraCaptureSession,利用Surface进行预览。在预览过程中,使用OpenGL ES进行图像绘制。文章还提到了关键概念如SurfaceTexture、纹理绑定以及CameraCharacteristics中的重要参数。并分享了一个开源项目链接作为参考。
摘要由CSDN通过智能技术生成

之前有用过旧版的Camera实现相机预览,可是很多东西不好控制,而且旧版的camera现在以被弃用,所以使用Camera2来进行项目的开发。

先看效果:

这里写图片描述

camera2是为连接Android相机的接口。

这里写图片描述

这里引用了管道的概念将安卓设备和摄像头之间联通起来,系统向摄像头发送Capture请求,而摄像头返回CameraMetadata。在一切建立在一个叫做CameraCaptureSession的会话中。

Camera2支持RAW输出,可以调节曝光,对焦模式,快门等。

这里写图片描述

  • CameraManager:摄像头管理器,用于检测摄像头,打开系统摄像头,调用CameraManager.getCameraCharacteristics(String)可以获取指定摄像头的相关特性
  • CameraCharacteristics 摄像头的特性
  • CameraDevice 摄像头,类似android.hardware.Camera也就是Camera1的Camera
  • CameraCaptureSession 这个对象控制摄像头的预览或者拍照,setRepeatingRequest()开启预览,capture()拍照,CameraCaptureSession提供了StateCallback、CaptureCallback两个接口来监听CameraCaptureSession的创建和拍照过程。
  • CameraRequest和CameraRequest.Builder,预览或者拍照时,都需要一个CameraRequest对象。CameraRequest表示一次捕获请求,用来对z照片的各种参数设置,比如对焦模式、曝光模式等。CameraRequest.Builder用来生成CameraRequest对象。
预览的基本思想

在这里,我使用的是OpenGL ES,用摄像头获取的图像,调用OpenGL ES的库进行绘制。

摄像头:

Camera2使用的是Surface来进行预览,这个surface包括:SurfaceView, SurfaceTexture ( Surface(SurfaceTexture))

关于各个surface的区别可以参考:https://blog.csdn.net/jinzhuojun/article/details/44062175

主要思路

  1. 获得摄像头管理器 mCameraManagermCameraManager.openCamera()来打开摄像头
  2. 指定要打开的摄像头,并创建openCamera()所需要的CameraDevice.StateCallback stateCallback
  3. CameraDevice.StateCallback stateCallback中调用createPreview(),这个方法中,使用CaptureRequest.Builder创建预览需要的CameraRequest,并初始化了CameraCaptureSession
  4. CameraCaptureSession的回调中,最后调用了setRepeatingRequest(previewRequest, null, null)进行了预览

Camera代码:

public class CameraHelper  {
   

    private Context mContext;
    private CameraManager mCameraManager;
    private CameraDevice mCameraDevice;
    private String mCameraId = null;
    private boolean mFlashSupport = false;
    private Surface mSurface;
    private CaptureRequest.Builder mPreviewBuilder;

    private android.os.Handler mMainHandler;
    private android.os.Handler mChildHanlder;

    private static final String TAG = "CameraHelper";


    public CameraHelper(Context context, SurfaceTexture surfaceTexture){

        mContext = context;
        Display display = ((WindowManager)context
                .getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        DisplayMetrics metrics = new DisplayMetrics();
        display.getMetrics(metrics);
        int screenWidth = metrics.widthPixels;
        int screenHidth = metrics.heightPixels;

        //设置图像像素比位4:3
        surfaceTexture.
                setDefaultBufferSize(4*screenWidth/3,3 * screenWidth / 4);
        mSurface = new Surface(surfaceTexture);
        initCamera();
    }

    private void initCamera(){

        //得到CameraManager
        mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
        try {
            for(String id : mCameraManager.getCameraIdList()){

                CameraCharacteristics characteristics
                        = mCameraManager.getCameraCharacteristics(id);
                Integer front = cha
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
使用Camera2 Api实现相机预览需要以下步骤: 1. 实现CameraDevice.StateCallback接口,当相机设备状态发生变化时会回调该接口。 2. 获取相机管理器,并申请相机权限。 3. 打开相机,并设置预览Surface相机回调。 4. 获取预览数据,进行相应的渲染和处理。 以下是示例代码: ```java public class CameraPreviewActivity extends AppCompatActivity implements SurfaceHolder.Callback, CameraDevice.StateCallback { private CameraManager mCameraManager; private String mCameraId; private CameraDevice mCameraDevice; private CameraCaptureSession mCaptureSession; private SurfaceHolder mSurfaceHolder; private Size mPreviewSize; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera_preview); SurfaceView surfaceView = findViewById(R.id.surface_view); mSurfaceHolder = surfaceView.getHolder(); mSurfaceHolder.addCallback(this); mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { mCameraId = mCameraManager.getCameraIdList()[0]; } catch (CameraAccessException e) { e.printStackTrace(); } if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1); } else { openCamera(); } } private void openCamera() { try { mCameraManager.openCamera(mCameraId, this, null); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onOpened(CameraDevice camera) { mCameraDevice = camera; try { List<Surface> surfaces = new ArrayList<>(); // 设置预览Surface Surface previewSurface = mSurfaceHolder.getSurface(); surfaces.add(previewSurface); // 创建相机会话 mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(CameraCaptureSession session) { mCaptureSession = session; startPreview(); } @Override public void onConfigureFailed(CameraCaptureSession session) { Log.e("CameraPreview", "createCaptureSession failed"); } }, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private void startPreview() { try { // 创建预览请求 CaptureRequest.Builder previewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); previewBuilder.addTarget(mSurfaceHolder.getSurface()); //设置自动对焦模式 previewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // 开始预览 mCaptureSession.setRepeatingRequest(previewBuilder.build(), null, null); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onSurfaceCreated(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 获取预览大小 try { CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(mCameraId); StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); mPreviewSize = map.getOutputSizes(SurfaceHolder.class)[0]; // 更新Surface大小 int rotatedPreviewWidth = width; int rotatedPreviewHeight = height; int maxWidth = mSurfaceHolder.getSurfaceFrame().width(); int maxHeight = mSurfaceHolder.getSurfaceFrame().height(); if (maxWidth > 0 && maxHeight > 0) { rotatedPreviewWidth = Math.min(maxWidth, maxHeight); rotatedPreviewHeight = Math.max(maxWidth, maxHeight); } mSurfaceHolder.setFixedSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { mCameraDevice.close(); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == 1) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { openCamera(); } else { Toast.makeText(this, "Camera permission not granted", Toast.LENGTH_SHORT).show(); } } } @Override public void onDisconnected(CameraDevice camera) { mCameraDevice.close(); } @Override public void onError(CameraDevice camera, int error) { mCameraDevice.close(); mCameraDevice = null; } } ``` 在AndroidManifest.xml中添加相机权限: ```xml <uses-feature android:name="android.hardware.camera" /> <uses-permission android:name="android.permission.CAMERA" /> ``` 在布局文件中添加SurfaceView: ```xml <SurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" /> ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值