Decodificatore di immagini

L'API NDK ImageDecoder fornisce un'API standard per le app Android C/C++ per decodificare direttamente le immagini. Gli sviluppatori di app non devono più utilizzare le API Java (tramite JNI) o le librerie di decodifica delle immagini di terze parti. Questa API, insieme alle funzioni di codifica nel modulo Bitmap, consente quanto segue:

  • Le app e le librerie native possono essere più piccole perché non devono più collegare le proprie librerie di decodifica.
  • Le app e le librerie beneficiano automaticamente degli aggiornamenti della sicurezza della piattaforma per le librerie di decodifica.
  • Le app possono decodificare le immagini direttamente nella memoria che forniscono. Le app possono quindi post-elaborare i dati delle immagini (se lo desiderano) e passarli a OpenGL o al loro codice di disegno.

Questa pagina descrive come utilizzare l'API per decodificare un'immagine.

Disponibilità e funzionalità

L'API ImageDecoder è disponibile nelle app che hanno come target Android 11 (livello API 30) o versioni successive. L'implementazione si trova nei seguenti file:

  • imagedecoder.h per il decoder
  • bitmap.h per l'encoder
  • libjnigraphics.so

L'API supporta i seguenti formati di immagine:

  • JPEG
  • PNG
  • GIF
  • WebP
  • BMP

  • ICO

  • WBMP

  • HEIF

  • Negativi digitali (tramite l'SDK DNG)

Per coprire tutti gli utilizzi delle immagini raw decodificate, questa API non fornisce oggetti di livello superiore come quelli costruiti sulle immagini decodificate all'interno del framework Java, ad esempio:

  • Oggetti Drawable.
  • NinePatch: se sono presenti in un'immagine codificata, i chunk NinePatch vengono ignorati.
  • Densità bitmap: AImageDecoder non regola automaticamente le dimensioni in base alla densità dello schermo, ma consente la decodifica in dimensioni diverse tramite AImageDecoder_setTargetSize().
  • Animazioni: decodifica solo il primo fotogramma di un file GIF o WebP animato.

Decodificare un'immagine

La decodifica inizia con una forma di input che rappresenta l'immagine codificata. AImageDecoder accetta più tipi di input:

  • AAsset (mostrato di seguito)
  • Descrittore file
  • Buffer

Il codice seguente mostra come aprire un'immagine Asset da un file, decodificarla e poi smaltire correttamente il decodificatore e la risorsa. Per vedere un esempio di rappresentazione dell'immagine decodificata, consulta l'esempio della teiera.

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