2015-11-08

Android Studio でカメラアプリにグリッド表示を追加

スポンサーリンク

前回までに作成したカメラアプリを使って、写真をより良く撮影できるように補助線となるグリッドを表示できるようにします。

前回までの記事


Grid クラスを作成する


グリッドは複数の線分を描画するだけなので CanvasdrawLines() メソッドを使って Grid クラスを作成します。
  • Grid.java
package com.example.camera;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;

public class Grid extends View {
    float[] pts;
    Paint p;

    public Grid(Context context, int w, int h) {
        super(context);
        p = new Paint();
        p.setColor(Color.DKGRAY);
        p.setStrokeWidth(3);

        pts = new float[]{
                w / 3, 0, w/3, h,
                2 * w / 3, 0, 2 * w / 3, h,
                0, h / 3, w, h / 3,
                0, 2 * h / 3, w, 2 * h / 3};
    }
    protected void onDraw(Canvas canvas){
        super.onDraw(canvas);
        canvas.drawLines(pts, p);
    }
}

グリッドを描画する


グリッドはカメラのプレビューサイズに応じて画面を等分できるように surfaceChanged() メソッド内でインスタンス化してプレビューサイズを渡しています。
  • MainActivity.java
package com.example.camera;

import android.app.Activity;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Environment;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.util.List;

public class MainActivity extends Activity {

    SurfaceView sv;
    SurfaceHolder sh;
    Camera cam;
    Grid grid;
    FrameLayout fl;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        fl = new FrameLayout(this);
        setContentView(fl);

        sv = new SurfaceView(this);
        sh = sv.getHolder();
        sh.addCallback(new SurfaceHolderCallback());

        Button btn = new Button(this);
        btn.setText("撮影");
        btn.setLayoutParams(new LayoutParams(200, 150));
        btn.setOnClickListener(new TakePictureClickListener());

        fl.addView(sv);
        fl.addView(btn);
    }

    class SurfaceHolderCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            cam = Camera.open();
            Parameters param = cam.getParameters();
            List<Size> ss = param.getSupportedPictureSizes();
            Size pictSize = ss.get(0);

            param.setPictureSize(pictSize.width, pictSize.height);
            cam.setParameters(param);
        }
        @Override
        public void surfaceChanged(SurfaceHolder holder, int f, int w, int h) {
            try {
                cam.setDisplayOrientation(0);
                cam.setPreviewDisplay(sv.getHolder());

                Parameters param = cam.getParameters();
                List<Size> previewSizes =
                        cam.getParameters().getSupportedPreviewSizes();
                Size pre = previewSizes.get(0);
                param.setPreviewSize(pre.width, pre.height);

                LayoutParams lp = new LayoutParams(pre.width, pre.height);
                sv.setLayoutParams(lp);

                grid = new Grid(getApplicationContext(), pre.width, pre.height);
                fl.addView(grid);

                cam.setParameters(param);
                cam.startPreview();
            } catch (Exception e) { }
        }
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            cam.stopPreview();
            cam.release();
        }
    }

    class TakePictureClickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            cam.autoFocus(autoFocusCallback);
        }

        private Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                cam.takePicture(new Camera.ShutterCallback() {
                    @Override
                    public void onShutter() {}
                }, null, new TakePictureCallback());
            }
        };
    }

    class TakePictureCallback implements Camera.PictureCallback {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            try {
                File dir = new File(
                        Environment.getExternalStorageDirectory(), "Camera");
                if(!dir.exists()) {
                    dir.mkdir();
                }
                File f = new File(dir, "img.jpg");
                FileOutputStream fos = new FileOutputStream(f);
                fos.write(data);
                Toast.makeText(getApplicationContext(),
                        "写真を保存しました", Toast.LENGTH_LONG).show();
                fos.close();
                cam.startPreview();
            } catch (Exception e) { }
        }
    }
}

アプリを起動すると、グリッドが表示されていることが確認できます。

これ以降の記事

スポンサーリンク

0 件のコメント:

コメントを投稿