最終更新:
moonlight_aska 2015年11月21日(土) 07:53:33履歴
カメラを制御して写真の撮影を行うには, Camera.PictureCallbackインタフェースを利用する.
写真データは, /sdcard/CameraSampleの下に保存される.
端末:SHARP SH-03C / Android 2.2

- src/Camera01.java
package com.moonlight_aska.android.camera01;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class Camera01 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 画面をフルスクリーンに設定
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
// カメラ用ビューの設定
setContentView(new CameraView(this));
}
}
- src/CameraView.java
- PictureCallbackインターフェースのonPictureTakenメソッドをオーバーライドする.
- 撮影したデータ(data)をsdcardに保存する.
- View#onTouchEventメソッドをオーバーライドする.
- Camera#takePictureメソッドで, 写真を撮影する. 引数には, JPEG画像データを処理するコールバック関数を渡す.
- PictureCallbackインターフェースのonPictureTakenメソッドをオーバーライドする.
shutter | シャッターを押した瞬間のコールバック関数 or null |
raw | RAW画像データを処理するためのコールバック関数 or null |
jpeg | JPEG画像データを処理するためのコールバック関数 or null |
package com.moonlight_aska.android.camera01;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraView extends SurfaceView
implements SurfaceHolder.Callback, PictureCallback {
private Camera mCamera = null;
private static final String SDCARD_FOLDER = "/sdcard/CameraSample/";
public CameraView(Context context) {
super(context);
// TODO Auto-generated constructor stub
SurfaceHolder holder = getHolder();
holder.addCallback(this);
// holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // API Level 11で廃止予定に
// 保存用フォルダ作成
File dirs = new File(SDCARD_FOLDER);
if(!dirs.exists()) {
dirs.mkdir();
}
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd_kkmmss");
String datName = "P" + date.format(new Date()) + ".jpg";
try {
// データ保存
savePhotoData(datName, data);
} catch (Exception e) {
// TODO Auto-generated catch block
if(mCamera != null) {
mCamera.release();
mCamera = null;
}
}
// プレビュー再開
mCamera.startPreview();
}
// 画像データのセーブ
private void savePhotoData(String datName, byte[] data) throws Exception {
// TODO Auto-generated method stub
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(SDCARD_FOLDER + datName);
outStream.write(data);
outStream.close();
} catch (Exception e) {
if(outStream != null) {
outStream.close();
}
throw e;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction() == MotionEvent.ACTION_DOWN) {
// シャッターを切る
mCamera.takePicture(null, null, this);
}
return true;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
mCamera.stopPreview();
Camera.Parameters params = mCamera.getParameters();
List<Size> previewSizes = params.getSupportedPreviewSizes();
Size size = previewSizes.get(0);
params.setPreviewSize(size.width, size.height);
mCamera.setParameters(params);
// プレビュー開始
mCamera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
- AndroidManifest.xml
- カメラを使用するには, "android.permission.CAMERA"パーミッションを設定する.
- "android.hardware.camera"で, カメラ機能を備えたハードに限定する.
- "android.hardware.camera.autofocus"で, オートフォーカス機能を備えたハードに限定する.
- sdcardにデータを保存するには, "android.permission.WRITE_EXTERNAL_STORAGE"パーミションを設定する.
- 画面を横向き(landscape)に固定する. Androidのカメラは横向き専用なので...
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.moonlight_aska.android.camerasample"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-feature android:name="android.hardware.camera"></uses-feature>
<uses-feature android:name="android.hardware.camera.autofocus"></uses-feature>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".CameraSample"
android:label="@string/app_name"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
- 動作例
写真データは, /sdcard/CameraSampleの下に保存される.
端末:SHARP SH-03C / Android 2.2

このページへのコメント
写真の解像度などは
プレビューの取得時とtakepictureの取得で変化しますか?
ビットマップ操作になるため
画像をバイトからjpeg変換する際などバイト配列なので幅と高さのピクセルしかもってないのでしょうか?
mTextureView.getBitmap()
だと早く画像を取得できます。
TakePictureだとバイトからクォリティ指定で同期変換をかけるため100%にするには結構時間がかかります。
不思議なのはAndroidって結局Bitmapしかないので、
Bitmap画質がAndroidのがしつなんじゃないかなと思ってしまいますがそれだとカメラの画質いくつまでといった機器の性能に疑問を抱いてしまいます。
Nexsus7の性能みたら下記になってました。
500万画素背面
120万画素前面