2012年5月25日金曜日

SurfaceViewを使ってカメラプレビューを実装する

久しぶりにAndroidを触ってみました。
ほんと久しぶりだったんでけっこう忘れてるというか戸惑いました。
本当はFaceDetectorを使って顔認識するアプリを作ろうかと思ってたんですがその前にカメラビューを表示させるところから。
顔認識(FaceDetector)のところはまた今度しようかと思ってます。

まず、Eclipseを起動してプロジェクトを作成します。
それからカメラの機能を使うんでマニフェストファイル(AndroidManifest.xml)に以下を追記します。
<uses-permission android:name="andoird.permission.CAMERA" />

続いてレイアウトファイルにSurfaceViewを追加します。
<SurfaceView
 android:id="@+id/surface_view"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 />

最後にカメラプレビューを実装する部分を作ります。
package jp.kuseful.cameratest;

import java.util.List;

import android.app.Activity;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;

public class CameraTestActivity extends Activity {
 
    private Camera myCamera;
    private SurfaceView mySurfaceView;

    private SurfaceHolder.Callback mSurfaceListener = 
            new SurfaceHolder.Callback() {
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    // カメラを停止する
                    if (myCamera != null) {
                        myCamera.stopPreview();
                        myCamera.release();
                        myCamera = null;
                    }
                }

                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    // カメラを起動する
                    myCamera = Camera.open();
                    try {
                        myCamera.setPreviewDisplay(holder);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format
                        , int width, int height) {
                    myCamera.stopPreview();

                    Camera.Parameters parameters = myCamera.getParameters();

                    boolean portrait = isPortrait();

                    // 画面の向きを変更する
                    if (portrait) {
                        myCamera.setDisplayOrientation(90);
                    } else {
                        myCamera.setDisplayOrientation(0);
                    }

                    // サイズを設定
                    List sizes = parameters.getSupportedPreviewSizes();
                    Camera.Size size = sizes.get(0);
                    parameters.setPreviewSize(size.width, size.height);

                    // レイアウト調整
                    ViewGroup.LayoutParams layoutParams = mySurfaceView.getLayoutParams();
                    if (portrait) {
                        layoutParams.width = size.height;
                        layoutParams.height = size.width;
                    } else {
                        layoutParams.width = size.width;
                        layoutParams.height = size.height;
                    }
                    mySurfaceView.setLayoutParams(layoutParams);

                    myCamera.setParameters(parameters);
                    myCamera.startPreview();
                }
            };

    // 画面の向きを取得する
    protected boolean isPortrait() {
        return (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
    }
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mySurfaceView = (SurfaceView)findViewById(R.id.surface_view);
        SurfaceHolder holder = mySurfaceView.getHolder();

        // コールバックを登録
        holder.addCallback(mSurfaceListener);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
}

surfaceChangedのメソッド部分に大半のコードを書いてます。
その部分を簡単に説明すると

  1. カメラを一時的に停止する
  2. 状態を取得する
  3. デバイスの向きにあわせて画面を回転させる
  4. カメラプレビューの大きさを設定する
  5. レイアウト(アスペクト比)を調整する
  6. 状態を設定する
  7. カメラを再開する
とまぁこんなかんじの流れです。
実際に使うとなるともぉちょっと調整が必要ですがこれでカメラプレビューの実装自体はできると思います。

今度はこれから顔認識するようなものを作ってみようかと思います。


カメラは基本的に横向きの設定を持ってるみたいなんで縦も対応させようとすると回転させる必要がありました。(マニフェストファイルとかなんか設定できそうですけどね)

2012.5.30 ちょっと続きを書いてみました。そちらもどうぞー
カメラプレビューにちょっとした機能を追加



2 件のコメント:

  1. このコメントは投稿者によって削除されました。

    返信削除
  2. uses-permission android:name="andoird.permission.CAMERA"
    とありますが
    uses-permission android:name="android.permission.CAMERA"
    の誤りで、そのままでは動作しません。相当分かりづらいトラップです...

    返信削除