Android Camera1小结

1.概述

本文将仿照此前博文Android NDK Camera2小结的方式,来记录Camera1的使用。

Camera1仅为Java实现(不必纠结于此,Native实现...JNI反调...你懂的~且性能差别不大)。

本文的讲解基于UML Component图,描述Camera1核心对象及API的调用生成关系。如缩略图不清晰,可点击放大。

Component图中,模块为函数,节点为对象。横向(左或右)箭头为资源释放操作调用。调用过程与顺序/时机无关。

其中绿色模块为Camera对象成员方法,黄色为Camera类静态方法。

粉色为Camera.Parameters对象成员方法。

红色为自定义方法,需要自行实现。

Component图未包含所有接口,仅为Camera1预览模式的简单实现。

2.Camera1的使用

相比于Camera2的复杂架构,Camera1(android.hardware.Camera)十分简单,仅为一个类文件。因此,操作也即为简便。

遵循以下步骤便可完成预览。

2.1获取Camera数量

使用静态方法Camera.getNumberOfCameras,获取camera数量num。Camera ID范围为【0,num-1】。

int cameraCount = Camera.getNumberOfCameras();

2.2获取CameraInfo

以Camera ID作为传参,调用静态方法Camera.getCameraInfo,获取对应CameraInfo。CameraInfo仅包括三项,Facing(镜头方向,前置/后置),orientation(镜头旋转角度)和canDisableShutterSound(是否支持取消快门声音)。

通常通过CameraInfo,来确定要使用的Camera。

for (int i = 0; i < cameraCount; i++) {
            Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
            Camera.getCameraInfo(i, cameraInfo);
}

2.3开启Camera

以Camera ID作为传参,调用静态方法Camera.open即可打开设备,该方法将返回一个Camera对象。但打开设备,并不代表能够看到画面。仍需要后续操作,来完成预览。包括设置Camera.Parameters,以及画布(surface View)。若需要使用图片数据,则需要设置Callback接口。

Camera camera = Camera.open(cameraId);

2.4设置Camera配置参数

获取Camera对象后,调用成员方法getParameters,可以获取Camera.Parameters。Camera.Parameters中包含的信息,要远多于CameraInfo。在获取Camera.Parameters后,可以调用成员方法getSupportedXXXX来获取相应的数据。例如分辨率,预览格式等。

对于分辨率,可以调用Camera.Parameters成员方法getSupportedPreviewSizes,获取List<Camera.Size>。设置则是调用Camera.Parameters成员方法setPreviewSize。

Camera.Parameters params = camera.getParameters();
List<Camera.Size> supportSizes = params.getSupportedPreviewSizes();
...
mParams.setPreviewSize(width, height);

对于预览格式,可以调用Camera.Parameters成员方法getSupportedPreviewFormats,获取List<Integer>。设置则是调用setPreviewFormat。由于前端为视频流,因此,通常使用PixelFormat.YCbCr_420_SP。

parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP);

当然,还有其它一些参数可以设置,例如曝光补偿(可参照关于Android Camera的曝光补偿),焦距(可参照关于Android Camera变焦)等。

List<Integer> zoomRatios =parameters.getZoomRatios();
int MAX_ZOOM = mParams.getMaxZoom();
int tMaxExposure=parameters.getMaxExposureCompensation();
int tMinExposure=parameters.getMinExposureCompensation();
...
mParams.setZoom(currentZoom);
parameters.setExposureCompensation(mExposureCompensationRate);

在设置完Camera.Parameters子项后,需要将其回填给Camera,需要调用Camera成员方法setParameters。

mCamera.setParameters(mParams);

2.5设置预览界面

surface view为Camera的画布,仅需将其SurfaceHolder作为传参,调用Camera的成员方法setPreviewDisplay即可完成预览界面设置。

SurfaceHolder holder;
...
mCamera.setPreviewDisplay(holder);

2.6预览画面矫正

通过用Camera的成员方法setDisplayOrientation调设置画面的矫正角度,使得画面以自然0度显示在画布上。通常使用角度为0,90,180,270。关于android设备的角度问题,将另辟博文描述。

mCamera.setDisplayOrientation(90);

2.7设置previewCallback

如果想获取图像数据,则需要通过调用Camera的成员方法setPreviewCallback添加Callback方法。默认返回为YCbCr_420_SP格式的数据。

PreviewCallback mpreview = new PreviewCallback() {
        public void onPreviewFrame(byte[] data, Camera camera) {

        }
    };
mCamera.setPreviewCallback(mpreview);
    public interface PreviewCallback
    {
        /**
         * Called as preview frames are displayed.  This callback is invoked
         * on the event thread {@link #open(int)} was called from.
         *
         * <p>If using the {@link android.graphics.ImageFormat#YV12} format,
         * refer to the equations in {@link Camera.Parameters#setPreviewFormat}
         * for the arrangement of the pixel data in the preview callback
         * buffers.
         *
         * @param data the contents of the preview frame in the format defined
         *  by {@link android.graphics.ImageFormat}, which can be queried
         *  with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
         *  If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}
         *             is never called, the default will be the YCbCr_420_SP
         *             (NV21) format.
         * @param camera the Camera service object.
         */
        void onPreviewFrame(byte[] data, Camera camera);
    };

2.8启动预览

完成相关设置后,仅需调用Camera成员方法startPreview即可。

mCamera.startPreview();

2.9停止预览

调用Camera成员方法stopPreview即可。

mCamera.stopPreview()

2.10关闭相机

调用Camera成员方法release即可。

mCamera.release();

3.结束语

Android Camera2 Java实现始于andorid 5.0, Native 实现则开始于android7.0(API level24)。

到目前为止,5.0以上系统市场占有率为85%,7.0以上系统仅为37%,因此,Camera2不足以适配所有Android 设备。

所以,Camera1虽然最终将被替代,但仍有存在价值。Camera1仅为单个类,没有Camera2复杂的结构,并且java实现还是相对简单实用。在不考虑被遗弃的情况,Camera1还是更为通用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章