Dekoder obrazów

Interfejs NDK ImageDecoder API udostępnia standardowy interfejs API dla aplikacji w języku C/C++ na Androida do bezpośredniego dekodowania obrazów. Deweloperzy aplikacji nie muszą już korzystać z interfejsów Java API (przez JNI) ani bibliotek do dekodowania obrazów innych firm. Ten interfejs API wraz z funkcjami kodowania w module Bitmap umożliwia:

  • Natywne aplikacje i biblioteki mogą być mniejsze, ponieważ nie muszą już łączyć własnych bibliotek dekodowania.
  • Aplikacje i biblioteki automatycznie korzystają z aktualizacji zabezpieczeń platformy bibliotek do dekodowania.
  • Aplikacje mogą dekodować obrazy bezpośrednio do zapewnianej przez nie pamięci. Aplikacje mogą następnie przetworzyć dane obrazu (w razie potrzeby) i przekazać je do OpenGL lub do swojego kodu.

Na tej stronie dowiesz się, jak dekodować obraz za pomocą interfejsu API.

Dostępność i możliwości

Interfejs ImageDecoder API jest dostępny w aplikacjach kierowanych na Androida 11 (poziom API 30) lub nowszy. Implementacja znajduje się w tych plikach:

  • imagedecoder.h – dekoder
  • bitmap.h dla kodera
  • libjnigraphics.so

Interfejs API obsługuje te formaty obrazów:

  • JPEG
  • PNG
  • GIF
  • WebP
  • BMP

  • ICO

  • WBMP

  • HEIF

  • Cyfrowe wykluczające dane (za pomocą DNG SDK)

Aby pokryć wszystkie przypadki użycia zdekodowanych nieprzetworzonych obrazów, ten interfejs API nie udostępnia obiektów wyższego poziomu, takich jak obiekty utworzone na zdekodowanych obrazach w ramach platformy Java, takie jak:

  • Drawable obiekty.
  • NinePatch: jeśli ten obraz znajduje się w zakodowanym obrazie, fragmenty NinePatch są ignorowane.
  • Gęstość bitmapy: AImageDecoder nie automatycznie dostosowuje rozmiaru na podstawie gęstości ekranu, ale umożliwia dekodowanie do innego rozmiaru za pomocą AImageDecoder_setTargetSize().
  • Animacje: dekoduje tylko pierwszą klatkę animowanego pliku GIF lub WebP.

Dekodowanie obrazu

Dekodowanie rozpoczyna się od danych wejściowych reprezentujących zakodowany obraz. Funkcja AImageDecoder akceptuje różne rodzaje danych wejściowych:

  • AAsset (na ilustracji poniżej)
  • Deskryptor pliku
  • Bufor

Poniższy kod pokazuje, jak otworzyć obraz Asset z pliku, zdekodować go, a następnie prawidłowo pozbyć się dekodera i zasobu. Przykład renderowania zdekodowanego obrazu znajdziesz w przykładzie czajnika.

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