图像解码器

NDK ImageDecoder API 提供了一种标准 API,供 Android C/C++ 应用直接解码图像。应用开发者不再需要使用 Java API(通过 JNI)或第三方图像解码库。此 API 与 Bitmap 模块中的编码函数结合使用,可实现以下功能:

  • 缩小原生应用和库的大小,因为它们不再需要链接自己的解码库。
  • 应用和库可自动从解码库的平台安全更新中受益。
  • 应用可以直接将图像解码到其提供的内存中。然后,应用可以对图像数据进行后处理(如果需要),并将其传递给 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)

为了涵盖已解码原始图片的所有用法,此 API 不提供更高级别的对象,例如在 Java 框架内基于解码图片构建的对象,例如:

解码图像

从表示编码图像的某种形式的输入开始解码。 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);