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 框架中基于解码图像构建的更高级别对象,例如:
Drawable
对象.NinePatch
:如果编码图像中存在 NinePatch 块,则会忽略它们。- 位图密度:
AImageDecoder
不会根据屏幕密度自动调整大小,但允许通过AImageDecoder_setTargetSize()
解码为不同大小。 - 动画:仅解码动画 GIF 或 WebP 文件的第一帧。
解码图像
解码从表示编码图像的某种形式的输入开始。AImageDecoder
接受多种输入类型:
AAsset
(如下所示)- 文件描述符
- 缓冲区
以下代码演示了如何从文件中打开图像 Asset
、对其进行解码,然后正确释放解码器和 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);