ตัวถอดรหัสรูปภาพ

API ImageDecoder ของ NDK มี API มาตรฐานสําหรับแอป C/C++ ของ Android เพื่อถอดรหัสรูปภาพโดยตรง นักพัฒนาแอปไม่จำเป็นต้องใช้ Java API (ผ่าน JNI) หรือไลบรารีการถอดรหัสรูปภาพของบุคคลที่สามอีกต่อไป API นี้พร้อมด้วยฟังก์ชันการเข้ารหัสในโมดูลบิตแมปจะเปิดใช้สิ่งต่อไปนี้

  • แอปและไลบรารีที่มาพร้อมเครื่องอาจมีขนาดเล็กลงเนื่องจากไม่ต้องลิงก์ไลบรารีการถอดรหัสของตนเองอีกต่อไป
  • แอปและไลบรารีจะได้รับประโยชน์โดยอัตโนมัติจากการอัปเดตความปลอดภัยของแพลตฟอร์ม ไปจนถึงการถอดรหัสไลบรารี
  • แอปสามารถถอดรหัสรูปภาพไปยังหน่วยความจำที่ให้ไว้โดยตรง จากนั้นแอปจะประมวลผลข้อมูลรูปภาพหลังการประมวลผล (หากต้องการ) และส่งไปยัง 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)

เพื่อให้ครอบคลุมการใช้งานทั้งหมดของรูปภาพ RAW ที่ถอดรหัสแล้ว API นี้จะไม่มอบออบเจ็กต์ระดับสูงขึ้น เช่น ออบเจ็กต์ที่สร้างขึ้นบนรูปภาพที่ถอดรหัสแล้วภายในเฟรมเวิร์ก Java เช่น

  • Drawable ออบเจ็กต์
  • NinePatch: ระบบจะละเว้นกลุ่ม NinePatch หากมีอยู่ในรูปภาพที่เข้ารหัส
  • ความหนาแน่นของบิตแมป: AImageDecoder ไม่ได้ปรับขนาดโดยอัตโนมัติตามความหนาแน่นของหน้าจอ แต่อนุญาตให้ถอดรหัสเป็นขนาดอื่นผ่าน AImageDecoder_setTargetSize() ได้
  • ภาพเคลื่อนไหว: จะถอดรหัสเฉพาะเฟรมแรกของไฟล์ GIF แบบเคลื่อนไหวหรือ WebP

ถอดรหัสรูปภาพ

การถอดรหัสเริ่มต้นด้วยอินพุตรูปแบบหนึ่งที่แสดงภาพที่เข้ารหัส 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);