ユーザーID パスワード

技術情報

  • FAQ よくある質問
  • 個人ユーザー向けサービスのお手続きについて

コード&コラム

第6回
カメラを使ってみよう(後編)


前へ 1 |2 |3 |4 次へ

Step1 オートフォーカス機能を利用しよう

第5回で作成したカメラアプリには、オートフォーカスが実装されておらず、下図のようにかなりの確率でピントがボケてしまう現象が起こってしまいます。

img

Step1では、前回作成したカメラアプリにオートフォーカス機能を追加します。CameraAppプロジェクトを用意してください。「オート」と聞くとカメラの挙動までこちらが制御しなければならないかと難しく感じる方もいるかも知れませんが、すでにAndroid™ ではオートフォーカスの利用が用意されているのでそこまで手間をかけず利用することができます。
オートフォーカスを実装するには、CameraViewクラスに[Camera.AutoFocusCallback]をimplementsに加えます。
画面タッチ時の処理を記述するonTouchEventメソッドにカメラでの撮影を行う「camera.takePicture(null,null,this);」の命令が書いてありますが、今回は画面タッチ時にはオートフォーカス機能を呼び出しますので[camera.autoFocus(this);]と直しておきましょう。
さらに[onAutoFocus]メソッドを追加しましょう。場所はどこでも構いませんが、分かりやすいようにonTouchEventメソッドの後に記述するといいでしょう。メソッドの中にはオートフォーカス機能を呼び出すために[camera.autoFocus()]を記述します。第5回のおさらいも兼ねてCameraView.javaのコードを下に記します。

public class CameraView extends SurfaceView implements SurfaceHolder.Callback, PictureCallback, Camera.AutoFocusCallback{
    private SurfaceHolder surfaceholder; //サーフェスホルダーオブジェクト
    private Camera camera; //カメラオブジェクト

    //コンストラクタ
    public CameraView(Context context){
        super(context);

        //サーフェスホルダーの取得とコールバック通知先の指定
        surfaceholder=getHolder();
        surfaceholder.addCallback(this);

        //SurfaceViewの種別をプッシュバッファーに変更します
        surfaceholder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder surfaceholder){
        try{
            //カメラを呼び出す
            camera=Camera.open();
            //表示先のサーフェスホルダーを指定
            camera.setPreviewDisplay(surfaceholder);
        }catch(Exception e){
        }
    }
    public void surfaceChanged(SurfaceHolder surfaceholder,int format, int width, int height){
        //プレビューの開始
        camera.setPreview();
    }
    public void surfaceDestroyed(SurfaceHolder surfaceholder){
        camera.setPreviewCallback(null); //コールバックの停止
        camera.stopPreview(); //プレビューの停止
        camera.release(); //カメラリソースの停止
        camera=(null); //カメラオブジェクトの停止
    }

    @Override
    //タッチ時に呼び出されるメソッド
    public boolean onTouchEvent(MotionEvent event) {
        //1本の指でタッチされたときに実行
        if (event.getAction()==MotionEvent.ACTION_DOWN) {
            //オートフォーカス機能を呼び出す
            camera.autoFocus(this);
        }
        //それ以外のときはtrueを返して処理をすすめる
        return true;
    }

    //オートフォーカスが呼び出されたときに処理される
    public void onAutoFocus(boolean success, Camera camera){
        camera.autoFocus();
    }


    //camera.takePicture時にスクリーンショットの値が渡される
    public void onPictureTaken(byte[] data, Camera camera) {
        Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length, null);
        MediaStore.Images.Media.insertImage(getContext().getContentResolver(), bmp, "", null);
        camera.startPreview();
    }
}

autoFocus()の引数にはオートフォーカスが完了したときのコールバック処理を記述します。今回はmAutoFocusListenerという名前でコールバックを指定します。そして同名のコールバックを作成します。

    //オートフォーカスが呼び出されたときに処理される
    public void onAutoFocus(boolean success, Camera camera){
        //オートフォーカス完了時のコールバック処理を呼び出す
        camera.autoFocus(mAutoFocusListener);
    }

    //camera.AutoFocus完了時に呼び出されるコールバック
    private Camera.AutoFocusCallback mAutoFocusListener =
        new Camera.AutoFocusCallback(){
    }

オートフォーカス完了時に呼び出されるmAutoFocusListenerコールバックの中身にはカメラでの撮影を行う[camera.takePicture()]メソッドを書き込みます。このようにオートフォーカスのメソッドと、カメラのシャッターを切るメソッドが別々に用意されているために若干記述が難しくなってしまいます。

    //camera.AutoFocus完了時に呼び出されるコールバック
    private Camera.AutoFocusCallback mAutoFocusListener =
        new Camera.AutoFocusCallback(){
        private void onAutoFocus(boolean success, Camera camera){
            camera.takePicture();
        }
    }

前回も説明しましたが、「takePicture()」の第1引数にはシャッター時の、第2引数にはraw画像を取得した時の、第3引数にはJPEG画像を取得したときのメソッドを記述します。前回は第3引数を「this」として自動的に「onPictureTaken」を指定していましたが、今回の場合同じようにしてしまうと「new camera.AutoFocusCallback()」を指定してしまうので、「onPictureTaken」のメソッドを含んだ「mPictureLinstener」という名前のコールバックを新しく作成してそれを指定するようにします。

    //camera.AutoFocus完了時に呼び出されるコールバック
    private Camera.AutoFocusCallback mAutoFocusListener =
        new Camera.AutoFocusCallback(){
        private void onAutoFocus(boolean success, Camera camera){
            camera.takePicture(null, null, mPictureListener);
        }
    }

    //camera.takePicture時に呼び出されるコールバック
    private Camera.PictureCallback mAutoFocusListener =
        new Camera.PictureCallback(){
        public void onPictureTaken(byte[] data, Camera camera){
            Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data).length, null);

            MediaStore.Images.Media.insertImage(getContext().getContentResolver(), bmp,"",null);
            camera.startPreview();
        }
    }

お疲れさまでした。以上でオートフォーカス機能を追加する作業は終了です!
最後にAndroidmanifest.xmlにオートフォーカスを利用する旨を追加して書き込みます。

    <uses-feature android:name="android.hardware.camera.autofocus" ⁄>

実行すると画面タッチ時にオートフォーカスが起動し、その完了時にシャッターが降りるようになっていると思います。

img

ギャラリーから画像の保存を確認出来れば成功です!

いかがでしょうか?
オートフォーカス機能を実装する以前に撮影した写真に比べ、くっきりとした写真が撮れているのではないでしょうか。

第6回 カメラを使ってみよう(後編)
 Step1 オートフォーカス機能を利用しよう
 Step2 ビデオカメラアプリを作成しよう
 Step3 録画して保存しよう

サンプルコード

第1回 リファレンスコード(文字列編)

第2回 リファレンスコード2(グラフィックス編)

第3回 リファレンスコード3(タッチイベント編)

第4回 リファレンスコード4(チェックボックス/ラジオグループ編)

第5回 リファレンスコード5(スピナー編)

第6回 リファレンスコード6(サウンド/ムービー編)

第7回 リファレンスコード7(トースト編)

第8回 リファレンスコード8(Google Maps API利用編)

第9回 リファレンスコード9(SQLite編)

第10回 リファレンスコード10(音声認識編)

第11回 リファレンスコード11(日付/時刻ダイアログ編)

第12回 リファレンスコード12(Bluetooth編)