引言
今天烛谊,測試妹子拿個(gè)樣機(jī)過來說:“手機(jī)拍出來的照片拷貝到windows電腦上無法打開”。查了一下代碼渗鬼,僅僅是一個(gè)bitmap.compress(Bitmap.CompressFormat.JPEG, 90, data)篡撵,用過無數(shù)次的方法,無論如何不可能出問題脾歧。那么問題肯定出在電腦上了,百度一下演熟,還真有解決方案鞭执,將windows顏色系統(tǒng)的默認(rèn)值改為 “Agfa:Swop Standard”,可以正常顯示了芒粹。本想告訴測試妹子解決方案兄纺,但卻總隱約覺得不對(duì)勁,仔細(xì)排查一圈下來發(fā)現(xiàn)是JPEG圖片的EXIF信息出了問題化漆。
1. 問題現(xiàn)象
手機(jī)拍照后估脆,將照片拷貝到windows電腦上,使用windows照片查看器無法打開照片座云,提示:
Windows 照片查看器無法顯示此圖片疙赠,因?yàn)橛?jì)算機(jī)上的可用內(nèi)存可能不足。請關(guān)閉一些目前沒有使用的程序或者釋放部分硬盤空間(如果硬盤幾乎已滿)朦拖,然后重試圃阳。
但是同樣的照片:
- 在手機(jī)上可以正常顯示。
- 點(diǎn)擊windows照片查看器的幻燈片放映也可以顯示贞谓。
- 使用其它看圖工具也可以顯示限佩。
此時(shí)葵诈,電腦內(nèi)存或者磁盤空間是充足的裸弦。
2. 問題可能的原因
可能的原因一:
色彩空間不同,windows默認(rèn)的色彩空間是sRGB作喘,而很多相機(jī)理疙、手機(jī)的色彩空間是Adobe RGB。可能的原因二:
JPEG圖片的EXIF信息有問題泞坦。由于某些相機(jī)APP處理照片后窖贤,修改或者添加了某些EXIF信息。例如贰锁,修改了圖片數(shù)據(jù)長度等赃梧,EXIF信息與實(shí)際圖片數(shù)據(jù)不一致,windows照片查看器無法正常解析照片豌熄,導(dǎo)致無法打開照片授嘀。甚至華為P40也有用戶反饋過類似的問題:照片傳到電腦里總是說Windows照片查看器無法顯示此圖片。
什么是EXIF信息锣险?
EXIF信息是可交換圖像文件的縮寫蹄皱,是專門為數(shù)碼相機(jī)的照片設(shè)定的览闰,可以記錄數(shù)碼照片的屬性信息和拍攝數(shù)據(jù)。EXIF可以附加于JPEG巷折、TIFF压鉴、RIFF等文件之中,為其增加有關(guān)數(shù)碼相機(jī)拍攝信息的內(nèi)容和索引圖或圖像處理軟件的版本信息锻拘。
JPEG文件可包含實(shí)際的圖像數(shù)據(jù)和Exif信息油吭。Exif信息包括品牌、型號(hào)署拟、光圈上鞠、曝光時(shí)間、ISO芯丧、焦距芍阎、閃光、白平衡缨恒、日期時(shí)間谴咸、位置信息、色彩空間等等各種信息骗露。但不是所有JPEG文件都有Exif信息岭佳。
3. 解決方案
3.1 針對(duì)色彩空間不同,有兩種解決方案:
方案一:
不使用windows默認(rèn)的圖片查看器萧锉,使用其它看圖工具珊随。
方案二:
修改windows顏色系統(tǒng)的默認(rèn)值。打開windows “控制面板”柿隙,查看方式由 “類別” 修改為 “小圖標(biāo)”叶洞,打開 “顏色管理”,點(diǎn)擊 “高級(jí)” 選項(xiàng)卡禀崖,將“設(shè)備配置文件(D): ”由“系統(tǒng)默認(rèn)(sRGB IEC61966-2.1)” 改為 “Agfa:Swop Standard”衩辟。
再次使用windows默認(rèn)的圖片查看器打開圖片,就可以正常顯示了波附。
3.2 針對(duì)JPEG圖片EXIF信息有問題艺晴,也有兩種解決方案:
方案一:
不使用windows默認(rèn)的圖片查看器,使用其它看圖工具掸屡。一些第三方的圖片查看器顯示圖片時(shí)封寞,并不依賴EXIF信息,它們可以正常顯示照片仅财。
方案二:
下載一個(gè) “jpg圖片修復(fù)工具”狈究,用它修復(fù)JPEG圖片的EXIF信息。修復(fù)后windows默認(rèn)的圖片查看器就可以正常顯示照片了满着。所謂的修復(fù)谦炒,其實(shí)就是重新生成與JPEG圖像數(shù)據(jù)一致的EXIF信息贯莺。
4. 實(shí)際android項(xiàng)目上的問題分析及解決
我們回到引言中測試妹子報(bào)的那個(gè)bug,這個(gè)展銳平臺(tái)的項(xiàng)目在Camera APP中集成了一個(gè)第三方算法庫宁改,大概的圖像格式的轉(zhuǎn)換流程為:
如上圖缕探,JpegCallback中出來原JPEG圖片時(shí),還一起生成了圖片的EXIF信息还蹲。
首先爹耗,我懷疑色彩空間不是sRGB。于是將bitmap的ColorSpace打印出來:
2021-01-25 10:10:32.125 31995-32126/com.android.camera2 D/CAM2: bitmap.getColorSpace():sRGB IEC61966-2.1 (id=0, model=RGB),
發(fā)現(xiàn)色彩空間確實(shí)是sRGB谜喊。
那么潭兽,問題就應(yīng)該出在EXIF信息上了。再將EXIF信息打印出來斗遏,最終發(fā)現(xiàn)問題就出在JPEG圖片的數(shù)據(jù)長度上山卦。第三方算法輸出RGB,所以必須利用Bitmap將RGB壓縮成JPEG再保存诵次,再次壓縮后账蓉,新JPEG圖片的數(shù)據(jù)長度與原JPEG圖片的數(shù)據(jù)長度已經(jīng)不同了,新JPEG圖片的占用空間要比較原JPEG圖片大一點(diǎn)點(diǎn)逾一。日志證明了這一點(diǎn):
2021-01-25 10:33:35.155 31995-32126/com.android.camera2 D/CAM2:jpegData.length:2431896
2021-01-25 10:33:35.812 31995-32126/com.android.camera2 D/CAM2: newJpegData.length:2904395
所以铸本,問題的原因就是:圖片的EXIF信息在JpegCallback中出來原JPEG圖片時(shí)就生成了,后面圖片數(shù)據(jù)改變了遵堵,卻沒有更新EXIF信息箱玷。
而windows默認(rèn)圖片查看器又可能比較蠢,查看圖片時(shí)陌宿,按EXIF信息去分配內(nèi)存锡足,真正加載圖片時(shí)發(fā)現(xiàn)內(nèi)存不夠,所以就報(bào)一個(gè)內(nèi)存不足的提示限番,造成了難以理解的烏龍舱污。
知道了問題的原因呀舔,解決起來也就很簡單了弥虐,只需要更新一下EXIF信息中的數(shù)據(jù)長度:
exifInterface.setTagValue(ExifInterface.TAG_JPEG_LENGTH, newJpegData.length);
重新編譯、驗(yàn)證媚赖,果然霜瘪,拍出來的照片都可以正常用windows默認(rèn)圖片查看器打開顯示了。
通過這個(gè)bug惧磺,我們可以知道颖对,如果一張JPEG圖片除圖像數(shù)據(jù)外,還保存有EXIF信息磨隘,那么圖像數(shù)據(jù)需要和EXIF信息能對(duì)應(yīng)上缤底,否則會(huì)出現(xiàn)一些奇怪的問題顾患。如果對(duì)圖像數(shù)據(jù)進(jìn)行過編輯和處理,那么EXIF信息也要同步更新个唧。
5. 參考
Windows照片查看器無法顯示此圖片江解,因?yàn)橛?jì)算機(jī)上的可用內(nèi)存可能不足。
EXIF信息