Extensions API

CameraX 提供 Extensions API,可供您使用製造商在各款 Android 裝置 (手機、平板電腦等) 導入的以下特效:

  • 自動模式:根據周圍場景自動調整最終圖像。舉例來說,廠商導入的程式庫可能會執行低光源偵測功能,而在拍照時切換到低光源模式或 HDR 模式;或是在拍攝肖像時自動套用修容模式。自動模式可讓廠商導入的程式庫選取模式。
  • 散景模式:這種模式會凸顯前景人物,使其看起來更為清晰,相片的背景則會模糊處理。通常拍攝肖像時會使用這種模式,效果會與使用大鏡頭相機類似。
  • 修容模式:這種模式在拍攝靜態圖像時,可以潤飾臉部膚色以及幾何線條等。
  • 高動態範圍 (HDR) 模式:這種模式在拍攝明暗不一的場景時,可以將多種不同的亮度細節清晰呈現在相片成品。舉例來說,在光線明亮的窗前拍攝物件時,使用 HDR 模式可讓物件與窗外場景皆清晰可見;但在一般模式下,其中之一可能會有曝光不足的現象。但使用 HDR 的代價是,透過這種模式拍攝照片通常需要較長作業時間,而且使用者無法從中掌控。且根據使用的 HDR 方法,也可能產生不同拍攝成果。
  • 夜視模式:這種模式可在弱光環境下 (通常為夜間),取得最佳靜態圖像。

如果裝置要支援上述廠商的擴充功能,必須符合下列要求:

  • 裝置的 ROM 為對應效果提供程式庫支援。
  • 目前裝置已安裝 ROM 程式庫。
  • 裝置已搭載程式庫所需的作業系統版本。

只要裝置「支援」且「已安裝」某項擴充功能,該擴充功能就會優先啟用,否則會以優雅降級的方式處置。

廠商不需導入每一種效果和功能,未導入的功能會直接預設為導入 CameraX。預設的導入項目會回報無法使用對應功能,並略過啟用程序。

擴充功能架構

下圖顯示搭載 CameraX 的擴充功能架構。

圖 1 CameraX 擴充功能架構

擴充功能與 CameraX 的核心 API 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

發布新版 Extensions API (1.0.0-alpha26 版本) 後,我們目前已淘汰於 2019 年 8 月發布的舊版 Extensions API。自 1.0.0-alpha28 版本起,舊版 Extensions API 已從程式庫中移除。現在,使用新版 Extensions API 的應用程式,必須取得已啟用擴充功能的 CameraSelector,並用其繫結用途。

使用舊版 Extensions API 的應用程式,則應遷移到新版 Extensions API,以確保日後與即將發布的 CameraX 版本相容。

其他資源

如要進一步瞭解 CameraX,請參閱下列其他資源。

程式碼研究室

  • 開始使用 CameraX
  • 程式碼範例

  • CameraX 範例應用程式
  • 其他參考資料

    CameraX 廠商擴充功能

    CameraX 廠商擴充功能驗證工具