Android Camera-Camera1使用

Android Camera API和Android版本一樣,也是碎片化比較嚴重,所以Google官方推出了CameraView,提供給開發(fā)者參考和學習,現(xiàn)在最新的可以使用Jetpack CameraX來開發(fā),大大簡化了開發(fā)的復雜度。本系列從Camera1->Camera2->CameraView->CameraX,一步步講解Camera的進化過程,本篇先介紹Camera1的使用。
相機開發(fā)的流程:

  1. 檢測設備攝像頭,打開相機
  2. 創(chuàng)建預覽畫面,顯示實時預覽畫面
  3. 設置相機參數(shù),進行拍照監(jiān)聽
  4. 監(jiān)聽中,保存圖片資源或者直接操作原始數(shù)據(jù)
  5. 釋放相機資源

上面的是基本的相機開發(fā)流程,不同的Camera API在實現(xiàn)上會有不同,整體流程上還是統(tǒng)一的。

Camera1使用

權(quán)限聲明

<uses-feature
        android:name="android.hardware.camera"
        android:required="true" />

<uses-permission android:name="android.permission.CAMERA" />

相機必須聲明CAMERA權(quán)限,在Android6.0上,你還需要在代碼中動態(tài)申請權(quán)限

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
                    REQUEST_CAMERA_PERMISSION);

開發(fā)流程

下圖是一個開發(fā)流程的導覽:

打開相機

Camera.open()

該方法的系統(tǒng)源碼實現(xiàn)

public static Camera open() {
    int numberOfCameras = getNumberOfCameras();
    CameraInfo cameraInfo = new CameraInfo();
    for (int i = 0; i < numberOfCameras; i++) {
        getCameraInfo(i, cameraInfo);
        if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
            return new Camera(i);
        }
    }
    return null;
}

這里會檢查可用的攝像頭,默認使用的CameraInfo.CAMERA_FACING_BACK后置攝像頭

創(chuàng)建預覽畫面

這里使用的是SurfaceView

private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
...
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        ...
        startPreview();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        releaseCamera();
    }
});
...
private void startPreview() {
    try {
        //設置實時預覽
        mCamera.setPreviewDisplay(mSurfaceHolder);
        //Orientation
        setCameraDisplayOrientation();
        //開始預覽
        mCamera.startPreview();

        startFaceDetect();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

設置預覽的時候,可以設置setPreviewCallback監(jiān)聽預覽數(shù)據(jù)的回調(diào)

void onPreviewFrame(byte[] data, Camera camera);

設置相機參數(shù)

設置相機參數(shù)后,需要重新啟動預覽,這邊在初始化的時候,已經(jīng)設置好了。

private void initParameters(final Camera camera) {
    mParameters = camera.getParameters();
    mParameters.setPreviewFormat(ImageFormat.NV21); //default

    if (isSupportFocus(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
        mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
    } else if (isSupportFocus(Camera.Parameters.FOCUS_MODE_AUTO)) {
        mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
    }

    //設置預覽圖片大小
    setPreviewSize();
    //設置圖片大小
    setPictureSize();

    camera.setParameters(mParameters);
}

Camera.Parameters可以設置的參數(shù)非常多,這里就介紹幾個比較常用的


Camera.Parameters

1.setFocusMode

設置對焦模式

  • FOCUS_MODE_AUTO:自動對焦
  • FOCUS_MODE_INFINITY:無窮遠
  • FOCUS_MODE_MACRO:微距
  • FOCUS_MODE_FIXED:固定焦距
  • FOCUS_MODE_EDOF:景深擴展
  • FOCUS_MODE_CONTINUOUS_PICTURE:持續(xù)對焦(針對照片)
  • FOCUS_MODE_CONTINUOUS_VIDEO:(針對視頻)

2.setPreviewSize

設置預覽圖片大小

3.setPreviewFormat

支持的格式:

  • ImageFormat.NV16
  • ImageFormat.NV21
  • ImageFormat.YUY2
  • ImageFormat.YV12
  • ImgaeFormat.RGB_565
  • ImageFormat.JPEG
    如果不設置,默認返回NV21的數(shù)據(jù)

4.setPictureSize

設置保存圖片的大小

5.setPictureFormat

設置保存圖片的格式,格式和setPreviewFormat一樣

6.setDisplayOrientation

設置相機預覽畫面旋轉(zhuǎn)的角度,degress取值0,90,180,270

7.setPreviewDisplay

設置實時預覽SurfaceHolder

8.setPreviewCallback

監(jiān)聽相機預覽數(shù)據(jù)回調(diào)

9.setParameters

設置相機的Parameters
其他一些設置,大家可以查看Android文檔進行相應的設置

設置方向

設置相機的預覽方向,orientation比較詳細的介紹

private void setCameraDisplayOrientation() {
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
    Camera.getCameraInfo(mCameraId, cameraInfo);
    int rotation = getWindowManager().getDefaultDisplay().getRotation();  //自然方向
    int degrees = 0;
    switch (rotation) {
        case Surface.ROTATION_0:
            degrees = 0;
            break;
        case Surface.ROTATION_90:
            degrees = 90;
            break;
        case Surface.ROTATION_180:
            degrees = 180;
            break;
        case Surface.ROTATION_270:
            degrees = 270;
            break;
    }

    int result;
    //cameraInfo.orientation 圖像傳感方向
    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (cameraInfo.orientation + degrees) % 360;
        result = (360 - result) % 360;
    } else {
        result = (cameraInfo.orientation - degrees + 360) % 360;
    }

    mOrientation = result;
    //相機預覽方向
    mCamera.setDisplayOrientation(result);
}

拍照

private void takePicture() {
    if (null != mCamera) {
        mCamera.takePicture(new Camera.ShutterCallback() {
            @Override
            public void onShutter() {

            }
        }, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                //base data
            }
        }, new Camera.PictureCallback() {
            @Override
            public void onPictureTaken(final byte[] data, Camera camera) {
                mCamera.startPreview();
                //save data
            }
        });
    }
}

takePicture的源碼實現(xiàn):

public final void takePicture(ShutterCallback shutter, PictureCallback raw,
            PictureCallback jpeg) {
        takePicture(shutter, raw, null, jpeg);
    }
  • shutter(ShutterCallback):快門按下后的回調(diào)
  • raw(PictureCallback):raw圖像數(shù)據(jù)
  • jpeg(PictureCallback):jpeg圖像生成以后的回調(diào)

釋放相機資源

在使用完成后,onPause或者onDestory中進行相機資源的釋放

private void releaseCamera() {
    if (null != mCamera) {
        mCamera.stopPreview();
        mCamera.stopFaceDetection();
        mCamera.setPreviewCallback(null);
        mCamera.release();
        mCamera = null;
    }
}
  • stopPreview:停止預覽
  • release:釋放資源

Camera1的開發(fā)上,還是相對比較簡單的,需要定制的功能項比較少,下面一篇開始介紹Camera2的使用。
文章中涉及到的代碼

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容