- Android
- 2013-08-21
この記事は最終更新日から1年以上経過しています。
Androidでカメラを扱うまとめです。
単純に撮った写真を保存するパターンと、パラメーターを指定して保存するパターン、
撮影した画像を圧縮して保存するパターンの3パターンを紹介します。
まずは、カメラを使用するために必要なパーミッションをAndroidManifest.xml
に記述します。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.FLASHLIGHT" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <uses-feature android:name="android.hardware.camera.flash" />
撮影処理をするSurfaceView
を継承したクラスを作成します。
まず、簡単に保存するパターン
import java.io.*; import java.util.List; import android.util.Log; import android.content.Context; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.MotionEvent; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.ShutterCallback; import android.graphics.*; import android.provider.MediaStore; public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { private Context mContext; private Camera mCamera; private boolean mFlag; private static final String TAG = "MySurfaceView"; MySurfaceView(Context context) { super(context); mContext = context; SurfaceHolder mHolder = getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { mCamera = Camera.open(); try { mCamera.setPreviewDisplay(holder); } catch (IOException ex) { mCamera.release(); mCamera = null; } } public void surfaceDestroyed(SurfaceHolder holder) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { setPictureFormat(format); setPreviewSize(w, h); mCamera.startPreview(); } @Override public boolean onTouchEvent(MotionEvent event) { // オートフォーカスで撮影 this.autoFocus(); // オートフォーカスなしで撮影 //this.takePicture(); return super.onTouchEvent(event); } public void autoFocus() { if(mFlag) { return; } mFlag = true; mCamera.autoFocus(new AutoFocusCallback() { @Override public void onAutoFocus(boolean success, final Camera camera) { // イメージの取得を開始、リスナーを設定。 camera.takePicture(mShutterListener, // シャッター後 rawListener, // Rawイメージ生成後 jpegListener); // Jpegイメージ生成後 } }); } public void takePicture() { if(mFlag) { return; } mFlag = true; if (mCamera != null) { // イメージの取得を開始、リスナーを設定。 mCamera.takePicture(mShutterListener, // シャッター後 rawListener, // Rawイメージ生成後 jpegListener); // Jpegイメージ生成後 } } ShutterCallback mShutterListener = new ShutterCallback() { @Override public void onShutter() { Log.d(TAG, "onShutter"); } }; PictureCallback rawListener = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { Log.d(TAG, "onPictureTaken: raw: data=" + data); } }; // PictureCallback jpegなどが生成された後に呼び出される private PictureCallback jpegListener = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // 保存する処理 Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length, null); // DCIM/Cameraに保存されます。 MediaStore.Images.Media.insertImage(mContext.getContentResolver(), bmp, "sample", null); new Thread() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException ex) { Log.w(TAG, ex); } mFlag = false; mCamera.startPreview(); } }.start(); } }; protected void setPreviewSize(int width, int height) { Camera.Parameters params = mCamera.getParameters(); List<Camera.Size> supported = params.getSupportedPreviewSizes(); if (supported != null) { for (Camera.Size size : supported) { if (size.width <= width && size.height <= height) { params.setPreviewSize(size.width, size.height); mCamera.setParameters(params); break; } } } } protected void setPictureFormat(int format) { try { Camera.Parameters params = mCamera.getParameters(); List<Integer> supported = params.getSupportedPictureFormats(); if (supported != null) { for (int f : supported) { if (f == format) { params.setPreviewFormat(format); mCamera.setParameters(params); break; } } } } catch (Exception e) { e.printStackTrace(); } } }
アクティビティを作成します。
public class MyCameraActivity extends Activity { private MySurfaceView mPreview; private final int FC = ViewGroup.LayoutParams.FILL_PARENT; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); mPreview = new MySurfaceView(this); setContentView(mPreview); // Keep screen on getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } @Override protected void onResume() { super.onResume(); } @Override protected void onPause() { // Keep screen off getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); super.onPause(); } @Override protected void onDestroy() { super.onDestroy(); } }
任意の場所や、パラメータを指定して保存する場合
import java.io.*; import java.util.List; import android.util.Log; import android.content.Context; import android.content.ContentResolver; import android.content.ContentValues; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.MotionEvent; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.ShutterCallback; import android.graphics.Bitmap; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; import android.provider.MediaStore.Images; import android.text.format.DateFormat; public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { private Context mContext; private Camera mCamera; private boolean mFlag; private static final String TAG = "MySurfaceView"; private static final Uri IMAGE_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; private static final String PATH = Environment.getExternalStorageDirectory().toString() + "/DCIM/Sample"; MySurfaceView(Context context) { super(context); mContext = context; SurfaceHolder mHolder = getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { mCamera = Camera.open(); try { mCamera.setPreviewDisplay(holder); } catch (IOException ex) { mCamera.release(); mCamera = null; } } public void surfaceDestroyed(SurfaceHolder holder) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { setPictureFormat(format); setPreviewSize(w, h); mCamera.startPreview(); } @Override public boolean onTouchEvent(MotionEvent event) { // オートフォーカスで撮影 this.autoFocus(); // オートフォーカスなしで撮影 //this.takePicture(); return super.onTouchEvent(event); } public void autoFocus() { if(mFlag) { return; } mFlag = true; mCamera.autoFocus(new AutoFocusCallback() { @Override public void onAutoFocus(boolean success, final Camera camera) { // イメージの取得を開始、リスナーを設定。 camera.takePicture(mShutterListener, // シャッター後 rawListener, // Rawイメージ生成後 jpegListener); // Jpegイメージ生成後 } }); } public void takePicture() { if(mFlag) { return; } mFlag = true; if (mCamera != null) { // イメージの取得を開始する。リスナーを設定する mCamera.takePicture(mShutterListener, // シャッター後 rawListener, // Rawイメージ生成後 jpegListener); // Jpegイメージ生成後 } } ShutterCallback mShutterListener = new ShutterCallback() { @Override public void onShutter() { Log.d(TAG, "onShutter"); } }; PictureCallback rawListener = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { Log.d(TAG, "onPictureTaken: raw: data=" + data); } }; // PictureCallback jpegなどが生成された後に呼び出される private PictureCallback jpegListener = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // 保存 addImageAsApplication(mContext.getContentResolver(), data); new Thread() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException ex) { Log.w(TAG, ex); } mFlag = false; mCamera.startPreview(); } }.start(); } }; private static String createName(long dateTaken) { return DateFormat.format("yyyy-MM-dd_kk.mm.ss", dateTaken).toString(); } public static Uri addImageAsApplication(ContentResolver cr, byte[] jpegData) { long dateTaken = System.currentTimeMillis(); String name = createName(dateTaken) + ".jpg"; return addImageAsApplication(cr, name, dateTaken, PATH, name, null, jpegData); } public static Uri addImageAsApplication(ContentResolver cr, String name, long dateTaken, String directory, String filename, Bitmap source, byte[] jpegData) { OutputStream outputStream = null; String filePath = directory + "/" + filename; try { File dir = new File(directory); if (!dir.exists()) { dir.mkdirs(); } File file = new File(directory, filename); if (file.createNewFile()) { outputStream = new FileOutputStream(file); outputStream.write(jpegData); } } catch (FileNotFoundException ex) { Log.w(TAG, ex); return null; } catch (IOException ex) { Log.w(TAG, ex); return null; } finally { if (outputStream != null) { try { outputStream.close(); } catch (Throwable t) { } } } ContentValues values = new ContentValues(7); values.put(Images.Media.TITLE, name); values.put(Images.Media.DISPLAY_NAME, filename); values.put(Images.Media.DESCRIPTION, filename); values.put(Images.Media.DATE_TAKEN, dateTaken); values.put(Images.Media.MIME_TYPE, "image/jpeg"); values.put(Images.Media.DATA, filePath); return cr.insert(IMAGE_URI, values); } protected void setPreviewSize(int width, int height) { Camera.Parameters params = mCamera.getParameters(); List<Camera.Size> supported = params.getSupportedPreviewSizes(); if (supported != null) { for (Camera.Size size : supported) { if (size.width <= width && size.height <= height) { params.setPreviewSize(size.width, size.height); mCamera.setParameters(params); break; } } } } protected void setPictureFormat(int format) { try { Camera.Parameters params = mCamera.getParameters(); List<Integer> supported = params.getSupportedPictureFormats(); if (supported != null) { for (int f : supported) { if (f == format) { params.setPreviewFormat(format); mCamera.setParameters(params); break; } } } } catch (Exception e) { e.printStackTrace(); } } }
圧縮して保存する場合
※写真を加工する際は一度Bitmapに変換する必要があります。
import android.graphics.Bitmap.CompressFormat; //追加インポート // PictureCallback jpegなどが生成された後に呼び出される private PictureCallback jpegListener = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // 保存する処理 //カメラのイメージ Bitmap cameraMap = BitmapFactory.decodeByteArray(data, 0, data.length, null); // 保存 addImageAsApplication(mContext.getContentResolver(), cameraMap); new Thread() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException ex) { Log.w(TAG, ex); } mFlag = false; mCamera.startPreview(); } }.start(); } }; private static String createName(long dateTaken) { return DateFormat.format("yyyy-MM-dd_kk.mm.ss", dateTaken).toString(); } public static Uri addImageAsApplication(ContentResolver cr, Bitmap bitmap) { long dateTaken = System.currentTimeMillis(); String name = createName(dateTaken) + ".jpg"; return addImageAsApplication(cr, name, dateTaken, PATH, name, bitmap, null); } public static Uri addImageAsApplication(ContentResolver cr, String name, long dateTaken, String directory, String filename, Bitmap source, byte[] jpegData) { OutputStream outputStream = null; String filePath = directory + "/" + filename; try { File dir = new File(directory); if (!dir.exists()) { dir.mkdirs(); } File file = new File(directory, filename); if (file.createNewFile()) { outputStream = new FileOutputStream(file); if (source != null) { source.compress(CompressFormat.JPEG, 75, outputStream); } else { outputStream.write(jpegData); } } } catch (FileNotFoundException ex) { Log.w(TAG, ex); return null; } catch (IOException ex) { Log.w(TAG, ex); return null; } finally { if (outputStream != null) { try { outputStream.close(); } catch (Throwable t) { } } } ContentValues values = new ContentValues(7); values.put(Images.Media.TITLE, name); values.put(Images.Media.DISPLAY_NAME, filename); values.put(Images.Media.DESCRIPTION, filename); values.put(Images.Media.DATE_TAKEN, dateTaken); values.put(Images.Media.MIME_TYPE, "image/jpeg"); values.put(Images.Media.DATA, filePath); return cr.insert(IMAGE_URI, values); }
その他、カメラのパラメータ色々
protected void setPictureFormat(int format) { try { Camera.Parameters params = camera.getParameters(); List<Integer> supported = params.getSupportedPictureFormats(); if (supported != null) { for (int f : supported) { if (f == format) { params.setPreviewFormat(format); camera.setParameters(params); break; } } } } catch (Exception e) { e.printStackTrace(); } } protected void setPreviewSize(int width, int height) { Camera.Parameters params = camera.getParameters(); List<Camera.Size> supported = params.getSupportedPreviewSizes(); if (supported != null) { for (Camera.Size size : supported) { if (size.width <= width && size.height <= height) { params.setPreviewSize(size.width, size.height); camera.setParameters(params); break; } } } } protected void setAntibanding(String antibanding) { Camera.Parameters params = camera.getParameters(); List<String> supported = params.getSupportedAntibanding(); if (supported != null) { for (String ab : supported) { if (ab.equals(antibanding)) { params.setAntibanding(antibanding); camera.setParameters(params); break; } } } } protected void setColorEffect(String effect) { Camera.Parameters params = camera.getParameters(); List<String> supported = params.getSupportedColorEffects(); if (supported != null) { for (String e : supported) { if (e.equals(effect)) { params.setColorEffect(effect); camera.setParameters(params); break; } } } } protected void setFlashMode(String flash_mode) { Camera.Parameters params = camera.getParameters(); List<String> supported = params.getSupportedFlashModes(); if (supported != null) { for (String fm : supported) { if (fm.equals(flash_mode)) { params.setFlashMode(flash_mode); camera.setParameters(params); break; } } } } protected void setFocusMode(String focus_mode) { Camera.Parameters params = camera.getParameters(); List<String> supported = params.getSupportedFocusModes(); if (supported != null) { for (String fm : supported) { if (fm.equals(focus_mode)) { params.setFocusMode(focus_mode); camera.setParameters(params); break; } } } } protected void setSceneMode(String scene_mode) { Camera.Parameters params = camera.getParameters(); List<String> supported = params.getSupportedSceneModes(); if (supported != null) { for (String sm : supported) { if (sm.equals(scene_mode)) { params.setSceneMode(scene_mode); camera.setParameters(params); break; } } } } protected void setWhiteBalance(String white_balance) { Camera.Parameters params = camera.getParameters(); List<String> supported = params.getSupportedWhiteBalance(); if (supported != null) { for (String wb : supported) { if (wb.equals(white_balance)) { params.setWhiteBalance(white_balance); camera.setParameters(params); break; } } } } protected void setColorEffects(String color_effects) { Camera.Parameters params = mCamera.getParameters(); List<String> supported = params.getSupportedColorEffects(); if (supported != null) { for (String ce : supported) { if (ce.equals(color_effects)) { params.setColorEffect(color_effects); mCamera.setParameters(params); break; } } } }
4,802 views