图像解码器

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

  • 本机应用程序和库可以更小,因为它们不再需要链接自己的解码库。
  • 应用程序和库会自动从平台对解码库的安全更新中受益。
  • 应用程序可以将图像直接解码到它们提供的内存中。然后,应用程序可以(如果需要)对图像数据进行后处理,并将其传递给 OpenGL 或其绘制代码。

本页介绍如何使用 API 解码图像。

可用性和功能

ImageDecoder API 可用于面向 Android 11(API 级别 30)或更高版本的应用程序。实现位于以下文件中

  • imagedecoder.h(用于解码器)
  • bitmap.h(用于编码器)
  • libjnigraphics.so

此 API 支持以下图像格式

  • JPEG
  • PNG
  • GIF
  • WebP
  • BMP

  • ICO

  • WBMP

  • HEIF

  • 数字底片(通过 DNG SDK)

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

解码图像

解码从某种形式的输入开始,该输入代表编码图像。 AImageDecoder 接受多种类型的输入

  • AAsset(如下所示)
  • 文件描述符
  • 缓冲区

以下代码展示了如何从文件打开图像 Asset、解码它,然后适当地处置解码器和资源。要查看渲染已解码图像的示例,请参阅 茶壶示例

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