Extensions API

CameraX には次の特殊効果を利用するための Extensions API が用意され、メーカーによりさまざまな Android デバイス(スマートフォン、タブレットなど)に実装されています。

  • 自動: 周囲の風景に合わせて画像の仕上がりを自動的に調整します。たとえば、ベンダー ライブラリの実装では、ローライトの検出を行い、ローライト モードまたは HDR モードに切り替えて写真を撮影できます。また、ポートレートを撮影する際には顔写真加工モードが自動的に適用されます。自動モードでは、モードの選択がベンダー ライブラリの実装に委ねられます。
  • ボケ: ボケモードは、手前の人物がはっきり見えるようにし、写真の背景をぼかします。通常、大きなレンズが付いたカメラで撮影する写真のようなポートレート写真を撮影することを目的としています。
  • 顔写真加工: 静止画像を撮影する際に顔の肌の色、形状などを加工します。
  • HDR(ハイ ダイナミック レンジ): HDR モードで写真を撮ると、幅広い光量レベルの風景が最終的な画像に写るようになります。たとえば、明るい窓の前で物体の写真を撮影する場合、通常モードでは物体と窓越しの風景のどちらか一方がほとんど写りませんが、HDR モードを使用すると両方が写るようになります。しかし、HDR モードでは通常 1 つの画像のキャプチャにかなり長い時間がかかり、ユーザーによる制御はできません。また、使用する HDR 方式によっては他のアーティファクトが表示される可能性があります。
  • 夜間: 暗い場所で(通常は夜間に)静止画像をきれいに撮影します。

デバイスでこのようなベンダー拡張機能をサポートするには、デバイスが次の要件を満たしている必要があります。

  • デバイスの ROM から、この効果に対するライブラリ サポートが提供されている。
  • ROM ライブラリが現在のデバイスにインストールされている。
  • デバイスに、ライブラリに必要なバージョンのオペレーティング システムがインストールされている。

拡張機能は選択的に有効にできます。拡張機能がデバイスでサポートされており、かつ物理的に利用できる場合は有効になります。該当しない場合は、グレースフル デグラデーションが行われます。

ベンダーはすべての効果および機能の実装を提供する必要はありません。ベンダー提供の実装がない機能の場合、デフォルトで CameraX の実装が適用されます。デフォルトの実装では機能を利用できないことが報告され、その有効化がスキップされます。

拡張機能のアーキテクチャ

次の図は、CameraX を使用した拡張機能のアーキテクチャを示しています。

図 1. 拡張機能の CameraX アーキテクチャ

拡張機能は CameraX の Camera2 コアとは別のものです。図の赤い矢印は、ユーザーが拡張機能ベースの機能(HDR 画像キャプチャなど)をトリガーしたときのメインとなるデータフローを示しています。

画像キャプチャとプレビューの効果を有効にする

Extensions API を使用する前に、ExtensionsManager#getInstanceAsync(Context、CameraProvider)メソッドを使用して ExtensionsManager インスタンスを取得します。これにより、拡張機能の可用性情報をクエリできます。次に、拡張機能が有効になっている CameraSelector を取得します。CameraSelector 拡張機能を有効にして bindToLifecycle() メソッドを呼び出すとき、画像キャプチャとプレビューのユースケースに拡張機能モードが適用されます。

画像キャプチャとプレビューのユースケースの拡張機能を実装するには、次のコードサンプルをご覧ください。

Kotlin

import androidx.camera.extensions.ExtensionMode
import androidx.camera.extensions.ExtensionsManager

fun onCreate() {
    // Create a camera provider
    val cameraProvider : ProcessCameraProvider = ... // Get the provider instance

    lifecycleScope.launch {
        // Create an extensions manager
        val extensionsManager =
                ExtensionsManager.getInstanceAsync(context, cameraProvider).await()

        // Select the camera
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

        // Query if extension is available.
        if (extensionsManager.isExtensionAvailable(
                cameraSelector,
                ExtensionMode.BOKEH
            )
        ) {
            // Unbind all use cases before enabling different extension modes.
            cameraProvider.unbindAll()

            // Retrieve extension enabled camera selector
            val bokehCameraSelector = extensionsManager.getExtensionEnabledCameraSelector(
                cameraSelector,
                ExtensionMode.BOKEH
            )

            // Bind image capture and preview use cases with the extension enabled camera selector.
            val imageCapture = ImageCapture.Builder().build()
            val preview = Preview.Builder().build()
            cameraProvider.bindToLifecycle(
                lifecycleOwner,
                bokehCameraSelector,
                imageCapture,
                preview
            )
        }
    }
}

Java

import androidx.camera.extensions.ExtensionMode;
import androidx.camera.extensions.ExtensionsManager;

void onCreate() {
    // Create a camera provider
    ProcessCameraProvider cameraProvider = ... // Get the provider instance

    // Call the getInstanceAsync function to retrieve a ListenableFuture object
    ListenableFuture future =
            ExtensionsManager.getInstanceAsync(context, cameraProvider);

    // Obtain the ExtensionsManager instance from the returned ListenableFuture object
    future.addListener(() -> {
        try {
            ExtensionsManager extensionsManager = future.get();

            // Select the camera
            CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;

            // Query if extension is available.
            if (extensionsManager.isExtensionAvailable(cameraSelector, ExtensionMode.BOKEH)) {
                // Unbind all use cases before enabling different extension modes.
                cameraProvider.unbindAll();

                // Retrieve extension enabled camera selector
                CameraSelector bokehCameraSelector = extensionsManager
                    .getExtensionEnabledCameraSelector(cameraSelector, ExtensionMode.BOKEH);

                // Bind image capture and preview use cases with the extension enabled camera selector.
                ImageCapture imageCapture = new ImageCapture.Builder().build();
                Preview preview = new Preview.Builder().build();
                cameraProvider.bindToLifecycle(lifecycleOwner, bokehCameraSelector, imageCapture, preview);
            }
        } catch (ExecutionException | InterruptedException e) {
            // This should not happen unless the future is cancelled or the thread is interrupted by
            // applications.
        }
    }, ContextCompact.getMainExecutor(context));
}

効果を無効にする

ベンダー拡張機能を無効にするには、すべてのユースケースをアンバインドし、画像キャプチャとプレビューのユースケースを通常のカメラセレクタで再バインドします。たとえば、CameraSelector.DEFAULT_BACK_CAMERA を使用して背面カメラに再バインドします。

依存関係

CameraX の Extensions API は、camera-extensions ライブラリに実装されています。拡張機能は CameraX コアモジュール(corecamera2lifecycle)に依存します。

Groovy

dependencies {
  def camerax_version = "1.1.0-alpha08"
  implementation "androidx.camera:camera-core:${camerax_version}"
  implementation "androidx.camera:camera-camera2:${camerax_version}"
  implementation "androidx.camera:camera-lifecycle:${camerax_version}"
  //the CameraX Extensions library
  implementation "androidx.camera:camera-extensions:1.0.0-alpha28"
    ...
}

Kotlin

dependencies {
  val camerax_version = "1.1.0-alpha08"
  implementation("androidx.camera:camera-core:${camerax_version}")
  implementation("androidx.camera:camera-camera2:${camerax_version}")
  implementation("androidx.camera:camera-lifecycle:${camerax_version}")
  // the CameraX Extensions library
  implementation("androidx.camera:camera-extensions:1.0.0-alpha28")
    ...
}

以前の API の削除

1.0.0-alpha26 での新しい Extensions API のリリースに伴い、2019 年 8 月にリリースされた以前の Extensions API のサポートは終了しました。バージョン 1.0.0-alpha28 以降、以前の Extensions API はライブラリから削除されています。新しい Extensions API を使用するアプリは、拡張機能が有効な CameraSelector を取得し、ユースケースをバインドする際に使用する必要があります。

以前の Extensions API を使用しているアプリは、今後の CameraX のリリースとの将来的な互換性を確保するために、新しい Extensions API に移行する必要があります。

参考情報

CameraX について詳しくは、以下の参考情報をご確認ください。

Codelab

  • CameraX のスタートガイド
  • コードサンプル

  • CameraX のサンプルアプリ
  • その他のリファレンス

    CameraX ベンダー拡張機能

    CameraX ベンダー拡張機能検証ツール