woshidan's loose leaf

ぼんやり勉強しています

Camera API(カメラ関係の古い方)を使ってみる件

まとめ

  • カメラ撮影中の写ってる範囲を表示している部分はプレビューと呼んで SurfaceView で扱う
  • Camera.setParametersでプレビューの時の画像サイズや、プレビュー後(撮影後)の画像サイズが指定できたはずなのだが、compileSDKVersion 25以上で新規プロジェクト作ったらその関数がAndroid Studioから見つからず。。
    • Camera.getParameters().setPreviewSize() などだった
    • PreviewSize(プレビュー中に表示する画像のサイズ)やPictureSize(撮影後にコールバックに渡す画像のサイズ)は機種ごとにサポートしているサイズが決まっているので
  • 撮影後、カメラで撮った画像を処理させるには Camera.PictureCallback を定義して、 Camera.takePicture(ShutterCallback, PictureCallback, PictureCallback)
    • ここで2つ目の PictureCallbackに渡す方のクラスの onPictureTaken(byte[], Camera)を定義することで撮影した画像の処理を書くことができる
    • Camera.takePicture()を呼び出すと、プレビュー部分の画像の更新が止まる.
    • Camera.startPreview() で再びPreview表示を動かすことができる
android {
    compileSdkVersion 25
    buildToolsVersion "25.0.1"
    defaultConfig {
        applicationId "com.example.woshidan.cameratest"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

のとき、Camera APII(カメラ関係の古い方)をちょっと触ってみた。 CameraPreview はほぼ公式のチュートリアルのまま。 以下のコードでは、一回シャッターボタンを押すと画像がボタンを押したタイミングで止まり、もう一度押すとプレビューが再開される、みたいなもの。

public class MainActivity extends Activity {

    private Camera mCamera;
    private CameraPreview mPreview;
    private boolean isCaptured = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create an instance of Camera
        mCamera = getCameraInstance();

        // mCamera.getParameters().setXXX...でプレビュー画面の設定などのパラメータを設定できる
        List<Camera.Size> supportedSizes = mCamera.getParameters().getSupportedPreviewSizes();
        mCamera.getParameters().setPreviewSize(supportedSizes.get(supportedSizes.size() - 1).width, supportedSizes.get(supportedSizes.size() - 1).height);

        // Create our Preview view and set it as the content of our activity.
        mPreview = new CameraPreview(this, mCamera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mPreview);

        Button captureButton = (Button) findViewById(R.id.button_capture);
        captureButton.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // get an image from the camera
                        if (isCaptured) {
                            mCamera.startPreview(); // 撮影用のプレビューをもう一度動かす
                            isCaptured = false;
                        } else {
                            mCamera.takePicture(null, null, mPicture);
                            // 撮影結果を撮影結果をあれこれするコールバック(Camera.PictureCallback)へ渡す
                            // この関数を呼び出すと、Preview部分の表示の更新は止まる
                            isCaptured = true;
                        }
                    }
                }
        );
    }

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open(0); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
        }
        return c; // returns null if camera is unavailable
    }


    private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // 結果をSDカードに書き込んだりする
        }
    };
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.woshidan.cameratest">
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" /><!-- カメラが使えない端末でプレイストアで検索したときこのアプリを表示させない -->
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@android:style/Theme.Holo">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="landscape"
            android:theme="@android:style/Theme.Holo.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>