Decodificador de imágenes

La API ImageDecoder de NDK proporciona una API estándar para que las apps C/C++ de Android decodifiquen imágenes de forma directa. Los desarrolladores de apps ya no necesitan usar las API de Java (a través de JNI) ni las bibliotecas de decodificación de imágenes de terceros. Esta API, junto con las funciones de codificación en el módulo Bitmap, permite lo siguiente:

  • Las bibliotecas y las aplicaciones nativas pueden ser más pequeñas, porque ya no tienen que vincular sus propias bibliotecas de decodificación.
  • Las apps y las bibliotecas se benefician automáticamente de las actualizaciones de seguridad de la plataforma en las bibliotecas de decodificación.
  • Las apps pueden decodificar imágenes directamente en la memoria que proporcionan. Estas pueden procesar posteriormente los datos de la imagen (si lo deseas) y pasarlos a OpenGL o su código de dibujo.

En esta página, se describe cómo usar la API para decodificar una imagen.

Disponibilidad y capacidad

La API de ImageDecoder está disponible en apps orientadas a Android 11 (API nivel "R") o versiones posteriores. La implementación se encuentra dentro de los siguientes archivos:

  • imagedecoder.h para el decodificador
  • bitmap.h para el codificador
  • libjnigraphics.so

La API admite los siguientes formatos de imagen:

  • JPEG
  • PNG
  • GIF
  • WebP
  • BMP

  • ICO

  • WBMP

  • HEIF

  • Negativos digitales (a través del SDK de DNG)

Para abarcar todos los usos de las imágenes decodificadas sin procesar, esta API no proporciona objetos de nivel superior como los que se compilan sobre las imágenes decodificadas dentro del marco de trabajo de Java, a saber:

  • Objetos Drawable.
  • NinePatch: si está presente en una imagen codificada, se ignoran los fragmentos de NinePatch.
  • Densidad del mapa de bits: AImageDecoder no realiza ningún ajuste de tamaño automático según la densidad de la pantalla, pero permite decodificar en otro tamaño mediante AImageDecoder_setTargetSize().
  • Animaciones: solo decodifica el primer marco de un archivo GIF o WebP animado.

Cómo decodificar una imagen

La decodificación comienza con alguna forma de entrada que representa la imagen codificada. AImageDecoder acepta varios tipos de entrada:

  • AAsset (se muestra a continuación)
  • Descriptor de archivo
  • Búfer

En el siguiente código, se muestra cómo abrir una imagen Asset desde un archivo, decodificarla y, luego, deshacerse correctamente del decodificador y el elemento. Para ver un ejemplo de procesamiento de la imagen decodificada, consulta el ejemplo de la tetera.

AAssetManager* nativeManager = AAssetManager_fromJava(env, jAssets);
const char* file = // Filename
AAsset* asset = AAssetManager_open(nativeManager, file, AASSET_MODE_STREAMING);
AImageDecoder* decoder;
int result = AImageDecoder_createFromAAsset(asset, &decoder);
if (result != ANDROID_IMAGE_DECODER_SUCCESS) {
  // An error occurred, and the file could not be decoded.
}

const AImageDecoderHeaderInfo* info = AImageDecoder_getHeaderInfo(decoder);
int32_t width = AImageDecoderHeaderInfo_getWidth(info);
int32_t height = AImageDecoderHeaderInfo_getHeight(info);
AndroidBitmapFormat format =
       (AndroidBitmapFormat) AImageDecoderHeaderInfo_getAndroidBitmapFormat(info);
size_t stride = AImageDecoder_getMinimumStride(decoder);  // Image decoder does not
                                                          // use padding by default
size_t size = height * stride;
void* pixels = malloc(size);

result = AImageDecoder_decodeImage(decoder, pixels, stride, size);
if (result != ANDROID_IMAGE_DECODER_SUCCESS) {
  // An error occurred, and the file could not be decoded.
}

// We’re done with the decoder, so now it’s safe to delete it.
AImageDecoder_delete(decoder);

// The decoder is no longer accessing the AAsset, so it is safe to
// close it.
AAsset_close(asset);

// Draw the pixels somewhere

// Free the pixels when done drawing with them
free(pixels);