天天看點

白夜追兇 :手 Q 圖檔的顯示和發送邏輯

作者:陳舜堯導語: “這張圖檔在快捷發圖欄背景是黑色的,為啥發到AIO(會話視窗)裡背景就變成白的了?” 通過一個bug單,對黑白背景問題跟進的過程中發現了手q中很多奇怪的表現。一層層看代碼,整理總結了手q中圖檔的顯示和發送邏輯,以及對透明通道圖檔的特殊處理。
白夜追兇 :手 Q 圖檔的顯示和發送邏輯

這張圖檔在快捷發圖欄背景是黑色的,發到AIO裡背景就變成白的了。拿到問題,分析有兩種可能原因:展示view的背景色不一緻;選中的png圖檔的透明通道在AIO和快捷發圖欄兩個不同的場景下過濾規則不一緻。

很容易就能發現兩個場景處理圖檔的不同:快捷發圖欄将png圖檔擷取為bitmap,再壓縮成jpeg,這個過程直接忽略了透明通道,android預設處理的結果就是一張黑色背景的jpeg。快捷發圖欄所有圖檔的位元組流持久化到同一個檔案裡,這樣做的目的是下次從本地加載多張圖檔時,會共用同一個檔案IO,提高加載效率;

AIO中的縮略圖也是由原圖壓縮成jpeg,在處理的代碼中,我發現了人為加白色背景的邏輯,原來這都是産品的政策,可能考慮到AIO中png圖檔黑色背景視覺上不太美觀,是以進行了特殊處理。然而快捷發圖欄和AIO中視覺上沒做到統一,有道是 産品拍頭一時爽,開發解bug火葬場

白夜追兇 :手 Q 圖檔的顯示和發送邏輯

既然問題找到了,美滋滋的準備加個雞腿,然而事情并沒有那麼簡單!回歸問題的時候我用了另外一張png圖檔測試,咦,怎麼這張圖檔在AIO中背景是黑色的?

有兩個懷疑方向:1、png壓縮成jpeg的過程,丢失透明通道導緻AIO中這張圖檔為黑色背景;2、有沒有可能是在canvas上繪制白色背景失敗導緻的該問題?

白夜追兇 :手 Q 圖檔的顯示和發送邏輯

先從第一個方向分析,通過BitmapFactory.decode把png輸出為bitmap,再把白底、bitmap依次繪到canvas上,期間旋轉資訊的處理、對長圖的特殊處理、subSample這裡就不展開了。這裡懷疑png輸出為bitmap時,透明通道丢失。

我們知道ARGB指的是一種色彩模式,裡面A代表Alpha,R表示red,G表示green,B表示blue,其實所有的可見色都是右紅綠藍組成的,是以紅綠藍又稱為三原色,每個原色都存儲着所表示顔色的資訊值,Bitmap.Option中config的值有下面幾種,ALPHA_8 代表8位Alpha位圖 ,ARGB_4444 代表16位ARGB位圖 ,ARGB_8888 代表32位ARGB位圖 ,RGB_565 代表16位RGB位圖。有沒有可能是png輸出為bitmap的過程中,有奇葩的政策調整config的值導緻ALPHA通道遺失?于是一步步斷點跟蹤這塊的代碼,很遺憾沒發現異常。

再看看第二個方向,我們review下加白色背景的代碼(見上圖),Paint設定了Xfermode。PorterDuff.Mode能設定canvas繪圖時不同圖層的混合方式,下圖展示了不同的混合方式。我們處理是将圖檔bitmap疊加到白色背景上,這裡SRC_OVER看上去也沒問題。。。

白夜追兇 :手 Q 圖檔的顯示和發送邏輯

啪啪啪打臉,看來不是懷疑的兩個方向出了問題。于是病急亂投醫把鍋甩給了圖檔。。。。。

“會不會是png格式的問題,png某個參數導緻轉化過程中bitmap背景不同????”

在查閱資料、用工具分析對比了兩張png圖檔的結構,欣喜得發現問題跟png格式并沒有半毛錢關系。冷靜下來,還是用老辦法,一步一步跟代碼!!!!

白夜追兇 :手 Q 圖檔的顯示和發送邏輯

遊戲圖壓縮後P2大于P1(是的你沒看錯,壓縮後圖檔反而大,壓縮步驟取bitmap,再繪制,最後品質壓縮成jpeg),是以是拿原始圖檔當作大圖P3去生成縮略圖P4,原始圖檔有透明通道,是以對應的縮略圖能加上白色背景;骰子圖檔壓縮後發現比原圖小,是以用壓縮圖P2當作大圖P3去生成縮略圖P4。P2是品質壓縮png生成的jpeg,已經丢失透明通道,是一張黑色背景的圖。即使在P4加上白色背景也被上層圖層覆寫,我們看到的就是黑色骰子縮略圖。

我之前分析的過程中忽略了壓縮原始圖檔生成P2這一步。一葉障目,理清了思路,問題就顯而易見了!

既然理清了流程,那就把所有情況下的表現分析下吧。我們看看勾選原圖下的表現。

白夜追兇 :手 Q 圖檔的顯示和發送邏輯

這裡很好了解,骰子圖勾選原圖後,是把原始圖檔生成縮略圖P4,原始圖有透明通道,是以生成的縮略圖也有白色背景。

白夜追兇 :手 Q 圖檔的顯示和發送邏輯

如果是PC發送PNG圖檔,用戶端去接收消息下載下傳圖檔呢?PC端發送圖檔不存在是否勾選原圖的概念,也不存在壓縮的概念(耿直boy)。用戶端接收方會去下載下傳PC端發送的圖檔P5和架平生成的縮略圖P7。

這時我在回歸過程中又發現了一起不尋常的現象。用戶端發送遊戲圖後,接收端收到圖檔,在AIO中的縮略圖會有一個由黑變白的過程。呵呵,兵來将擋,bug來我解。又滾去熟悉了下接收端的邏輯。

白夜追兇 :手 Q 圖檔的顯示和發送邏輯

發送的這張遊戲圖是由透明通道的,架平并沒有為有透明通道的圖檔添加白色背景的政策,是以接收端下載下傳的是一張黑色背景的架平縮略圖。

這裡要提到手q的預下載下傳政策。使用者可能會去點開大圖,如果點選時再去下載下傳,轉菊花的過程體驗很差,是以手q會綜合網絡情況、目前已用流量等次元去判斷是否需要提前幫使用者下載下傳大圖。圖中圖檔消息命中了預下載下傳政策,手q幫使用者提前下載下傳好了大圖。

這時候問了,大圖明明是黑色背景,為什麼AIO中會閃變成白色?哈哈哈,這裡又是手q人性化的一點,由于下載下傳好了大圖,為了讓使用者在AIO中可以直接可以看到比較清晰的縮略圖,手q不信任架平生成的縮略圖,用已經下載下傳的大圖在本地生成了相對高清的縮略圖。

而下載下傳的大圖是有透明通道的png,根據前面已經提到的産品政策,我們會給本地生成的縮略圖加上白色背景,是以出現了閃變~

白夜追兇 :手 Q 圖檔的顯示和發送邏輯

全文告一段落,在跟進問題的過程中,又完整的走了一遍手Q的圖檔發送流程。

除了提高對業務的熟悉程度之外,不禁感慨,前輩們為圖檔發送展示流程做了數不清的優化項,前人栽樹後人乘涼,由衷的欽佩!