カテゴリー
SugiBlog Webエンジニアのためのお役立ちTips

カメラを扱うまとめ – Android

この記事は最終更新日から1年以上経過しています。

Androidでカメラを扱うまとめです。
単純に撮った写真を保存するパターンと、パラメーターを指定して保存するパターン、
撮影した画像を圧縮して保存するパターンの3パターンを紹介します。

まずは、カメラを使用するために必要なパーミッションをAndroidManifest.xmlに記述します。

1<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2<uses-permission android:name="android.permission.CAMERA" />
3<uses-permission android:name="android.permission.FLASHLIGHT" />
4 
5<uses-feature android:name="android.hardware.camera" />
6<uses-feature android:name="android.hardware.camera.autofocus" />
7<uses-feature android:name="android.hardware.camera.flash" />

撮影処理をするSurfaceViewを継承したクラスを作成します。

まず、簡単に保存するパターン

1import java.io.*;
2import java.util.List;
3 
4import android.util.Log;
5import android.content.Context;
6 
7import android.view.SurfaceHolder;
8import android.view.SurfaceView;
9import android.view.MotionEvent;
10 
11import android.hardware.Camera;
12import android.hardware.Camera.AutoFocusCallback;
13import android.hardware.Camera.PictureCallback;
14import android.hardware.Camera.ShutterCallback;
15 
16import android.graphics.*;
17import android.provider.MediaStore;
18 
19public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
20    private Context mContext;
21    private Camera mCamera;
22    private boolean mFlag;
23    private static final String TAG = "MySurfaceView";
24 
25    MySurfaceView(Context context) {
26        super(context);
27        mContext = context;
28        SurfaceHolder mHolder = getHolder();
29        mHolder.addCallback(this);
30        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
31    }
32 
33    public void surfaceCreated(SurfaceHolder holder) {
34        mCamera = Camera.open();
35        try {
36            mCamera.setPreviewDisplay(holder);
37        } catch (IOException ex) {
38            mCamera.release();
39            mCamera = null;
40        }
41    }
42 
43    public void surfaceDestroyed(SurfaceHolder holder) {
44        mCamera.stopPreview();
45        mCamera.release();
46        mCamera = null;
47    }
48 
49    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
50        setPictureFormat(format);
51        setPreviewSize(w, h);
52        mCamera.startPreview();
53    }
54 
55    @Override
56    public boolean onTouchEvent(MotionEvent event) {
57 
58        // オートフォーカスで撮影
59        this.autoFocus();
60 
61        // オートフォーカスなしで撮影
62        //this.takePicture();
63 
64        return super.onTouchEvent(event);
65    }
66 
67    public void autoFocus() {
68        if(mFlag) { return; }
69        mFlag = true;
70        mCamera.autoFocus(new AutoFocusCallback() {
71            @Override
72            public void onAutoFocus(boolean success, final Camera camera) {
73                // イメージの取得を開始、リスナーを設定。
74                camera.takePicture(mShutterListener, // シャッター後
75                        rawListener,                 // Rawイメージ生成後
76                        jpegListener);               // Jpegイメージ生成後
77            }
78        });
79    }
80 
81    public void takePicture() {
82        if(mFlag) { return; }
83        mFlag = true;
84        if (mCamera != null) {
85            // イメージの取得を開始、リスナーを設定。
86            mCamera.takePicture(mShutterListener, // シャッター後
87                    rawListener,                  // Rawイメージ生成後
88                    jpegListener);                // Jpegイメージ生成後
89        }
90    }
91 
92    ShutterCallback mShutterListener = new ShutterCallback() {
93        @Override
94        public void onShutter() {
95            Log.d(TAG, "onShutter");
96        }
97    };
98    PictureCallback rawListener = new PictureCallback() {
99        @Override
100        public void onPictureTaken(byte[] data, Camera camera) {
101            Log.d(TAG, "onPictureTaken: raw: data=" + data);
102        }
103    };
104 
105    // PictureCallback jpegなどが生成された後に呼び出される
106    private PictureCallback jpegListener = new PictureCallback() {
107        @Override
108        public void onPictureTaken(byte[] data, Camera camera) {
109            // 保存する処理
110            Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length, null);
111            // DCIM/Cameraに保存されます。
112            MediaStore.Images.Media.insertImage(mContext.getContentResolver(), bmp, "sample", null);
113 
114            new Thread() {
115                @Override
116                public void run() {
117                    try {
118                        Thread.sleep(1000);
119                    } catch (InterruptedException ex) {
120                        Log.w(TAG, ex);
121                    }
122                    mFlag = false;
123                    mCamera.startPreview();
124                }
125            }.start();
126        }
127    };
128 
129    protected void setPreviewSize(int width, int height) {
130        Camera.Parameters params = mCamera.getParameters();
131        List<Camera.Size> supported = params.getSupportedPreviewSizes();
132        if (supported != null) {
133            for (Camera.Size size : supported) {
134                if (size.width <= width && size.height <= height) {
135                    params.setPreviewSize(size.width, size.height);
136                    mCamera.setParameters(params);
137                    break;
138                }
139            }
140        }
141    }
142 
143    protected void setPictureFormat(int format) {
144        try {
145            Camera.Parameters params = mCamera.getParameters();
146            List<Integer> supported = params.getSupportedPictureFormats();
147            if (supported != null) {
148                for (int f : supported) {
149                    if (f == format) {
150                        params.setPreviewFormat(format);
151                        mCamera.setParameters(params);
152                        break;
153                    }
154                }
155            }
156        } catch (Exception e) {
157            e.printStackTrace();
158        }
159    }
160}

アクティビティを作成します。

1public class MyCameraActivity extends Activity {
2    private MySurfaceView mPreview;
3    private final int FC = ViewGroup.LayoutParams.FILL_PARENT;
4 
5    @Override
6    protected void onCreate(Bundle savedInstanceState) {
7        super.onCreate(savedInstanceState);
8        requestWindowFeature(Window.FEATURE_NO_TITLE);
9 
10        mPreview = new MySurfaceView(this);
11        setContentView(mPreview);
12 
13        // Keep screen on
14        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
15    }
16 
17    @Override
18    protected void onResume() {
19        super.onResume();
20    }
21 
22    @Override
23    protected void onPause() {
24        // Keep screen off
25        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
26        super.onPause();
27    }
28 
29    @Override
30    protected void onDestroy() {
31        super.onDestroy();
32    }
33 
34}

任意の場所や、パラメータを指定して保存する場合

1import java.io.*;
2import java.util.List;
3 
4import android.util.Log;
5import android.content.Context;
6import android.content.ContentResolver;
7import android.content.ContentValues;
8 
9import android.view.SurfaceHolder;
10import android.view.SurfaceView;
11import android.view.MotionEvent;
12 
13import android.hardware.Camera;
14import android.hardware.Camera.AutoFocusCallback;
15import android.hardware.Camera.PictureCallback;
16import android.hardware.Camera.ShutterCallback;
17 
18import android.graphics.Bitmap;
19import android.net.Uri;
20import android.os.Environment;
21import android.provider.MediaStore;
22import android.provider.MediaStore.Images;
23 
24import android.text.format.DateFormat;
25 
26public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
27    private Context mContext;
28    private Camera mCamera;
29    private boolean mFlag;
30    private static final String TAG = "MySurfaceView";
31    private static final Uri IMAGE_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
32    private static final String PATH = Environment.getExternalStorageDirectory().toString() + "/DCIM/Sample";
33 
34    MySurfaceView(Context context) {
35        super(context);
36        mContext = context;
37        SurfaceHolder mHolder = getHolder();
38        mHolder.addCallback(this);
39        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
40    }
41 
42    public void surfaceCreated(SurfaceHolder holder) {
43        mCamera = Camera.open();
44        try {
45            mCamera.setPreviewDisplay(holder);
46        } catch (IOException ex) {
47            mCamera.release();
48            mCamera = null;
49        }
50    }
51 
52    public void surfaceDestroyed(SurfaceHolder holder) {
53        mCamera.stopPreview();
54        mCamera.release();
55        mCamera = null;
56    }
57 
58    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
59        setPictureFormat(format);
60        setPreviewSize(w, h);
61        mCamera.startPreview();
62    }
63 
64    @Override
65    public boolean onTouchEvent(MotionEvent event) {
66 
67        // オートフォーカスで撮影
68        this.autoFocus();
69 
70        // オートフォーカスなしで撮影
71        //this.takePicture();
72 
73        return super.onTouchEvent(event);
74    }
75 
76    public void autoFocus() {
77        if(mFlag) { return; }
78        mFlag = true;
79        mCamera.autoFocus(new AutoFocusCallback() {
80            @Override
81            public void onAutoFocus(boolean success, final Camera camera) {
82                // イメージの取得を開始、リスナーを設定。
83                camera.takePicture(mShutterListener, // シャッター後
84                        rawListener,                 // Rawイメージ生成後
85                        jpegListener);               // Jpegイメージ生成後
86            }
87        });
88    }
89 
90    public void takePicture() {
91        if(mFlag) { return; }
92        mFlag = true;
93        if (mCamera != null) {
94            // イメージの取得を開始する。リスナーを設定する
95            mCamera.takePicture(mShutterListener, // シャッター後
96                    rawListener,                  // Rawイメージ生成後
97                    jpegListener);                // Jpegイメージ生成後
98        }
99    }
100 
101    ShutterCallback mShutterListener = new ShutterCallback() {
102        @Override
103        public void onShutter() {
104            Log.d(TAG, "onShutter");
105        }
106    };
107    PictureCallback rawListener = new PictureCallback() {
108        @Override
109        public void onPictureTaken(byte[] data, Camera camera) {
110            Log.d(TAG, "onPictureTaken: raw: data=" + data);
111        }
112    };
113 
114    // PictureCallback jpegなどが生成された後に呼び出される
115    private PictureCallback jpegListener = new PictureCallback() {
116        @Override
117        public void onPictureTaken(byte[] data, Camera camera) {
118            // 保存
119            addImageAsApplication(mContext.getContentResolver(), data);
120 
121            new Thread() {
122                @Override
123                public void run() {
124                    try {
125                        Thread.sleep(1000);
126                    } catch (InterruptedException ex) {
127                        Log.w(TAG, ex);
128                    }
129                    mFlag = false;
130                    mCamera.startPreview();
131                }
132            }.start();
133        }
134    };
135 
136    private static String createName(long dateTaken) {
137        return DateFormat.format("yyyy-MM-dd_kk.mm.ss", dateTaken).toString();
138    }
139 
140    public static Uri addImageAsApplication(ContentResolver cr, byte[] jpegData) {
141        long dateTaken = System.currentTimeMillis();
142        String name = createName(dateTaken) + ".jpg";
143        return addImageAsApplication(cr, name, dateTaken, PATH, name, null, jpegData);
144    }
145 
146    public static Uri addImageAsApplication(ContentResolver cr, String name,
147            long dateTaken, String directory,
148            String filename, Bitmap source, byte[] jpegData) {
149 
150        OutputStream outputStream = null;
151        String filePath = directory + "/" + filename;
152        try {
153            File dir = new File(directory);
154            if (!dir.exists()) {
155                dir.mkdirs();
156            }
157            File file = new File(directory, filename);
158            if (file.createNewFile()) {
159                outputStream = new FileOutputStream(file);
160                outputStream.write(jpegData);
161            }
162 
163        } catch (FileNotFoundException ex) {
164            Log.w(TAG, ex);
165            return null;
166        } catch (IOException ex) {
167            Log.w(TAG, ex);
168            return null;
169        } finally {
170            if (outputStream != null) {
171                try {
172                    outputStream.close();
173                } catch (Throwable t) {
174                }
175            }
176        }
177 
178        ContentValues values = new ContentValues(7);
179        values.put(Images.Media.TITLE, name);
180        values.put(Images.Media.DISPLAY_NAME, filename);
181        values.put(Images.Media.DESCRIPTION, filename);
182        values.put(Images.Media.DATE_TAKEN, dateTaken);
183        values.put(Images.Media.MIME_TYPE, "image/jpeg");
184        values.put(Images.Media.DATA, filePath);
185        return cr.insert(IMAGE_URI, values);
186    }
187 
188    protected void setPreviewSize(int width, int height) {
189        Camera.Parameters params = mCamera.getParameters();
190        List<Camera.Size> supported = params.getSupportedPreviewSizes();
191        if (supported != null) {
192            for (Camera.Size size : supported) {
193                if (size.width <= width && size.height <= height) {
194                    params.setPreviewSize(size.width, size.height);
195                    mCamera.setParameters(params);
196                    break;
197                }
198            }
199        }
200    }
201 
202    protected void setPictureFormat(int format) {
203        try {
204            Camera.Parameters params = mCamera.getParameters();
205            List<Integer> supported = params.getSupportedPictureFormats();
206            if (supported != null) {
207                for (int f : supported) {
208                    if (f == format) {
209                        params.setPreviewFormat(format);
210                        mCamera.setParameters(params);
211                        break;
212                    }
213                }
214            }
215        } catch (Exception e) {
216            e.printStackTrace();
217        }
218    }
219 
220}

圧縮して保存する場合
※写真を加工する際は一度Bitmapに変換する必要があります。

1import android.graphics.Bitmap.CompressFormat; //追加インポート
2 
3    // PictureCallback jpegなどが生成された後に呼び出される
4    private PictureCallback jpegListener = new PictureCallback() {
5        @Override
6        public void onPictureTaken(byte[] data, Camera camera) {
7            // 保存する処理
8            //カメラのイメージ
9            Bitmap cameraMap = BitmapFactory.decodeByteArray(data, 0,
10                    data.length, null);
11 
12            // 保存
13            addImageAsApplication(mContext.getContentResolver(), cameraMap);
14 
15            new Thread() {
16                @Override
17                public void run() {
18                    try {
19                        Thread.sleep(1000);
20                    } catch (InterruptedException ex) {
21                        Log.w(TAG, ex);
22                    }
23                    mFlag = false;
24                    mCamera.startPreview();
25                }
26            }.start();
27        }
28    };
29 
30    private static String createName(long dateTaken) {
31        return DateFormat.format("yyyy-MM-dd_kk.mm.ss", dateTaken).toString();
32    }
33 
34    public static Uri addImageAsApplication(ContentResolver cr, Bitmap bitmap) {
35        long dateTaken = System.currentTimeMillis();
36        String name = createName(dateTaken) + ".jpg";
37        return addImageAsApplication(cr, name, dateTaken, PATH, name, bitmap, null);
38    }
39 
40    public static Uri addImageAsApplication(ContentResolver cr, String name,
41            long dateTaken, String directory,
42            String filename, Bitmap source, byte[] jpegData) {
43 
44        OutputStream outputStream = null;
45        String filePath = directory + "/" + filename;
46        try {
47            File dir = new File(directory);
48            if (!dir.exists()) {
49                dir.mkdirs();
50            }
51            File file = new File(directory, filename);
52            if (file.createNewFile()) {
53                outputStream = new FileOutputStream(file);
54                if (source != null) {
55                    source.compress(CompressFormat.JPEG, 75, outputStream);
56                } else {
57                    outputStream.write(jpegData);
58                }
59            }
60 
61        } catch (FileNotFoundException ex) {
62            Log.w(TAG, ex);
63            return null;
64        } catch (IOException ex) {
65            Log.w(TAG, ex);
66            return null;
67        } finally {
68            if (outputStream != null) {
69                try {
70                    outputStream.close();
71                } catch (Throwable t) {
72                }
73            }
74        }
75 
76        ContentValues values = new ContentValues(7);
77        values.put(Images.Media.TITLE, name);
78        values.put(Images.Media.DISPLAY_NAME, filename);
79        values.put(Images.Media.DESCRIPTION, filename);
80        values.put(Images.Media.DATE_TAKEN, dateTaken);
81        values.put(Images.Media.MIME_TYPE, "image/jpeg");
82        values.put(Images.Media.DATA, filePath);
83        return cr.insert(IMAGE_URI, values);
84    }

その他、カメラのパラメータ色々

1protected void setPictureFormat(int format) {
2    try {
3        Camera.Parameters params = camera.getParameters();
4        List<Integer> supported = params.getSupportedPictureFormats();
5        if (supported != null) {
6            for (int f : supported) {
7                if (f == format) {
8                    params.setPreviewFormat(format);
9                    camera.setParameters(params);
10                    break;
11                }
12            }
13        }
14    } catch (Exception e) {
15        e.printStackTrace();
16    }
17}
18 
19protected void setPreviewSize(int width, int height) {
20    Camera.Parameters params = camera.getParameters();
21    List<Camera.Size> supported = params.getSupportedPreviewSizes();
22    if (supported != null) {
23        for (Camera.Size size : supported) {
24            if (size.width <= width && size.height <= height) {
25                params.setPreviewSize(size.width, size.height);
26                camera.setParameters(params);
27                break;
28            }
29        }
30    }
31}
32 
33protected void setAntibanding(String antibanding) {
34    Camera.Parameters params = camera.getParameters();
35    List<String> supported = params.getSupportedAntibanding();
36    if (supported != null) {
37        for (String ab : supported) {
38            if (ab.equals(antibanding)) {
39                params.setAntibanding(antibanding);
40                camera.setParameters(params);
41                break;
42            }
43        }
44    }
45}
46 
47protected void setColorEffect(String effect) {
48    Camera.Parameters params = camera.getParameters();
49    List<String> supported = params.getSupportedColorEffects();
50    if (supported != null) {
51        for (String e : supported) {
52            if (e.equals(effect)) {
53                params.setColorEffect(effect);
54                camera.setParameters(params);
55                break;
56            }
57        }
58    }
59}
60 
61protected void setFlashMode(String flash_mode) {
62    Camera.Parameters params = camera.getParameters();
63    List<String> supported = params.getSupportedFlashModes();
64    if (supported != null) {
65        for (String fm : supported) {
66            if (fm.equals(flash_mode)) {
67                params.setFlashMode(flash_mode);
68                camera.setParameters(params);
69                break;
70            }
71        }
72    }
73}
74 
75protected void setFocusMode(String focus_mode) {
76    Camera.Parameters params = camera.getParameters();
77    List<String> supported = params.getSupportedFocusModes();
78    if (supported != null) {
79        for (String fm : supported) {
80            if (fm.equals(focus_mode)) {
81                params.setFocusMode(focus_mode);
82                camera.setParameters(params);
83                break;
84            }
85        }
86    }
87}
88 
89protected void setSceneMode(String scene_mode) {
90    Camera.Parameters params = camera.getParameters();
91    List<String> supported = params.getSupportedSceneModes();
92    if (supported != null) {
93        for (String sm : supported) {
94            if (sm.equals(scene_mode)) {
95                params.setSceneMode(scene_mode);
96                camera.setParameters(params);
97                break;
98            }
99        }
100    }
101}
102 
103protected void setWhiteBalance(String white_balance) {
104    Camera.Parameters params = camera.getParameters();
105    List<String> supported = params.getSupportedWhiteBalance();
106    if (supported != null) {
107        for (String wb : supported) {
108            if (wb.equals(white_balance)) {
109                params.setWhiteBalance(white_balance);
110                camera.setParameters(params);
111                break;
112            }
113        }
114    }
115}
116 
117protected void setColorEffects(String color_effects) {
118    Camera.Parameters params = mCamera.getParameters();
119    List<String> supported = params.getSupportedColorEffects();
120    if (supported != null) {
121        for (String ce : supported) {
122            if (ce.equals(color_effects)) {
123                params.setColorEffect(color_effects);
124                mCamera.setParameters(params);
125                break;
126            }
127        }
128    }
129}
この記事がお役に立ちましたらシェアお願いします
4,852 views

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です