谷歌公佈,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 軟體解碼、軟體編碼。
二. HEIF圖片價值:
1.與 JPEG 同等圖片質量的壓縮率是 JPEG 的2.39倍,可節省約50%空間,節省網路傳輸流量。
2.支援儲存多張圖片(圖片集合、序列圖等,如連拍)。
3.支援動態圖片(類似 Gif 動圖)。
4.支援圖片深度資訊、透明度資訊。
目標:替代 JPEG,成為主流圖片型別
三. 適配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();
}
}
複製程式碼
顯示效果:
②通過歷史版本已有類 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");
}
複製程式碼
顯示效果:
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 版本對此格式的支援也充分說明了這一點,建議各位廣大開發者趕緊適配。
關注“安卓綠色聯盟”公眾號回覆關鍵詞“申請”,瞭解華為終端開放實驗室免費雲測申請流程。