【Android Training-Multimedia】キャプチャ写真[Lesson 3-ダイレクトコントロールカメラ]


このレッスンでは、frameworkのAPIsを使用してカメラのハードウェアを直接制御する方法について説明します.設備を直接制御するカメラは、撮影や録画よりも複雑です.しかし、専門的な特殊なカメラプログラムを作成したい場合は、この授業でこの部分を説明します.
Open the Camera Object[カメラオブジェクトを開く]Cameraオブジェクトを取得することは、カメラを直接制御する最初のステップである.Androidが持参したカメラプログラムのように、Cameraにアクセスする方法はonCreateメソッドにもう一つのThreadをつけてCameraを開くことをお勧めします.この方法はオープン作業に時間がかかるためANRを引き起こすことを避けることができる.より基礎的な実装方法では、Cameraを開く動作がonResume()メソッドに遅延され、コードがより再利用され、制御プロセスが複雑化しないようにする.[原文:In a more basic implementation,opening the camera can be deferred to the onResume() method to facilitate code reuse and keep the flow of control simple.]
cameraが別のプログラムで使用されている間にCamera.open()を実行するとexceptionが放出されるので、キャプチャする必要があります.
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;
    }
}

API level 9から、cameraのframeworkは複数のcamerasをサポートすることができる.もしあなたがopen() 
最後のcameraを手に入れることができます
Create the Camera Preview[カメラプレビューインタフェースを作成]
写真を撮るには、通常、撮影されるものを表示するためのプレビューインタフェースが必要です.写真を撮るのと同じように、1つ使う必要があります.SurfaceView
録画した画面を表示します.
  • Preview Class

  • プレビューインタフェースを表示するには、Previewクラスが必要です.このクラスは実現する必要があるandroid.view.SurfaceHolder.Callback
    cameraハードウェアから取得したデータをプログラムに渡すインタフェース.
    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クラスは、画像を表示する前に渡さなければなりません.Camera
    オブジェクト.以下に説明するように、
  • Set and Start the Preview

  • Cameraインスタンスに関連するpreviewは、まずCameraオブジェクトを作成するために指定された順序で作成する必要があります.次の例では、初期化cameraの動作がカプセル化され、ユーザがCameraを変更しようとしてもsetCamera()を実行することによって呼び出されるCamera.startPreview()
    .PreviewオブジェクトはsurfaceChanged()
    のコールバックメソッドでは、再作成する動作をします.
    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();
        }
    }

    Modify Camera Settings[カメラ設定の変更]
    カメラ設定は、ズームレベルから露出補正(exposure compensation)まで、写真の撮り方を変えることができます.以下の例ではプレビューサイズを変更する設定のみを示しますが、詳細はCameraのソースコードを参照してください.
    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();
    }

    Set the Preview Orientation[プレビュー方向を設定]
    ほとんどのカメラプログラムはプレビューを横画面にロックします.それは人が写真を撮る自然な方法だからです.設定中は縦画面の写真を撮るのを止めていませんが、これらの情報はEXIFに記録されます.  setCameraDisplayOrientation()
    方法は、プレビューの方向を変更し、画像が記録される効果に影響を与えないようにすることができます.しかし、Android APIレベル14の前に、方向を変える前にプレビューを停止してから再起動する必要があります.
    Take a Picture[写真を撮る]
    プレビューが開始されると、Camera.takePicture()の方法で次の画像を撮ることができます.Camera.PictureCallbackCamera.ShutterCallbackのオブジェクトを作成し、Camera.takePicture()に渡すことができます.
    連写の動作をしたい場合は、Camera.PreviewCallbackを作成し、onPreviewFrame()を実現することができます.また、いくつかのプレビューフレームを選択して写真を撮るか、遅延した写真を撮る動作を確立することもできます.
    Restart the Preview[再起動プレビュー]
    画像が取得された後、ユーザーが次の画像を撮る前にプレビューを再起動する必要があります.次の例では、shutter buttonを再ロードすることで再起動を実現します.
    @Override
    public void onClick(View v) {
        switch(mPreviewState) {
        case K_STATE_FROZEN:
            mCamera.startPreview();
            mPreviewState = K_STATE_PREVIEW;
            break;
    
        default:
            mCamera.takePicture( null, rawCallback, null);
            mPreviewState = K_STATE_BUSY;
        } // switch
        shutterBtnConfig();
    }

    Stop the Preview and Release the Camera[プレビューを停止してカメラを解放]
    あなたのプログラムがカメラを使った後、クリーンアップの動作をする必要があります.特に、Camera オブジェクトを解放する必要があります.そうしないと、他のapp crashが発生します.
    では、プレビューを停止してカメラを解放するのはいつですか?プレビューのsurfaceが破壊された後、プレビューを停止してカメラを解放する動作を行うことができます.次のようになります.
    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 in onPause() (and re-open() it in
              onResume()).
            */
            mCamera.release();
        
            mCamera = null;
        }
    }

    この授業の前に、このシリーズの動作もsetCamera()
    メソッドの一部なので、cameraを初期化する動作は、常にプレビューを停止することから始まります.
    学習:http://developer.android.com/training/camera/cameradirect.htmlあ、交流を歓迎します!
    転載は出典を明記してください.http://blog.csdn.net/kesenhooあ、ありがとう!