카메라 제어

Android 2014. 2. 10. 19:30
  • 우선 카메라 Object를 얻어야 한다. Open을 할 때 UI Thread에서 하면 안된다.
    다른 앱이 카메라를 사용중이거나 다른 문제가 있을 경우 아래 코드의 try에 걸리게 된다.
    API Level 9 이상에서는 멀티 카메라를 지원하므로 ID값을 입력하지만, 그 이전 API에서는 open()하면 첫번째 뒷면 카메라의 Object가 나온다.

    private boolean safeCameraOpen(int id) {
       
    boolean qOpened = false;
     
       
    try {
            releaseCameraAndPreview
    ();
            mCamera
    = Camera.open(id);
            qOpened
    = (mCamera != null);
       
    } catch (Exception e) {
           
    Log.e(getString(R.string.app_name), "failed to open Camera");
            e
    .printStackTrace();
       
    }

       
    return qOpened;    
    }

    private void releaseCameraAndPreview() {
        mPreview
    .setCamera(null);
       
    if (mCamera != null) {
            mCamera
    .release();
            mCamera
    = null;
       
    }
    }
  • 카메라가 찍는 영상을 화면에 미리보기는 SurfaceView에 하게 되는데, 아래와 같이 구현해주면 된다. 

    class Preview extends ViewGroup implements SurfaceHolder.Callback {

       
    SurfaceView mSurfaceView;
       
    SurfaceHolder mHolder;

       
    Preview(Context context) {
           
    super(context);

            mSurfaceView
    = new SurfaceView(context);
            addView
    (mSurfaceView);

           
    // Install a SurfaceHolder.Callback so we get notified when the
           
    // underlying surface is created and destroyed.
            mHolder
    = mSurfaceView.getHolder();
            mHolder
    .addCallback(this);
            mHolder
    .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
       
    }

    }

  • (Preview Class 내부) setCamera()로 카메라 Object를 넘겨주면, startPreview()를 통해 미리보기가 시작된다.

    public void setCamera(Camera camera) {
       
    if (mCamera == camera) { return; }
       
        stopPreviewAndFreeCamera
    ();
       
        mCamera
    = camera;
       
       
    if (mCamera != null) {
           
    List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
            mSupportedPreviewSizes
    = localSizes;
            requestLayout
    ();
         
           
    try {
                mCamera
    .setPreviewDisplay(mHolder);
           
    } catch (IOException e) {
                e
    .printStackTrace();
           
    }
         
           
    // Important: Call startPreview() to start updating the preview
           
    // surface. Preview must be started before you can take a picture.
            mCamera
    .startPreview();
       
    }
    }
  • 카메라 관련 설정(줌 Level 등)이 변경되면, 아래와 같이 setParameters()를 이용해 미리보기를 변경할 수 있다. 아래 예제는 미리보기 View 크기 변경임.
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
       
    // Now that the size is known, set up the camera parameters and begin
       
    // the preview.
       
    Camera.Parameters parameters = mCamera.getParameters();
        parameters
    .setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        requestLayout
    ();
        mCamera
    .setParameters(parameters);

       
    // Important: Call startPreview() to start updating the preview surface.
       
    // Preview must be started before you can take a picture.
        mCamera
    .startPreview();
    }
  • 미리보기 방향을 변경하려면, setCameraDisplayOrientation() 메소드를 사용한다. API Level 14 이전에는 방향 변경전에 미리보기를 중지하고, 설정 후 재시작해야 한다.
    아래 코드는 현재 화면과 같은 방향으로 미리보기를 표시하기 위한 방법이다.

     public static void setCameraDisplayOrientation(Activity activity,
             
    int cameraId, android.hardware.Camera camera) {
         android
    .hardware.Camera.CameraInfo info =
                 
    new android.hardware.Camera.CameraInfo();
         android
    .hardware.Camera.getCameraInfo(cameraId, info);
         
    int rotation = activity.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;
         
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
             result
    = (info.orientation + degrees) % 360;
             result
    = (360 - result) % 360;  // compensate the mirror
         
    } else {  // back-facing
             result
    = (info.orientation - degrees + 360) % 360;
         
    }
         camera
    .setDisplayOrientation(result);
     
    }
     
  • 사진은 Camera.takePicture()을 통해서 찍을 수 있다. Camera.PictureCallback Camera.ShutterCallback으로 결과를 받는다.
  • 연속적으로 사진 찍기는 Camera.PreviewCallback을 통해서 할 수 있다.
  • 사진을 찍은 후에는 미리보기가 멈추므로, 미리보기를 다시 시작해줘야 한다.
  • 카메라 사용 후 Release는 미리보기 SurfaceView가 Destroy 될 때 하면 좋다. 또한, onPause()에서도 Release를 해야 하며, onResume()에서 다시 카메라를 Open해야 한다. 위 setCamera()처럼 카메라 초기화시에도 항상 미리보기 및 카메라를 Release해야 한다.

    public void surfaceDestroyed(SurfaceHolder holder) {
       
    // Surface will be destroyed when we return, so stop the preview.
       
    if (mCamera != null) {
           
    // Call stopPreview() to stop updating the preview surface.
            mCamera
    .stopPreview();
       
    }
    }

    /**
     * When this function returns, mCamera will be null.
     */

    private void stopPreviewAndFreeCamera() {

       
    if (mCamera != null) {
           
    // Call stopPreview() to stop updating the preview surface.
            mCamera
    .stopPreview();
       
           
    // Important: Call release() to release the camera for use by other
           
    // applications. Applications should release the camera immediately
           
    // during onPause() and re-open() it during onResume()).
            mCamera
    .release();
       
            mCamera
    = null;
       
    }
    }


출처 : http://developer.android.com/

설정

트랙백

댓글