LoginSignup
1
3

More than 3 years have passed since last update.

Android の Camera2 API を使って RAW モードで撮影する

Last updated at Posted at 2019-06-22

Android の Camera2 API を使って カメラのプレビュー画面を表示する
の続きです。

RAW モード

一般的なデジカメやスマホは、撮影した画像をJPEG形式で保存する。
JPEG形式は、非可逆の圧縮方式なので、カメラ本来の画質より劣化する。
デジタル一眼などの専用機種では、
カメラ本来の画質で保存するRAW モードをサポートしている。

参考 : RAWデータとは

DNG フォーマット

RAW モードの画像保存は、カメラメーカーが独自のフォーマットを使用している。
カメラメーカーが提供する専用ソフトでないと、閲覧や編集することができない。
DNG 形式は、Adobeが推奨しているRAW モードの画像ファイルのフォーマットです。

参考 : PhotoshopとDNGの将来

Android端末の対応

Android OS では、API 21 から RAW モードで撮影保存するAPIを提供している。
ただし、機種依存なのですべての端末で利用出来るわけではない。

画像保存は、DNG フォーマットを採用している。

一方で、DNG フォーマットを閲覧編集するAPIは、提供されていない。
そのため、標準の画像閲覧アプリでは、閲覧編集もできない。

Adobeから 写真加工・編集アプリ Lightroom Mobile の Android 版が提供されているので、それを利用する。

Google Play : Adobe Lightroom

端末が RAW モードの撮影をサポートしているか

下記のように判定する。

contains(characteristics.get(
                                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES),
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)

reference : REQUEST_AVAILABLE_CAPABILITIES

Raw モードで撮影する

基本的な処理は、JPEG 形式の写真を撮影するときと同じです。
下記を参考のこと。

Camera2 API を使って 写真を撮る

ImageReader

JPEG 形式のときは、カメラからの画像をキャプチャーするために ImageReader を生成した。

同様に、Raw モード用の ImageReader を生成する

        CameraCharacteristics  characteristics;
        ImageReader.OnImageAvailableListener rawImageAvailableListener;

        StreamConfigurationMap map = characteristics.get(
                        CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

// Raw モードの画像サイズを取得する
        Size largestRaw = Collections.max(
                        Arrays.asList(map.getOutputSizes(ImageFormat.RAW_SENSOR)),
                        new CompareSizesByArea());

// ImageReader を生成する
        ImageReader imageReaderRaw =
                                ImageReader.newInstance( 
                                        largestRaw.getWidth(),
                                        largestRaw.getHeight(), ImageFormat.RAW_SENSOR, 
                                        4);
// リスナーを設定する
        imageReaderRaw.setOnImageAvailableListener(
                            rawImageAvailableListener, backgroundHandler);

reference : ImageReader

DNG形式でファイルに保存する

JPEG形式のときは、ImageReader にキャプチャーされた Image から Bitmap を取得し保存した。

Raw モードでは、DngCreator を使って下記のように保存する。

    CameraCharacteristics characteristics;
    CaptureResult captureResult;
    Image image;
    File file;

    DngCreator dngCreator  = new DngCreator(characteristics, captureResult);

    try {
            FileOutputStream output = new FileOutputStream(file);
            dngCreator.writeImage(output, image);
    } catch (IOException e) {
            e.printStackTrace();
    }

reference : DngCreator

DngCreator の機能は、reference だけだとわかりにくい。
ソースコードも読んでおくといい。

ソースコード : DngCreator.java

Media Content Provider に登録する

Lightroom Mobile などの閲覧編集アプリから参照できるように、
画像ファイルを Media Content Provider に登録する。

        File file;
        MediaScannerConnection.MediaScannerConnectionClient mediaScannerConnectionClient;

        String[] paths = new String[]{ file.getPath() };
        MediaScannerConnection.scanFile(context, paths, null, mediaScannerConnectionClient );

reference : scanFile

JPEG画像との併用

公式サンプルでは、DNG 形式と同時に JPEG 形式でも撮影保存している。

DNG 形式 と JPEG 形式 は 3264x2448 と画像のサイズは同じでも、
ファイルサイズは DNG 形式 はJPEG 形式に比べ 5〜6倍になる

DNG : 3264x2448 15.44 MB
JPEG : 3264x2448 2.8MB

DNG 形式 という高画質の画像があるので、
JPEG 形式はサムネイル的な小さい画像のサイズでもいい。
そこで、JPEG 形式でファイル保存するときに、画像サイズを小さくする。

    Bitmap  srcBitmap;
    int desiredSize;

    int bitmap_width = srcBitmap.getWidth();
    int bitmap_height = srcBitmap.getHeight();
    int max = Math.max(bitmap_width, bitmap_height);
    double scale = (double)desiredSize/ (double)max;
    int scaled_width =  (int) ( (double)bitmap_width * scale );
    int scaled_height =  (int) ( (double)bitmap_height * scale );
    Bitmap resized_bitmap = Bitmap.createScaledBitmap(srcBitmap,
        scaled_width, scaled_height, true);

reference : createScaledBitmap

これにより、ファイルサイズは 12分の1に減少する。

JPEG 原寸: 3264x2448  2.8MB
JPEG サムネイル: 480x640 243KB 

Camera2Basic と Camera2Raw の違い

Rawモードの撮影は、上記のようにCamera2Basicをベースに、RAW用のImage Readerを追加すれば、いいのですが。
それ以外にも違いがあります。

Camera2Basic を読み解くだけで、お腹いっぱいです。
Camera2Raw と読み比べしたら、パンクしそう。

 自動ホワイトバランス

Camera2Raw は、自動ホワイトバランスを設定している。
これは画質に大きく左右するので、納得です。
一方で、Camera2Basicでは、なぜ設定していないのか、疑問になる。
推測するに、その頃は対応している実機がなかったのかな。

 RefCountedAutoCloseable

imgereaderのリソース管理のための AutoCloseable のラッパークラス。
imgereaderをそのまま使うのではなく、このクラスでラップしている。
連続して撮影するときに、imgereader を複数作成するので、
その管理のためと思われる。
今回は、ひとまずなしで。

PendingUserCaptures

PICTUREボタンをクリックした数

連続して撮影するときに、すぐに実行せず、カメラデバイスの状態に応じて、順次処理するための変数。
今回は、ひとまずなしで。

サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/Camera214

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3