Bộ giải mã hình ảnh

API ImageDecoder của NDK cung cấp một API tiêu chuẩn cho các ứng dụng Android C/C++ để giải mã hình ảnh trực tiếp. Nhà phát triển ứng dụng không cần sử dụng API Java (thông qua JNI) hoặc thư viện giải mã hình ảnh của bên thứ ba nữa. API này cùng với các chức năng mã hoá trong mô-đun Bitmap, cho phép:

  • Các ứng dụng và thư viện gốc có thể nhỏ hơn vì không còn phải liên kết thư viện giải mã riêng.
  • Các ứng dụng và thư viện tự động hưởng lợi từ các bản cập nhật bảo mật nền tảng cho thư viện giải mã.
  • Ứng dụng có thể giải mã hình ảnh trực tiếp vào bộ nhớ do ứng dụng cung cấp. Sau đó, ứng dụng có thể xử lý hậu kỳ dữ liệu về hình ảnh (nếu muốn) và truyền dữ liệu đó đến OpenGL hoặc mã vẽ của ứng dụng.

Trang này mô tả cách sử dụng API để giải mã hình ảnh.

Phạm vi cung cấp và khả năng

API ImageDecoder có sẵn trên các ứng dụng nhắm mục tiêu đến Android 11 (API cấp 30) trở lên. Quá trình triển khai diễn ra bên trong các tệp sau:

  • imagedecoder.h cho bộ giải mã
  • bitmap.h cho bộ mã hoá
  • libjnigraphics.so

API này hỗ trợ các định dạng hình ảnh sau:

  • JPEG
  • PNG
  • GIF
  • WebP
  • BMP

  • ICO

  • WBMP

  • HEIF

  • Âm bản kỹ thuật số (thông qua SDK DNG)

Để đáp ứng tất cả trường hợp sử dụng hình ảnh thô được giải mã, API này không cung cấp đối tượng cấp cao hơn như đối tượng được tạo ngoài hình ảnh đã giải mã bên trong khung Java, chẳng hạn như:

  • Đối tượng Drawable.
  • NinePatch: Nếu xuất hiện trong hình ảnh được mã hoá, thì các đoạn NinePatch sẽ bị bỏ qua.
  • Mật độ bitmap :AImageDecoder không điều chỉnh kích thước tự động dựa trên mật độ màn hình, nhưng cho phép giải mã thành một kích thước khác qua AImageDecoder_setTargetSize().
  • Ảnh động: Chỉ giải mã khung đầu tiên của tệp GIF hoặc WebP động.

Giải mã hình ảnh

Quá trình giải mã bắt đầu bằng một số dạng dữ liệu đầu vào biểu thị hình ảnh đã mã hoá. AImageDecoder chấp nhận nhiều loại dữ liệu đầu vào:

  • AAsset (trình bày bên dưới)
  • Chỉ số mô tả tệp
  • Vùng đệm

Mã sau đây cho biết cách mở Asset của hình ảnh từ một tệp, giải mã hình ảnh đó, sau đó xử lý đúng cách bộ giải mã và nội dung. Để xem ví dụ về cách kết xuất hình ảnh được giải mã, hãy xem mẫu ấm trà.

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