欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~

作者:陈舜尧

导语: “这张图片在快捷发图栏背景是黑色的,为啥发到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的图片发送流程。

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

阅读推荐

一站式满足电商节云计算需求的秘诀Web 前端性能优化 : 如何有效提升静态文件的加载速度使用 Skeleton Screen 提升用户感知体验

此文已由作者授权腾讯云技术社区发布,转载请注明文章出处
原文链接:https://cloud.tencent.com/community/article/602504

白夜追凶 :手 Q 图片的显示和发送逻辑的更多相关文章

  1. css——手机端图片正确显示

    这两天遇到的问题汇总(一): 1.图片在app端显示有差异:如下                        左边图片是:图片显示太大,以至于让整个页面都失真的效果:右边是调好样式之后的效果,知道增 ...

  2. 使用MailKit发送带有内嵌图片的邮件且图片不显示成附件

    使用MailKit发送带有内嵌图片的邮件且图片不显示成附件 参考文章:MailKit---发送邮件 注意 在邮件客户端中是否显示内嵌图片为附件依据不同邮件有所不同,暂经测试Outlook和qq不显示为 ...

  3. 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  4. 手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  5. H5页面微信分享和手Q分享设置

    RT: 一. 手Q分享: 如下代码所示:设置好 description,name,image,即可,唯一注意的是image最好是200*200,要不然过小不美观,过大加载太慢 <head> ...

  6. img只显示图片一部分 或 css设置背景图片只显示图片指定区域

    17:14 2016/3/22img只显示图片一部分 或 css设置背景图片只显示图片指定区域 background-position: 100% 56%; 设置背景图片显示图片的哪个坐标区域,图片左 ...

  7. 海量服务实践──手 Q 游戏春节红包项目设计与总结(上篇)

    导语 大哥说.今年手Q游戏的春节红包你来做.那该怎么做?以及怎么做才干让大哥放心?本文从后台的角度出发讲述了这个过程和方法.对于关键的前台部分也有所涉及. 文件夹 1.需求背景 1.1.红包类别 1. ...

  8. Jmeter 发测试报告到邮箱,expand/collapse 图片不显示

    由于发送到邮箱中html文件是不包含expand/collapse 资源文件的,所以导致邮箱中这两个图片没有显示,解决方法有两种: 1. 使用http能访问的图片链接地址 修改change中的图片资源 ...

  9. 使用localResizeIMG3+WebAPI实现手机端图片上传

    前言 惯例~惯例~昨天发表的使用OWIN作为WebAPI的宿主..嗯..有很多人问..是不是缺少了什么 - - 好吧,如果你要把OWIN寄宿在其他的地方...代码如下: namespace Conso ...

随机推荐

  1. 201521123068 《java程序设计》 第11周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 多线程的冲突:同时运行的线程需要访问共享数据(临界资源) 多线程的互斥访问:两个或两个以上的线程需要同时对同一数据 ...

  2. PowerBI开发 第五篇:关系的设计

    PowerBI 使用 内存的列式数据库 VertiPaq,用于对已发布的数据集进行数据压缩和快速处理,能够使PowerBI报表执行脱机访问,面向列的处理,高度优化对1:N关系的处理性能.PowerBI ...

  3. 磁盘管理之inode与block

    索引式文件系统 什么是inode? Inode其实就是索引号,便于我们寻找我们文件所存储的数据块block,索引式文件系统在查找信息,读写操作上都比原来的文件系统要快,我们可以通过inode中记录的b ...

  4. Python跨目录调用模块

    目的就是将脚本执行的根目录加入环境变量. #!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = '人生入戏' import os,sy ...

  5. Python: 列表注意细节与元组的基本用法

    列表注意细节: 1.list.clear():将列表中成员清空(与del list区别开) 2.list.copy():复制一份相同的列表(浅COPY,只复制列表第一层) 3.如果两个列表相等,如li ...

  6. Log Reservation

    本文是在阅读<SQL Server Transaction Log Management>的Chapter 2: Log Internals时发现以往对Log Grows的理解比较片面,大 ...

  7. Flask-WTF CSRF 保护P3

    使用FlaskForm处理请求的任何视图函数都已经获得了CSRF保护.如果有些视图函数还在使用FlaskForm或AJAX请求,请尽快使用FlaskForm提供的CSRF扩展来保护它们. 导入 想要为 ...

  8. mysql死锁+解决

    自己作死,navicat不恰当的操作导致了表死锁,操作如下: 给表新加字段:name 没有选择允许为空,但是有没有设置初始值,所以运行的结果就是数据库表里有了name不允许为空但是确实为空的记录: 然 ...

  9. JVM菜鸟进阶高手之路六(JVM每隔一小时执行一次Full GC)

    转载请注明原创出处,谢谢! 上次分析详细地址在:http://www.jianshu.com/p/a6236cd39e2d 以为上次问题是rmi的问题就此结束了,但是问题并没有结束,其实本次问题不是r ...

  10. Rendering Problems Failed to load platform rendering library 为何打开布局页面时手机预览页面显示不出来?

    看到图片右上角的 android图标没有?把它改为低版本的就可以了,如我的是21就可以了.原因我想是因为sdk版本更新了不兼容导致的吧.