白夜追凶 :手 Q 图片的显示和发送逻辑

作者:陈舜尧导语: “这张图片在快捷发图栏背景是黑色的,为啥发到AIO(会话窗口)里背景就变成白的了?” 通过一个bug单,对黑白背景问题跟进的过程中发现了手q中很多奇怪的表现。一层层看代码,整理总结了手q中图片的显示和发送逻辑,以及对透明通道图片的特殊处理。

一、黑背景?白背景?

这张图片在快捷发图栏背景是黑色的,发到AIO里背景就变成白的了。拿到问题,分析有两种可能原因:展示view的背景色不一致;选中的png图片的透明通道在AIO和快捷发图栏两个不同的场景下过滤规则不一致。

很容易就能发现两个场景处理图片的不同:快捷发图栏将png图片获取为bitmap,再压缩成jpeg,这个过程直接忽略了透明通道,android默认处理的结果就是一张黑色背景的jpeg。快捷发图栏所有图片的字节流持久化到同一个文件里,这样做的目的是下次从本地加载多张图片时,会共用同一个文件IO,提高加载效率;

AIO中的缩略图也是由原图压缩成jpeg,在处理的代码中,我发现了人为加白色背景的逻辑,原来这都是产品的策略,可能考虑到AIO中png图片黑色背景视觉上不太美观,所以进行了特殊处理。然而快捷发图栏和AIO中视觉上没做到统一,有道是 产品拍头一时爽,开发解bug火葬场

二、都是png,怎么有黑又有白!

既然问题找到了,美滋滋的准备加个鸡腿,然而事情并没有那么简单!回归问题的时候我用了另外一张png图片测试,咦,怎么这张图片在AIO中背景是黑色的?

有两个怀疑方向:1、png压缩成jpeg的过程,丢失透明通道导致AIO中这张图片为黑色背景;2、有没有可能是在canvas上绘制白色背景失败导致的该问题?

先从第一个方向分析,通过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看上去也没问题。。。

啪啪啪打脸,看来不是怀疑的两个方向出了问题。于是病急乱投医把锅甩给了图片。。。。。

“会不会是png格式的问题,png某个参数导致转化过程中bitmap背景不同????”

在查阅资料、用工具分析对比了两张png图片的结构,欣喜得发现问题跟png格式并没有半毛钱关系。冷静下来,还是用老办法,一步一步跟代码!!!!

游戏图压缩后P2大于P1(是的你没看错,压缩后图片反而大,压缩步骤取bitmap,再绘制,最后质量压缩成jpeg),所以是拿原始图片当作大图P3去生成缩略图P4,原始图片有透明通道,所以对应的缩略图能加上白色背景;骰子图片压缩后发现比原图小,所以用压缩图P2当作大图P3去生成缩略图P4。P2是质量压缩png生成的jpeg,已经丢失透明通道,是一张黑色背景的图。即使在P4加上白色背景也被上层图层覆盖,我们看到的就是黑色骰子缩略图。

我之前分析的过程中忽略了压缩原始图片生成P2这一步。一叶障目,理清了思路,问题就显而易见了!

三、黑白分明,搞清楚所有情况下的表现

既然理清了流程,那就把所有情况下的表现分析下吧。我们看看勾选原图下的表现。

这里很好理解,骰子图勾选原图后,是把原始图片生成缩略图P4,原始图有透明通道,所以生成的缩略图也有白色背景。

如果是PC发送PNG图片,客户端去接收消息下载图片呢?PC端发送图片不存在是否勾选原图的概念,也不存在压缩的概念(耿直boy)。客户端接收方会去下载PC端发送的图片P5和架平生成的缩略图P7。

四、黑白闪变是什么鬼!

这时我在回归过程中又发现了一起不寻常的现象。客户端发送游戏图后,接收端收到图片,在AIO中的缩略图会有一个由黑变白的过程。呵呵,兵来将挡,bug来我解。又滚去熟悉了下接收端的逻辑。

发送的这张游戏图是由透明通道的,架平并没有为有透明通道的图片添加白色背景的策略,所以接收端下载的是一张黑色背景的架平缩略图。

这里要提到手q的预下载策略。用户可能会去点开大图,如果点击时再去下载,转菊花的过程体验很差,所以手q会综合网络情况、当前已用流量等维度去判断是否需要提前帮用户下载大图。图中图片消息命中了预下载策略,手q帮用户提前下载好了大图。

这时候问了,大图明明是黑色背景,为什么AIO中会闪变成白色?哈哈哈,这里又是手q人性化的一点,由于下载好了大图,为了让用户在AIO中可以直接可以看到比较清晰的缩略图,手q不信任架平生成的缩略图,用已经下载的大图在本地生成了相对高清的缩略图。

而下载的大图是有透明通道的png,根据前面已经提到的产品策略,我们会给本地生成的缩略图加上白色背景,所以出现了闪变~

五、总结

全文告一段落,在跟进问题的过程中,又完整的走了一遍手Q的图片发送流程。

除了提高对业务的熟悉程度之外,不禁感慨,前辈们为图片发送展示流程做了数不清的优化项,前人栽树后人乘凉,由衷的钦佩!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏DeveWork

WebFont 三宗罪之二:吹毛求疵的WebFont 渲染差异

话说上次发了篇危言耸听的“WebFont 三宗罪”系列之一,今日来讲三宗罪之二:吹毛求疵的WebFont 渲染差异。为什么用上“吹毛求疵”这个修饰词呢?因为Je...

1725
来自专栏葬爱家族

Android高德之旅(7)绘制点标记

本系列第7篇,终于讲到了绘制。说到吃饭...呸,说到绘制,这在地图应用中是非常重要的一部分,很多时候我们集成地图SDK时,都不可能仅仅使用默认地图元素,在默认元...

903
来自专栏腾讯NEXT学位

简单粗暴的移动端适配方案 - REM

38510
来自专栏计算机编程

官方自适应新布局ConstraintLayout

谷歌在2016年自己研发的类似于IOS约束的布局,可以很好的完成自定义的布局控件的适配,现如今2K甚至是4K屏的出现,导致很多手机应用的开发受到适配上的限制,但...

1452
来自专栏向治洪

Android仿网易云音乐播放界面

概述 网易云音乐是一款非常优秀的音乐播放器,尤其是播放界面,使用唱盘机风格,显得格外古典优雅。这里抛砖引玉,原文地址:http://www.jianshu.co...

64610
来自专栏非著名程序员

Android 实现视屏播放器、边播边缓存功能、外加铲屎(IJKPlayer)

Android 实现视屏播放器与边播边缓存功能外加蹲坑铲屎(IJKPlayer) hello,大家好,我就是那个会掀桌子的话唠,刚刚结束两篇关于音频播放与录制的...

5529
来自专栏非著名程序员

Android如何实现毛玻璃效果之Android高级模糊技术

Android高级模糊技术 非著名程序员 自从iOS系统引入了Blur效果,也就是所谓的毛玻璃、模糊化效果,磨砂效果,各大系统就开始竞相模仿,这是怎样的一个效果...

24910
来自专栏前端小作坊

中文排版二三事

前段时间一直在折腾中文排版相关的事情,自认为结果还算不错。故开源之,即是Entry.css。这是一个可配置的、更适合阅读的中文文章样式库,可以用来快速搭建中文博...

731
来自专栏python小白到大牛

用 Python 实现打飞机,让子弹飞吧!

安装好 pygame 在第一次使用 pygame 的时候,pyCharm 会自动 install pygame。

1243
来自专栏林德熙的博客

Xamarin Forms 进度条控件

本文翻译:http://xamlnative.com/2016/04/14/xamarin-forms-a-simple-circular-progress-c...

801

扫码关注云+社区