מפענח תמונות

ממשק ה-API ImageDecoder של NDK מספק ממשק API רגיל לאפליקציות Android ב-C/C++ לצורך פענוח תמונות ישירות. מפתחי אפליקציות כבר לא צריכים להשתמש בממשקי ה-API של Java (דרך JNI) או בספריות של צד שלישי לפענוח תמונות. ממשק ה-API הזה, יחד עם פונקציות קידוד במודול Bitmap, מאפשר לבצע את הפעולות הבאות:

  • אפליקציות וספריות מקוריות יכולות להיות קטנות יותר כי אין יותר צורך לקשר ספריות פענוח משלהם.
  • אפליקציות וספריות נהנות באופן אוטומטי מעדכוני האבטחה של הפלטפורמה לספריות הפענוח.
  • אפליקציות יכולות לפענח תמונות ישירות לזיכרון שהן מספקות. לאחר מכן, האפליקציות יכולות לעבד את נתוני התמונה בשלב מאוחר יותר (אם רוצים) ולהעביר אותם ל-OpenGL או לקוד הציור שלהן.

בדף הזה נסביר איך משתמשים ב-API כדי לפענח תמונה.

זמינות ויכולת

ממשק ה-API ImageDecoder זמין באפליקציות שמטרגטות ל-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);