Décodage d'images

L'API ImageDecoder du NDK fournit une API standard pour les applications C/C++ Android permettant de décoder directement les images. Les développeurs d'applications n'ont plus besoin d'utiliser les API Java (via JNI) ni les bibliothèques de décodage d'images tierces. Cette API, ainsi que les fonctions d'encodage du module Bitmap, permet d'effectuer les opérations suivantes :

  • Les bibliothèques et applications natives peuvent être de plus petite taille, car elles n'ont plus besoin d'associer leurs propres bibliothèques de décodage.
  • Elles bénéficient automatiquement des mises à jour de sécurité de la plate-forme.
  • Les applications peuvent décoder les images directement dans la mémoire qu'elles fournissent. Elles peuvent ensuite post-traiter les données d'image (si vous le souhaitez) et les transmettre à OpenGL ou au code de dessin.

Cette page explique comment utiliser l'API pour décoder une image.

Disponibilité et fonctionnalités

L'API ImageDecoder est disponible sur les applications qui ciblent Android 11 (niveau d'API 30) ou une version ultérieure. L'implémentation se trouve dans les fichiers suivants :

  • imagedecoder.h pour le décodeur
  • bitmap.h pour l'encodeur
  • libjnigraphics.so

L'API accepte les formats d'image suivants :

  • JPEG
  • PNG
  • GIF
  • WebP
  • BMP

  • ICO

  • WBMP

  • HEIF

  • Négatifs numériques (via le SDK DNG)

Afin de couvrir toutes les utilisations des images brutes décodées, cette API ne fournit pas d'objets de niveau supérieur, tels que ceux créés sur des images décodées dans le framework Java :

  • Objets Drawable.
  • NinePatch : si cet objet est présent dans une image encodée, les fragments NinePatch sont ignorés.
  • Densité de bitmap : AImageDecoder n'effectue aucun ajustement automatique de la taille en fonction de la densité de l'écran, mais permet de décoder une autre taille via AImageDecoder_setTargetSize().
  • Animations : cet objet décode uniquement la première image d'un fichier GIF ou WebP.

Décoder une image

Le décodage commence par une forme d'entrée représentant l'image encodée. AImageDecoder accepte plusieurs types d'entrées :

  • AAsset (voir ci-dessous)
  • Descripteur de fichier
  • Tampon

Le code suivant montre comment ouvrir une image Asset à partir d'un fichier, comment la décoder, puis comment supprimer correctement le décodeur et la ressource. Pour voir un exemple d'affichage de l'image décodée, reportez-vous à l'exemple de théière.

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