【Android】カメラ機能を使って撮影した写真をSDカードに保存する方法


概ね、タイトルとおりです。

・【Android】カメラ機能を使ってプレビューをSurfaceViewに表示する方法
↑前回の記事でカメラのプレビューを表示するところまでやっているので、
今回で実際にシャッターを切り撮影する機能を紹介してみます。



AndroidManifestにSDカードを使用する用のパーミッションを追加


AndroidManifest.xmlに以下の一文追加するだけです。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>



撮影のトリガーとなるシャッターボタンを付ける


前回のプログラムでは全画面にプレビューを表示するだけでしたので、
まず撮影するボタンを付けてみます。

SurfaceView sv;
SurfaceHolder sh;
Button btn;
   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       LinearLayout ll = new LinearLayout(this);
       ll.setOrientation(LinearLayout.VERTICAL);
       setContentView(ll);

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

       sh.addCallback(  new SampleCallback() );
       sh.setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS );

        btn = new Button(this);
        btn.setText("撮影");
        ll.addView(btn);

        ll.addView(sv);
        btn.setOnClickListener( new SampleClick() );
   }
  class SampleClick implements OnClickListener{

    @Override
    public void onClick(View v) {
    }
  }



ボタンにOnClickListenerを登録しています。

takePicture関数の引数にコールバックを設定する


撮影をする時には、CameraクラスのtakePicture関数を使います。
この関数の引数には3つのコールバックを設定できます。

Camera.ShutterCallback shutterシャッター音を鳴らす時に使用
Camera.PictureCallback rawRAW画像データを受け取る時に使用
Camera.PictureCallback jpegJPEG画像データを受け取る時に使用

今回は三番目のJPEG画像データを受け取るコールバックを使いSDカードに保存する処理を紹介します。

class SampleClick implements OnClickListener{

@Override
public void onClick(View v) {
	cm.takePicture(null, null, new SamplePictureCallback() );
}
  class SamplePictureCallback implements PictureCallback{

  	@Override
  	public void onPictureTaken(byte[] data, Camera camera) {
  		try{
  			File dir = new File( Environment.getExternalStorageDirectory(), "sample20120712" );
  			if( dir.exists() == false ){
  				dir.mkdir();
  			}
  			File f = new File( dir, "test.jpg" );
  			FileOutputStream out = new FileOutputStream(f);
  			out.write(data);
  			Toast.makeText(getApplicationContext(), "保存しました。", Toast.LENGTH_LONG).show();
  			out.close();
  			//プレビュー再開
  			cm.startPreview();

  		}catch( Exception e ){}
  	}

  }
}


撮影された時にCameraクラスのtakePicture関数を実行。
三番目の引数にコールバック用の内部クラスを設定しています。

onPictureTaken関数の第一引数にjpegデータが渡されるので、それをSDカードに保存しています。

最後にstartPreview関数でプレビューを再開させています。

サンプルプログラム

(importは省略)
public class Sample20120712Activity extends Activity {

	Button btn;
	SurfaceView sv;
	SurfaceHolder sh;
	Camera cm;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout ll = new LinearLayout(this);
        ll.setOrientation(LinearLayout.VERTICAL);
        setContentView(ll);
        //全画面表示
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

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

        sh.addCallback(  new SampleCallback() );
        sh.setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS );
        btn = new Button(this);
        btn.setText("撮影");
        ll.addView(btn);
        ll.addView(sv);

        btn.setOnClickListener( new SampleClick() );

    }

    class SampleCallback implements Callback{

		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,	int height) {

			try{
				int d = 90;
				cm.setDisplayOrientation(d);
				cm.setPreviewDisplay(sv.getHolder());

				Camera.Parameters pr = cm.getParameters();
				pr.setPictureSize( width , height );
				cm.setParameters(pr);
				cm.startPreview();

			}catch( Exception e ){ }

		}

		@Override
		public void surfaceCreated(SurfaceHolder holder) {

			cm = Camera.open();
			Camera.Parameters pr = cm.getParameters();
			List<Size> ss = pr.getSupportedPictureSizes();
			Size s = ss.get(0);
			pr.setPictureSize( s.width , s.height );
			cm.setParameters(pr);

		}

		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			cm.stopPreview();
			cm.release();
		}

    }

    class SampleClick implements OnClickListener{

  		@Override
  		public void onClick(View v) {
  			cm.takePicture(null, null, new SamplePictureCallback() );
  		}
  		class SamplePictureCallback implements PictureCallback{

  			@Override
  			public void onPictureTaken(byte[] data, Camera camera) {
  				try{
  					File dir = new File( Environment.getExternalStorageDirectory(), "sample20120712" );
  					if( dir.exists() == false ){
  						dir.mkdir();
  					}
  					File f = new File( dir, "test.jpg" );
  					FileOutputStream out = new FileOutputStream(f);
  					out.write(data);
  					Toast.makeText(getApplicationContext(), "保存しました。", Toast.LENGTH_LONG).show();
  					out.close();
  					//プレビュー再開
  					cm.startPreview();

  				}catch( Exception e ){}
  			}

  		}
    }
}



【実行結果】
カメラ機能を使って写真をSDカードに保存するサンプルプログラム01 カメラ機能を使って写真をSDカードに保存するサンプルプログラム02


関連記事

コメントは受け付けていません。