이미지 디코더

NDK ImageDecoder API는 Android C/C++ 앱이 이미지를 직접 디코딩하도록 표준 API를 제공합니다. 앱 개발자는 자바 API(JNI를 통해) 또는 타사 이미지 디코딩 라이브러리를 더 이상 사용할 필요가 없습니다. 이 API는 비트맵 모듈의 인코딩 함수와 함께 다음을 가능하게 합니다.

  • 네이티브 앱 및 라이브러리는 자체 디코딩 라이브러리를 더 이상 연결할 필요가 없으므로 더 작을 수 있습니다.
  • 앱 및 라이브러리는 플랫폼 보안 업데이트에서 디코딩 라이브러리에 이르기까지 이러한 기능의 이점을 자동으로 활용합니다.
  • 앱은 제공하는 메모리로 이미지를 직접 디코딩할 수 있습니다. 그런 다음, 앱은 이미지 데이터를 후처리하여(원한다면) OpenGL 또는 드로잉 코드에 전달할 수 있습니다.

이 페이지에서는 API를 사용하여 이미지를 디코딩하는 방법을 설명합니다.

사용 가능 여부 및 기능

ImageDecoder API는 Android 11(API 수준 'R') 이상을 타겟팅하는 앱에서 사용할 수 있습니다. 구현은 다음 파일 내에 있습니다.

  • imagedecoder.h(디코더용)
  • bitmap.h(인코더용)
  • libjnigraphics.so

API는 다음 이미지 형식을 지원합니다.

  • JPEG
  • PNG
  • GIF
  • WebP
  • BMP

  • ICO

  • WBMP

  • HEIF

  • 디지털 네거티브(DNG SDK를 통해)

디코딩된 RAW 이미지의 모든 용도를 다루기 위해 이 API는 다음과 같이 자바 프레임워크 내의 디코딩된 이미지를 기반으로 빌드된 객체와 같은 상위 수준 객체를 제공하지 않습니다.

  • Drawable 객체
  • NinePatch: 인코딩된 이미지에 있다면 NinePatch 청크는 무시됩니다.
  • 비트맵 밀도: AImageDecoder는 화면의 밀도에 따라 자동으로 크기를 조정하지 않지만 AImageDecoder_setTargetSize()를 통해 다양한 크기로 디코딩할 수 있습니다.
  • 애니메이션: 애니메이션 GIF 또는 WebP 파일의 첫 번째 프레임만 디코딩합니다.

이미지 디코딩

디코딩은 인코딩된 이미지를 나타내는 몇 가지 입력 형식으로 시작됩니다. AImageDecoder는 다음과 같은 여러 유형의 입력을 허용합니다.

  • AAsset(아래 참조)
  • 파일 설명자
  • 버퍼

다음 코드는 파일에서 이미지 Asset을 열고 디코딩한 후 디코더 및 애셋을 적절하게 처리하는 방법을 보여줍니다. 디코딩된 이미지를 렌더링하는 예를 확인하려면 Teapot 샘플을 참조하세요.

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