大勢所趨,應用如何適配Android P HEIF圖片格式

安卓綠色聯盟發表於2018-07-23

谷歌公佈,Android P 版本支援HEIF格式圖片。HEIF 全稱為 High Efficiency Image Format,即高效率圖片格式。相比於 JPEG 等目前網際網路通用的圖片格式,HEIF 圖片有何價值?在HEIF圖片的適配過程中,應用會遭遇哪些典型性問題?該如何進行適配?

一. 什麼是HEIF圖片

1.HEIF(High Efficiency Image Format),即高效率圖片格式。2015年由 ISO 批准釋出,由 MPEG 標準組織制定,採用 HEVC 編碼格式。

2.蘋果自2017.9.20釋出的 iOS11 開始拍照儲存支援HEIF格式(iPhone 7及以上機型)。

3.谷歌 O 版本 MR1 支援 HEIF 靜態圖的軟體解碼,Android P 支援 HEIF 軟體解碼、軟體編碼。

大勢所趨,應用如何適配Android P HEIF圖片格式

二. HEIF圖片價值:

1.與 JPEG 同等圖片質量的壓縮率是 JPEG 的2.39倍,可節省約50%空間,節省網路傳輸流量。

2.支援儲存多張圖片(圖片集合、序列圖等,如連拍)。

3.支援動態圖片(類似 Gif 動圖)。

4.支援圖片深度資訊、透明度資訊。

目標:替代 JPEG,成為主流圖片型別

大勢所趨,應用如何適配Android P HEIF圖片格式

三. 適配HEIF圖片格式典型問題

1.在支援 HEIF 編解碼的手機無法開啟HEIF格式檔案。

2.儘管手機支援 HEIF 編解碼,應用仍無法掃描到使用者手機本地的HEIF格式圖片,無法分享或者傳送本地 HEIF 格式圖片給其他使用者。

3.將 HEIF 格式圖片,通過支援 HEIF 編解碼的手機傳送到不支援 HEIF 編解碼的手機,會出現圖片無法檢視的問題。

四. 適配指導

1.判斷手機是否支援 HEIF 格式

谷歌未提供統一介面,推薦應用通過手機系統版本來判斷是否支援 HEIF 格式編解碼。目前,Android O 版本 MR1 支援 HEIF 靜態圖的軟體解碼,Android P 支援 HEIF 軟體解碼、軟體編碼。

以華為 Android P 版本手機HEIF格式編解碼為例,參考實現程式碼

tic boolean isSupportHeif() {
   Log.e(TAG, "Build.MANUFACTURER:" + Build.MANUFACTURER + ", Build.VERSION.SDK_INT:" + Build.VERSION.SDK_INT);
if("HUAWEI".equals(Build.MANUFACTURER) && Build.VERSION.SDK_INT>27) {
        return true;
    }
    return false;
}
複製程式碼

2.如何讀取和顯示HEIF圖片檔案

①通過 Android P 版本新增的類 ImageDecoder 載入圖片。

參考實現程式碼

public static Drawable getHeifImageFromSdcardUseImageDecoder(String path) throws IOException {
    File file = new File(path);
    ImageDecoder.Source source = ImageDecoder.createSource(file);
    return ImageDecoder.decodeDrawable(source);
}

mImageHeif = findViewById(R.id.imageView2);
if (HeifUtils.isSupportHeif()) {
    try {
        Drawable drawble = HeifUtils.getHeifImageFromSdcardUseImageDecoder("/sdcard/bird_burst.heic");
        mImageHeif.setImageDrawable(drawble);
        textHeif.setText("load heif image use ImageDecoder");
    } catch (IOException e) {
        e.printStackTrace();
    }
}
複製程式碼

顯示效果:

大勢所趨,應用如何適配Android P HEIF圖片格式

②通過歷史版本已有類 BitmapFactory 載入圖片。

該方法工作量最小,只需放開 Android P 版本手機 HEIF 圖片檔案載入,無需修改圖片載入程式碼。需要注意的是,應用需預設支援 HEIF 圖片的載入檢視。

參考實現程式碼

public static Bitmap getHeifImageFromSdcardUseBitmapFactory(String path) {
    return BitmapFactory.decodeFile(path);
}

if (HeifUtils.isSupportHeif()) {
    Bitmap bmp = HeifUtils.getHeifImageFromSdcardUseBitmapFactory("/sdcard/bird_burst.heic");
    mImageHeif.setImageBitmap(bmp);
    textHeif.setText("load heif image use BitmapFactory");
}
複製程式碼

顯示效果:

大勢所趨,應用如何適配Android P HEIF圖片格式

3.圖片掃描推薦方式

方式一(推薦):通過 ContentProvider 掃描

實現本地圖片的上傳、分享或者是傳送功能,需要掃描手機本地的圖片。如果應用通過自身掃描的方式,需根據手機版本判斷手機支援的圖片編解碼格式,所以推薦使用 ContentProvider 掃描手機中的圖片。通過這種方法掃描,系統會將支援的所有解碼格式的圖片檔案返回給應用,不需要應用自身再去做格式判斷。

參考實現程式碼

public static void getAllImagesLocal(final Context context) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Cursor cursor = context.getContentResolver().query(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
            while (cursor.moveToNext()) {
                String path = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Images.Media.DATA));
                Log.e(TAG, "image path:" + path);
            }
        }
    }).start();
}
複製程式碼

通過抓取日誌,能夠看到應用如果在支援 HEIF 編解碼的手機執行,系統會將HEIF格式圖片掃描結果返回給應用,如果在不支援 HEIF 格式的手機執行,系統則不會將 HEIF 格式圖片掃描結果返回。

支援 HEIF 格式的手機執行抓取的日誌

Line 4653: 06-09 11:14:37.976 17127 17173 E HeifUtils: image path:/storage/emulated/0/Pictures/autumn_1440x960.heic
	Line 4654: 06-09 11:14:37.976 17127 17173 E HeifUtils: image path:/storage/emulated/0/Pictures/old_bridge_1440x960.heic
	Line 4655: 06-09 11:14:37.976 17127 17173 E HeifUtils: image path:/storage/emulated/0/tencent/MicroMsg/wallet/luckyMoneyEffect/1/package/input.png
	Line 4656: 06-09 11:14:37.976 17127 17173 E HeifUtils: image path:/storage/emulated/0/tencent/MicroMsg/wallet/luckyMoneyEffect/1/package/list.png
	Line 4657: 06-09 11:14:37.976 17127 17173 E HeifUtils: image path:/storage/emulated/0/tencent/MicroMsg/wallet/luckyMoneyEffect/1/package/cover.png
	Line 4658: 06-09 11:14:37.976 17127 17173 E HeifUtils: image path:/storage/emulated/0/tencent/MicroMsg/wallet/luckyMoneyEffect/1/package/chat.png
	Line 4659: 06-09 11:14:37.976 17127 17173 E HeifUtils: image path:/storage/emulated/0/bird_burst.heic
	Line 4660: 06-09 11:14:37.976 17127 17173 E HeifUtils: image path:/storage/emulated/0/Hydrangeas.jpg
	Line 4661: 06-09 11:14:37.976 17127 17173 E HeifUtils: image path:/storage/emulated/0/Download/bird_burst.heic
	Line 4662: 06-09 11:14:37.976 17127 17173 E HeifUtils: image path:/storage/emulated/0/Download/Hydrangeas.jpg
複製程式碼

方式二(不推薦):應用自身進行掃描

應用通過自身掃描,判斷哪些是可支援的圖片檔案,需要增加對 HEIF 格式的判斷, HEIF 格式檔案的字尾有兩種:.heif和.heic

4.HEIF 格式轉 JPEG

使用場景:

HEIF 格式轉成 JPEG 格式主要考慮向下相容的問題。通過支援 HEIF 格式的手機向不支援此格式的手機傳送 HEIF 圖片,如果直接傳送原始 HEIF 格式,會出現圖片無法使用的情況。因此,為了避免這種情況,可以考慮在傳送之前將 HEIF 格式圖片轉換成 JPEG 格式再傳送。應用可以選擇使用谷歌原生的介面來進行轉換。

參考實現程式碼

try {
    Bitmap bmp = HeifUtils.getHeifImageFromSdcardUseBitmapFactory("/sdcard/bird_burst.heic");
    File file = new File("/sdcard/download/bird_burst1.jpg");
    FileOutputStream out = new FileOutputStream(file);
    bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
    out.flush();
    out.close();
    Uri uri = Uri.fromFile(file);
    sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
} catch (Exception e) {
    e.printStackTrace();
}
複製程式碼

HEIF 圖片格式的諸多優勢使它具有很好的市場前景,這次谷歌 Android P 版本對此格式的支援也充分說明了這一點,建議各位廣大開發者趕緊適配。

關注“安卓綠色聯盟”公眾號回覆關鍵詞“申請”,瞭解華為終端開放實驗室免費雲測申請流程。

image

相關文章