白夜追凶 :手 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 条评论
登录 后参与评论

相关文章

来自专栏数据小魔方

think-cell chart系列16——树状分布图

今天跟大家分享think-cell chart系列的第16篇——树状分布图。 大家不要困惑于该图表的名称——树状分布图,其实它用的技巧非常简单(就是基本图表的组...

3664
来自专栏Duncan's Blog

Personalized Search论文阅读笔记-08年SIGIR

对于这样允许大众分类的应用,如何满足用户在搜索时尽可能准确地返回用户所需要的资源是一个有意思的问题。因为如果像传统的搜索方法仅通过查询关键词去匹配搜索结果,返回...

923
来自专栏数据小魔方

图表案例——简约却不简单的图表制作技巧

我们通常看到的小而美的图表,一般都是经过图表制作者深层次加工过的成品。 而要想了解一个规范的商务图表制作过程,对图表的拆解与还原就显得非常重要。 今天的案例是关...

3399
来自专栏向治洪

android自定义view实现公章效果

上次去一个公司面试,面试官问了一个题,怎么用android的自定义view实现一个公章的效果,据说这是华为之前的面试题,我想了下,要是公章的效果,最外层是一个圆...

2105
来自专栏Crossin的编程教室

【每周一坑】生成九宫格图片

非常简单的功能,但在开发中很常见,很多网页/应用里缩略图都是对图片进行缩放+切割得到的。

1073
来自专栏MixLab科技+设计实验室

TensorFlow.js、迁移学习与AI产品创新之道

TensorFlow 的 JS 版本终于出啦,deeplearn.js 正式收编至 TensorFlow 项目,并改名为 TensorFlow.js : 采用 ...

4024
来自专栏前端新视界

有趣的 CSS 像素艺术

原文:fun-times-css-pixel-art 译者:nzbin 友情提示:由于国内网络的原因,CodePen可能会打不开或者非常慢,请耐心等待! ...

1907
来自专栏Android先生

快给你的app上锁吧(android图案解锁)

思路 这里又是一个九宫格布局,布局可以参考上一篇快给你的app上锁吧(android数字解锁),只不过这里的九宫格上我们画的是图片(bitmap)。onDraw...

972
来自专栏MixLab科技+设计实验室

TensorFlow.js、迁移学习与AI产品创新之道

TensorFlow 的 JS 版本终于出啦,deeplearn.js 正式收编至 TensorFlow 项目,并改名为 TensorFlow.js :

7049
来自专栏CDA数据分析师

技能 | R语言的igraph画社交关系图示例

R语言中的igraph可以很方便地画出社交关系图。下面是几个示例。 1.最简单的社交关系图 library(igraph) dolphin <- read.cs...

2829

扫码关注云+社区