经常看到有人问:“安卓版微信发出去的图片怎么那么渣!比iPhone的差远了!”。不只是微信,很多应用安卓版的图片质量就是要比iPhone版逊色很多,这到底是怎么回事?

我们团队最初也纠结过这个问题,费了半天劲、绕了好大圈,直到最后才发现,原来这是谷歌犯得一个“小”错误,而且一直错到了今天。
   
谷歌的错就在于:libjpeg。

libjpeg是广泛使用的开源JPEG图像库(参考 http://en.wikipedia.org/wiki/Libjpeg
),安卓也依赖libjpeg来压缩图片。通过查看源码,我们会发现安卓并不是直接封装的libjpeg,而是基于了另一个叫Skia的开源项目
(http://en.wikipedia.org/wiki/Skia_Graphics_Engine)来作为的图像处理引擎。Skia是谷歌自己维
护着的一个大而全的引擎,各种图像处理功能均在其中予以实现,并且广泛的应用于谷歌自己和其它公司的产品中(如:Chrome、Firefox、
Android等)。Skia对libjpeg进行了良好的封装,基于这个引擎可以很方便为操作系统、浏览器等开发图像处理功能。

libjpeg在压缩图像时,有一个参数叫optimize_coding,关于这个参数,libjpeg.doc有如下解释:

boolean optimize_coding
    TRUE causes
the compressor to compute optimal Huffman coding tables
    for the
image.  This requires an extra pass over the data
and
    therefore
costs a good deal of space and time.  The default
is
    FALSE, which
tells the compressor to use the supplied or default
    Huffman
tables.  In most cases optimal tables save only a
few percent
    of file size
compared to the default tables.  Note that when
this is
    TRUE, you
need not supply Huffman tables at all, and any you do
    supply will
be overwritten.

这段话大概的意思就是如果设置optimize_coding为TRUE,将会使得压缩图像过程中基于图像数据计算哈弗曼表(关于图片压缩中的哈弗曼表,请自行查阅相关资料),由于这个计算会显著消耗空间和时间,默认值被设置为FALSE。

这段解释乍看起来没有任何问题,libjpeg的代码也经受了十多年的考验,健壮而高效。但很多人忽略了这一点,那就是,这段解释是十多年前写的,对于当
时的计算设备来说,空间和时间的消耗可能是显著的,但到今天,这似乎不应再是问题,相反,我们应该更多的考虑图片的品质(越来越好的显示技术)和图片的大
小(越来越依赖于云服务)。

谷歌的Skia项目工程师们最终没有设置这个参数,optimize_coding在Skia中默认的等于了FALSE,这就意味着更差的图片质量和更大的图片文件,而压缩图片过程中所耗费的时间和空间其实反而是可以忽略不计的。那么,这个参数的影响究竟会有多大呢?

经我们实测,使用相同的原始图片,分别设置optimize_coding=TRUE和FALSE进行压缩,想达到接近的图片质量(用Photoshop
放大到像素级逐块对比),FALSE时的图片大小大约是TRUE时的5-10倍。换句话说,如果我们想在FALSE和TRUE时压缩成相同大小的JPEG
图片,FALSE的品质将大大逊色于TRUE的(虽然品质很难量化,但我们不妨说成是差5-10倍)。

我们又对Android和iOS进行了对比(均使用标准的JPEG压缩方法),两个系统都没有提供设置optimize_coding的接口(通过阅读源
码,我们已经知道Android是FALSE,iOS不详),当压缩相同的原始图片时,结果也是一样,iOS完胜。想要品质接近,文件大小就会差出
5-10倍,而如果要压缩出相同大小的文件,Android的压缩品质简直就是惨不忍睹。

结果说明,苹果很清楚optimize_coding参数和哈弗曼表的意义,这里需要特别指出,苹果使用的哈弗曼表算法与libjpeg(及我们后来自行
采用的libjpeg-turbo)不同,像素级可以看出区别,苹果似乎基于libjpeg又进行了进一步的优化,压缩出来的图片细节上更柔和、更平滑。

以上试验,我们尝试过多个原图、多种压缩比例,试验结果均类似,如有兴趣,您不妨也自行进行尝试。

 

为什么Android的图片质量会比iPhone的差?的更多相关文章

  1. 为什么微信android图片质量会比iphone的差?

    为什么微信android图片质量会比iphone的差? 我们团队最初也纠结过这个问题,费了半天劲.绕了好大圈,直到最后才发现,原来这是谷歌犯得一个“小”错误,而且一直错到了今天. 谷歌的错就在于:li ...

  2. session图片验证码,页面和请求是两个地址。android手机好用,iphone 失效。

    问题描述:之前在H5页面用session做了一个验证码.安卓手机好使.但是到苹果就不好使了(页面访问是一个域名地址,ajax请求是用另外的一个ip地址). 详细说明: 验证码请求后台图片正常显示,an ...

  3. Android 开关按钮切换,类似于iphone 效果,view实现

    1.实现的效果 gitHub :  https://github.com/zcweng/ToggleButton

  4. linux安装 Android Studio详细教程,支持性较差,需要安装最新底层库内核的linux

    安装 Android Studio详细教程 libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5 lib32z1 jdk1.8.0_25 android-st ...

  5. Android 中图片压缩分析(上)

    作者: shawnzhao,QQ音乐技术团队一员 一.前言 在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩. 前者是在不改变图片尺寸的情 ...

  6. js 判断移动设备、pc端、android、iPhone、是否为微信、微博、qq空间

    varbrowser = {   versions: function () {      var u = navigator.userAgent, app = navigator.appVersio ...

  7. 为什么iphone手机比android手机流畅

    作为当下最流行.市场占用份额最大的两大手机操作系统IOS和android,目前两者加起来的市场占用率达到90%.我曾经一直用android手机,没有用过iphone,那时候正直iphone4和ipho ...

  8. JS判断请求来自Android手机还是iPhone手机,根据不同的手机跳转到不同的链接。

    <script type="text/javascript">var browser = {versions: function () {var u = navigat ...

  9. 判断iPhone/android手机

    JS判断请求来自Android手机还是iPhone手机,根据不同的手机跳转到不同的链接. var browser = {versions: function () {var u = navigator ...

随机推荐

  1. idhttp的用法

    1)POST function PostMethod(http: TIDhttp; URL: string; Params: TStringList): string;var RespData: TS ...

  2. django 创建项目

    django-admin startproject project-name 启动服务器 python manage.py runserver 0.0.0.0:8000 配置ALLOW_HOST

  3. 《深入理解Spark:核心思想与源码分析》一书正式出版上市

    自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售 ...

  4. SparkContext的初始化(叔篇)——TaskScheduler的启动

    <深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...

  5. HTML5的viewport使用

    viewport 语法介绍: <!-- html document --> <meta name="viewport" content=" height ...

  6. spring:bean的定义

    一个完整的Bean的配置文件: <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE beans ...

  7. 转 父表字表统计查询的sql练习

    create table father(        f_id number(2) primary key,        f_name varchar2(10) ); create table s ...

  8. Java里的if else语句例子

    import java.util.Scanner;public class if_else2{ public static void main(String[] args) { Scanner s=n ...

  9. 思维导图软件TheBrain 8全新发布 提供更强大的信息管理

    TheBrain思维导图软件是全球唯一一款动态的网状结构的思维导图软件,广泛用于学习.演讲.项目管理.会议.需求调研与分析等.其独特的信息组织方式使得用户可以创建并连接到数以万计的数字想法,为此在全球 ...

  10. Python操作memcached及redis

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...