Categories
SugiBlog ホームページ制作・システム開発

カメラを扱うまとめ – Android

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;
            }
        }
    }
}
2,618 views

コメントを残す

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

*