Android.Camera2相机超详细讲解

    xiaoxiao2021-03-25  60

    Android.Camera2相机超详细讲解

    在API21中Google就发布了Camera2类来取代Camera类,那么这个Camera2类到底改变了那些地方呢,我们来看官方的说法:

    Camera2 API

    Supports 30fps full resolution with burst mode 支持30fps的全高清连拍Supports change on manual camera settings between frame capture 支持帧之间的手动设置Supports RAW image capture 支持RAW格式的图片拍摄 Supports Zero Shutter Lag & Movie Snapshot 支持快门0延迟以及电影速拍Supports setting other manual camera device controls including level of Noise Cancelling  支持相机其他方面的手动控制包括噪音消除的级别 

    还有部分新功能没有列出

    查看了一下API,发现Camera2相对于Camera类架构都改变了,所以代码肯定是不通用的了,相比之前的代码应该算是比较难了一点了。

    先来看看camera2包架构示意图: 

    Google采用了pipeline(管道)的概念,将Camera Device相机设备和Android Device安卓设备连接起来, Android Device通过管道发送CaptureRequest拍照请求给Camera Device,Camera Device通过管道返回CameraMetadata数据给Android Device,这一切建立在一个叫作CameraCaptureSession的会话中。

    下面是camera2包中的主要类:  其中CameraManager是所有相机设备(CameraDevice)的管理者,而每个CameraDevice自己会负责建立CameraCaptureSession以及建立CaptureRequest。CameraCharacteristics是CameraDevice的属性描述类,在CameraCharacteristics中可以进行相机设备功能的详细设定(当然了,首先你得确定你的相机设备支持这些功能才行)。

    类图中有着三个重要的callback,其中CameraCaptureSession.CaptureCallback将处理预览和拍照图片的工作,需要重点对待。

    这些类是如何相互配合的?下面是简单的流程图:

    可以看出调用openCamera方法后会回调CameraDevice.StateCallback这个方法,在该方法里重写onOpened函数。在onOpened方法中调用createCaptureSession,该方法又回调CameraCaptureSession.StateCallback方法。在CameraCaptureSession.StateCallback中重写onConfigured方法,设置setRepeatingRequest方法(也就是开启预览了)。setRepeatingRequest又会回调 CameraCaptureSession.CaptureCallback方法。重写CameraCaptureSession.CaptureCallback中的 onCaptureCompleted方法,result就是未经过处理的元数据了。

    顺便提一下onCaptureProgressed方法很明显是在Capture过程中的,也就是在onCaptureCompleted之前,所以,在这之前相对图像干什么就看你的了,像美颜等操作就可以在这个方法中实现了。

    可以看出Camera2相机使用的逻辑还是比较简单的,其实就是3个Callback函数的回调,先说一下:setRepeatingRequest和capture方法其实都是向相机设备发送获取图像的请求,但是capture就获取那么一次,而setRepeatingRequest就是不停的获取图像数据,所以呢,使用capture就想拍照一样,图像就停在那里了,但是setRepeatingRequest一直在发送和获取,所以需要连拍的时候就调用它,然后在onCaptureCompleted中保存图像就行了。(注意了,图像的预览也是用的setRepeatingRequest,只是你不处理数据就行了)

    下面贴出代码,我用的TextureView来显示图像:

    首先权限不能忘: <uses-permission android:name="android.permission.CAMERA"/>

    布局:

    <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextureView android:id="@+id/textureview" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout> 12345678910 12345678910 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mThreadHandler = new HandlerThread("CAMERA2"); mThreadHandler.start(); mHandler = new Handler(mThreadHandler.getLooper()); mPreviewView = (TextureView) findViewById(R.id.textureview); mPreviewView.setSurfaceTextureListener(this); } @SuppressWarnings("ResourceType") @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { CameraManager cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE); try { String[] CameraIdList = cameraManager.getCameraIdList(); //获取可用相机设备列表 CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(CameraIdList[0]); //在这里可以通过CameraCharacteristics设置相机的功能,当然必须检查是否支持 characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL); //就像这样 cameraManager.openCamera(CameraIdList[0], mCameraDeviceStateCallback, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {} @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { return false; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) {} private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { try { startPreview(camera); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onDisconnected(CameraDevice camera) {} @Override public void onError(CameraDevice camera, int error) {} }; private void startPreview(CameraDevice camera) throws CameraAccessException { SurfaceTexture texture = mPreviewView.getSurfaceTexture(); texture.setDefaultBufferSize(mPreviewView.getWidth(), mPreviewView.getHeight()); Surface surface = new Surface(texture); try { mPreviewBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); } catch (CameraAccessException e) { e.printStackTrace(); } mPreviewBuilder.addTarget(surface); camera.createCaptureSession(Arrays.asList(surface), mSessionStateCallback, mHandler); } private CameraCaptureSession.StateCallback mSessionStateCallback = new CameraCaptureSession.StateCallback() { @Override public void onConfigured(CameraCaptureSession session) { try { //session.capture(mPreviewBuilder.build(), mSessionCaptureCallback, mHandler); session.setRepeatingRequest(mPreviewBuilder.build(), mSessionCaptureCallback, mHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(CameraCaptureSession session) {} }; private CameraCaptureSession.CaptureCallback mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {} @Override public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult){}}; } 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798

    如需按键,就加一个Button,写上

    mSession.setRepeatingRequest(mPreviewBuilder.build(), mSessionCaptureCallback, mHandler); 或者 session.capture(mPreviewBuilder.build(), mSessionCaptureCallback, mHandler);就可以了 123 123

    其实过程还是挺简单的,主要是逻辑比较简单,就是不停的Callback,然后在onCaptureCompleted中处理数据就行了。

    转载请注明原文地址: https://ju.6miu.com/read-35789.html

    最新回复(0)