概ね、タイトルとおりです。
・【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 raw | RAW画像データを受け取る時に使用 |
| Camera.PictureCallback jpeg | JPEG画像データを受け取る時に使用 |
今回は三番目の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 ){}
}
}
}
}
【実行結果】
