用户登录
用户注册

分享至

Android - 图片原理及深入分析优化

  • 作者: 王小明叫我哥
  • 来源: 51数据库
  • 2021-07-28

一、主流图片格式对比

1.webp

WebP是谷歌开发的一种新图片格式,WebP是同时支持有损和无损压缩的、使用直接色的、点阵图。

在无损压缩的情况下,相同质量的WebP图片,文件大小要比PNG小26%。

在有损压缩的情况下,具有相同图片精度的WebP图片,文件大小要比JPEG小25%~34%。

WebP图片格式支持图片透明度,一个无损压缩的WebP图片,如果要支持透明度只需要22%的格外文件大小。


2.jpeg&jpg

jpg是一种有损的基于直接色的图片格式。由于采用直接色,jpg可使用的颜色有1600w之多(2^24),而人眼识别的颜色数量大约只有1w多种,因此jpg非常适合色彩丰富图片、渐变色。jpg有损压缩移除肉眼无法识别的图片细节后,可以将图片的尺寸大幅度地减小。 但是jpg不适合icon、logo,因为相比gif/png-8,它在文件大小上丝毫没有优势。


3.png

png-8采用无损压缩,是基于8位索引色的位图格式。png-8相比gif对透明的支持更好,同等质量下,尺寸也更小。非常适合作为gif的替代品。但png-8也一个明显的不足就是不支持动画。

png-24采用无损压缩,是基于直接色的位图格式。png-24的图片质量堪比bmp,但是却有bmp不具备的尺寸优势。当然相比于jpg,gif,png-8,尺寸上还是要大。正是因为其高品质,无损压缩,非常适合用于源文件或需要二次编辑的图片格式的保存。 png-24与jpg一样能表达丰富的图片细节,但并不能替代jpg。图片存储为png-24比存储为jpg,文件大小至少是jpg的5倍,但在图片品质上的提升却微乎其微。所以除非对品质的要求极高,否则色彩丰富的网络图片还是推荐使用jpg。 png-24与png-8一样也支持透明。


4.heic格式

高效率图像格式在各方面均优于 JPEG,通过使用更现代的压缩算法,它可以将相同数量的数据大小压缩到 JPEG 图像文件的 50% 左右。

目前使用 HEIF 或 HEIC 照片唯一的缺点就是兼容性问题。现在的软件只要能够查看图片,那它肯定就可以读取 JPEG 图像,但如果你拍摄了以 HEIF 或 HEIC 扩展名结尾的图片,并不是在所有地方和软件中都可以正确识别。  这也是当我们将照片附加到电子邮件或在不支持 HEIF 文件的服务中进行共享时, iPhone 和 iPad 会自动将其转换为 JPEG 图像的原因。在使用 iTunes 将 HEIF 照片导入 Windows PC 时,也会自动将它们转换为 JPEG 格式。  虽然 Mac 从 macOS High Sierra 开始支持 .HEIF 和 .HEIC 文件,但 Windows 10 从 Windows 10 Build 17123 预览版才开始提供 HEIF 图像内置支持,所以对于老旧 Windows、macOS 和旧版 iOS 与 Android 用户需要使用第三方图像查看器或转换软件才能查看 .HEIF 或 .HEIC 文件。


二、Android采用webp的好处:

1.WebP 的优势体现在它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性,在 JPEG 和 PNG 上的转化效果都相当优秀、稳定和统一。


2.可以看到webp格式的支持度还不是很好,但是移动端的支持整体还可以


二、开启广色域增强

1.关于广色域

标准 RGB (sRGB) 外,Android 8.0(API 级别 26)还引入了对额外颜色空间的颜色管理支持,用于在具有兼容显示屏的设备上呈现图形。借助这种支持,您的应用可以通过 Java 或原生代码,使用从 PNG、JPEG 和 WebP 文件加载的嵌入式广色域配置文件呈现位图。


2.广色域特点

采用Display P3色域标准,DCI-P3规定的标准白色会比Display P3更偏黄一些,且Display P3由于更低Gamma值整体画面风格会更亮一些。


3.启用广色域

使用 colorMode 属性请求在兼容设备上以广色域模式显示 Activity。在广色域模式下,窗口可以在 sRGB 色域之外呈现,显示更鲜明的色彩。如果设备不支持广色域呈现,则此属性无效。如果您的应用需要确定某个特定显示屏是否支持广色域,请调用 isWideColorGamut() 方法。您的应用还可以调用 isScreenWideColorGamut(),该方法仅当显示屏支持广色域且设备支持广色域颜色呈现时才会返回 true

显示屏可能支持广色域,但不支持颜色管理,在这种情况下,系统不会向应用授予广色域模式。当显示屏不支持颜色管理时,就像 8.0 以前的所有 Android 版本一样,系统会将应用绘制的颜色重新映射到显示屏的色域。

如需在您的 Activity 中启用广色域,请在 AndroidManifest.xml 文件中将 colorMode 属性设置为 wideColorGamut。您需要对想要启用广色域模式的每个 Activity 执行此操作。


 android:colorMode="wideColorGamut" 

您还可以通过调用 setColorMode(int) 方法并传入 COLOR_MODE_WIDE_COLOR_GAMUT,在您的 Activity 中以编程方式设置颜色模式。


三、图片压缩策略

1.BitmapFactory.Options优化

BitmapFactory.Options的作用:

1.防止内存溢出;

2.节省内存开销;

3.系统更流畅;


BitmapFactory.Options的重要属性:

1.injustDecodeBounds; *设为true,那么BitmapFactory并不会真的返回一个Bitmap给你,它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM。 *设置为false,BitmapFactory返回bitmap;

2.outWidth&outHeight; *bitmap图像的宽和高;

3.inSampleSize; 获取采样率 *inSampleSize大于1时,图像高、宽分别以2的inSampleSize次方分之一缩小 *inSampleSize小于等于1时,图像高、宽不变;

4.inpreferredConfig: *ALPHA_8: 每个像素用占8位,存储的是图像的透明值,占1个字节; *RGB_565:每个像素用占16位,分别为5-R,6-G,5-B通道,占2个字节; *ARGB-4444:每个像素占16位,即每个通道用4位表示,占2个字节; *ARGB_8888:每个像素占32位,每个通道用8位表示,占4个字节; 5.inDither: *是否进行图像抖动处理;

6.inMutable: *如果设置为true,将返回一个mutable的bitmap,可用于修改BitmapFactory加载而来的bitmap.

7.inScale: *是否需要放缩位图


2.Luban鲁班压缩

压缩效果:

内容 原图 Luban Wechat
截屏 720P 720*1280,390k 720*1280,87k 720*1280,56k
截屏 1080P 1080*1920,2.21M 1080*1920,104k 1080*1920,112k
拍照 13M(4:3) 3096*4128,3.12M 1548*2064,141k 1548*2064,147k
拍照 9.6M(16:9) 4128*2322,4.64M 1032*581,97k 1032*581,74k
滚动截屏 1080*6433,1.56M 1080*6433,351k 1080*6433,482k


核心算法:

private int computeSize() {
    srcWidth = srcWidth % 2 == 1 ? srcWidth + 1 : srcWidth;
    srcHeight = srcHeight % 2 == 1 ? srcHeight + 1 : srcHeight;

    int longSide = Math.max(srcWidth, srcHeight);
    int shortSide = Math.min(srcWidth, srcHeight);

    float scale = ((float) shortSide / longSide);
    if (scale <= 1 && scale > 0.5625) {
        if (longSide < 1664) {
            return 1;
        } else if (longSide >= 1664 && longSide < 4990) {
            return 2;
        } else if (longSide > 4990 && longSide < 10240) {
            return 4;
        } else {
            return longSide / 1280 == 0 ? 1 : longSide / 1280;
        }
    } else if (scale <= 0.5625 && scale > 0.5) {
        return longSide / 1280 == 0 ? 1 : longSide / 1280;
    } else {
        return (int) Math.ceil(longSide / (1280.0 / scale));
    }
}


四、服务端请求地址Resize转换

Resize目的

自适应用户手机大小,自动选择合适的大小的图片进行下载展示,提高流量使用效率。

Resize条件

  1. 图片地址符合CDN替换规则(详见下面说明)
  2. 图片地址要求统一符合正则表达式 [_%dx%d.%@],示例_160x160.jpg ,即需要地址有尺寸规则且有格式。没有的话则不会重新resize

Resize规则

  1. 根据视图实际像素大小进行
  2. resize后长宽不能超过960像素
  3. resize默认步长为40像素(视图实际像素大小值往一个区间值上)

五、图片解码 libjpeg turbo 优化

1.网上数据


2、自己测试数据

示例 1.2M

libjpeg turbo

时间  2000ms

空间  大于安卓7.0 205kb ,小于安卓7.0 140kb


原生

时间 250ms

空间 210 kb


3.分析:

1.Android原生 2D 处理框架为 Skia, 在 JPEG 图像压缩上也是链接了 libjpeg-turbo,区别在于安卓7.0系统以下考虑性能没有采用普通的哈夫曼(Huffman)算法。

2.使用网上开源的使用哈夫曼(Huffman)算法的libjpeg-turbo,性能消耗接近10倍,且只对安卓7.0有压缩效果,安卓7.0以上原生应该是哈夫曼(Huffman)对算法性能做了优化,性能与未使用差别不大。

4.结论

不建议集成开源哈夫曼(Huffman)算法的libjpeg-turbo,只对Android 7.0以下有效, 只有30%左右对压缩,牺牲8倍以上性能。

本文地址:http://www.51sjk.com/Upload/Articles/1/0/254/254423_20210628000750087.jpg

软件
前端设计
程序设计
Java相关