API de Extensions

CameraX proporciona una API de Extensions para acceder a los siguientes efectos especiales que los fabricantes implementaron en varios dispositivos Android (teléfonos, tablets y otros):

  • Automático: Ajusta automáticamente la imagen final con el entorno. Por ejemplo, la implementación de la biblioteca del proveedor puede realizar una detección de poca luz y cambiar al modo noche o al HDR para tomar una foto, o bien la biblioteca puede aplicar automáticamente un modo de retoque facial al tomar una imagen vertical. El modo automático deja la selección del modo en la implementación de la biblioteca del proveedor.
  • Bokeh: El modo bokeh hace que el personaje en primer plano se vea más nítido y desenfoca el fondo de una foto. Por lo general, está diseñado para tomar fotos verticales de personas similares a las que produciría una cámara con una lente grande.
  • Retoque facial: Retoca el tono de piel, la geometría, etc., cuando se toman imágenes estáticas.
  • HDR (Alto rango dinámico): El modo HDR toma fotos que mantienen un rango más amplio de niveles de iluminación en el ambiente en la imagen final. Por ejemplo, cuando se toma la foto de un objeto frente a una ventana brillante, tanto el objeto como el ambiente pueden ser visibles a través de la ventana cuando se usa el modo HDR, mientras que en el modo normal, uno u otro podría no estar bien expuesto. Como desventaja, el modo HDR suele demorar mucho más en capturar una sola imagen, no tiene control por parte del usuario y, según el método HDR que use, puede tener otros artefactos.
  • Nocturno: Obtiene las mejores imágenes estáticas en situaciones con poca luz, por lo general, de noche.

Para que un dispositivo admita dichas extensiones de proveedores, debe cumplir con los siguientes requisitos:

  • El efecto debe admitir la biblioteca del ROM del dispositivo.
  • La biblioteca del ROM debe estar instalada en el dispositivo actual.
  • El dispositivo debe contar con la versión del sistema operativo que requiera la biblioteca.

Puedes habilitar una extensión de manera preferencial: si la extensión es compatible con el dispositivo y la tienes instalada, entonces estará habilitada. De lo contrario, se ajustará de manera óptima para versiones anteriores.

Los proveedores no tienen la obligación de proporcionar una implementación para cada efecto y función. Toda función que no tenga una implementación proporcionada por el proveedor se agregará de forma predeterminada a la implementación de CameraX. La implementación predeterminada informa que la función no está disponible y omite la habilitación.

Arquitectura de extensiones

En la siguiente imagen, se muestra la arquitectura de extensiones con CameraX.

Figura 1: Arquitectura de CameraX para extensiones

Las extensiones son independientes del núcleo Camera2 de CameraX. En el diagrama, las flechas rojas indican el flujo de datos principal cuando los usuarios activan una función basada en extensiones, como la captura de imágenes HDR.

Habilita un efecto para la captura de imágenes y la vista previa

Antes de usar la API de extensiones, recupera una instancia de ExtensionsManager mediante el método ExtensionsManager#getInstanceAsync(Context, CameraProvider). Esto te permitirá consultar la información de disponibilidad de extensiones. Luego, recupera un CameraSelector de extensión habilitada. El modo de extensión se aplicará en los casos de uso de captura de imágenes y de vista previa cuando se llame al método bindToLifecycle() con la extensión CameraSelector habilitada.

Si deseas implementar la extensión para los casos de uso de captura de imágenes y de vista previa, consulta la siguiente muestra de código:

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));
}

Inhabilita el efecto

Para inhabilitar las extensiones de proveedor, desvincula todos los casos de uso y vuelve a vincular los de captura de imagen y de vista previa con un selector de cámara normal. Por ejemplo, vuelve a vincular la cámara posterior con CameraSelector.DEFAULT_BACK_CAMERA.

Dependencias

La API de Extensions de CameraX se implementa en la biblioteca camera-extensions. Las extensiones dependen de los módulos principales de CameraX (core, camera2, lifecycle).

Groovy

dependencies {
  def camerax_version = "1.2.0-alpha04"
  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:${camerax_version}"
    ...
}

Kotlin

dependencies {
  val camerax_version = "1.2.0-alpha04"
  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:${camerax_version}")
    ...
}

Eliminación de la API heredada

Con la nueva API de Extensions versión 1.0.0-alpha26, su API heredada, cuyo lanzamiento fue en agosto de 2019, es ahora obsoleta. A partir de la versión 1.0.0-alpha28, se quitó la API de Extensions heredada de la biblioteca. Las aplicaciones que usan la nueva API de Extensions ahora deben adquirir un CameraSelector habilitado para extensiones y usarlo a fin de vincular los casos de uso.

Las aplicaciones que usan la API de Extensions heredadas deben migrar a su nueva versión para garantizar la compatibilidad futura con los próximos lanzamientos de CameraX.

Recursos adicionales

Para obtener más información acerca de CameraX, consulta los siguientes recursos adicionales.

Codelab

  • Comienza a usar CameraX
  • Muestra de código

  • Apps de ejemplo de CameraX
  • Otras referencias

    Extensiones de proveedores de CameraX

    Herramienta de validación de extensiones de proveedor de CameraX