Android APP图片优化

1.WebP图片在安卓上的使用(https://developer.android.com/studio/write/convert-webp.html)

WebP图片格式

WebP是Google在2010推出的一种图片格式,此图片格式可以比jpeg有更小的体积,同时支持无损压缩和透明。关于WebP格式的介绍参见http://www.jonathanklein.net/2013/02/a-comprehensive-guide-to-webp.html

WebP格式,Google开发的一种旨在加快图片加载速度的图片格式。Android 4.0(API级别14)及更高版本支持有损WebP图像,Android 4.3(API级别18)及更高版本支持无损和透明的WebP图像。

2010年谷歌推迟的图片格式,专门用来在web中使用, 压缩率只有jpg的2/3或者更低; 第一个版本的webp图片格式是有损的, 新版本中webp图片是无损的。

相对于png图片,webp比png小了45%,但是缺点是你压缩的时候需要的时间较长;

问题描述

Android原生支持的图片格式有JPEG,PNG,GIF,BMP和WebP五种。但是在Android应用开发中能够使用的编解码格式只有其中三种:JPEG、PNG、WebP,图片格式可以通过查看Bitmap类的CompressFormat枚举值来确定。WebP格式是从Android4.0版本开始支持,对Android4.0及以上版本可以直接用BitmapFactory来实现解码,对Android4.0以下版本不支持。 
使用BitmapFactory对图片解码的示例代码如下,options是BitmapFactory.Options对象。BitmapFactory会自动判断图片格式,如果解码成功会返回一个有效的Bitmap对象,如果解码失败会返回null。

Bitmap bitmap = BitmapFactory.decodeStream(imageStream, null, options);

正常来说,对Android4.0及以上版本通过上述代码解码WebP格式应该能够返回有效的Bitmap对象,然后实际使用过程中发现,有些WebP格式图片在Android4.0以上机型上无法通过BitmapFactory来解码,此外有个别机型虽然也是Android4.0以上版本,但所有WebP格式图片都无法解析。

再附上一个第三方解决方案(https://github.com/alexey-pelykh/webp-android-backport/tree/master/webp-android-backport-library
/**
  * Specifies the known formats a bitmap can be compressed into
  */
public enum CompressFormat {
     JPEG    ( 0 ),
     PNG     ( 1 ),
     WEBP    ( 2 );
 
     CompressFormat( int nativeInt) {
         this .nativeInt = nativeInt;
     }
     final int nativeInt;
}

问题原因

从官方文档中可以看到在Android4.0到Android4.2.1之间的版本不支持无损压缩和透明格式的WebP图片的编解码。所以如果从要解析的WebP图片中包含无损压缩或透明格式,且当前是Android4.0到Android4.2.1之间的系统,则BitmapFactory解码时就会出错。 
 
此外,个别Android机型虽然是Android4.0及以上的版本,但是在原生ROM基础上去掉了WebP功能,目前发现的只有NokiaXL,它是Android4.1的版本,但不支持任何WebP格式的编解码。

解决方法

Android SDK中并没有任何api可以判断当前设备是否支持WebP格式,也没有办法在解码前判断一张WebP格式图片中是否包含无损压缩和透明格式。只能通过BitmapFactory.decodeStream的结果来判断是否解码成功。因此,只能先尝试用BitmapFactory来解码,如果解码失败,再尝试用其他方法(通过google提供的libwebp)。目前来看Android4.2及以上版本中应该都已经支持所有的WebP格式图片的解码,因此,也可以统一从Android4.2版本开始用BitmapFactory来对WebP格式图片编解码,对Android4.2以下版本用其他方式实现。

然而,对于动态WebP,目前只能找到facebook的开源库Fresco对其支持,不过Fresco最低仅支持API 9,且引用的相关库较多。

https://www.fresco-cn.org/

2.SVG(Scalable Vector Graphics)图的使用

“清晰”和“体积”的矛盾与麻烦

面对android的各种dpi某事,想要所有设备上的图片都能有最清晰的效果,就意味着每种dpi模式都必须提供一份对应尺寸的资源,除非你不在乎安装包的体积有多大,所以这显然是不可能去做的。

在过去的几年里andorid从mdpi发展到xxxhdpi,每当APP想让相同的图片在更清晰的屏幕上显示我们想要的效果时,我们总要重新提供一份体积更大的高清png并且删掉可能不太多使用的小分辨率图片。

只保留一种分辨率图片的方法确实比所有dpi都来一份体积要小一点,然后只是用一份资源还需要承担的负面效果则是当向其他dpi模式scale时,图片也会变得模糊,并且你还要决定自己什么时候该更换上更大分辨率的图片了。

矢量图SVG

位图自身特点导致了高清资源同安装包体积之间的矛盾。这方面矢量图存在明显的优势,它可以在表达清晰图片的同时,不增加文件体积。而且只要你不重新设计图片,就用不着再去适配高dpi模式,矢量图什么分辨率都可以自适应。

我们认为SVG是比较合适的矢量化资源方案,因为它相比目前android上的一些矢量化方案更成熟、周边工具支持更好。像VectorDrawable、ttf这样的方案总有这不尽人意的地方,对于UI同学来说这两个模式也不太好操作,不能轻易生成的资源会牺牲大家的工作效率是明显得不偿失的。(另外,VectorDrawable经过我们测试发现性能并不理想,这受限于他的实现方法。)

使用SVG图面临的几个问题

1) 性能问题

理论上讲,SVG的效率可能会不如PNG好,这是因为它需要运行时的计算和对应平台的渲染绘制。而且对于PNG来说的另一优势是在开启硬件加速的设备上,绘制Bitmap一个非常快速的过程。可以想象,让SVG不比PNG慢将是一件很有挑战的事情。

2) 开发者的使用成本问题

SVG并不是android支持的标准资源格式,android资源框架自然不可能天然支持SVG的资源加载,而修改框架和提供支持很可能意味着会增加后面使用SVG的开发同学的学习成本和使用成本。因此必须要考虑如何即可以用SVG但又不增加开发负担。

3) 设计师的要求

SVG图的制作,对设计师的要求也很高,因为SVG涉及到CSS编码,不光是要求设计师掌握PS就可以了。好在现在有个比较好的开源SVG库http://www.iconfont.cn/plus/collections/index?type=2&spm=a313x.7781069.1998910419.5.hOR7v0

什么样的图适用SVG?

矢量图适用于简单的图标。Material 图标是适合在应用中用作矢量图的图像类型的一个好例子。相比之下,许多应用的启动图标包含许多细节,因此更适合用作光栅图像。

与对应的光栅图像相比,矢量图首次加载时可能消耗更多的 CPU 资源。之后,二者的内存使用率和性能则不相上下。我们建议您将矢量图像限制为最大 200 x 200 dp;否则,绘制它可能需要耗费很长的时间。

尽管矢量图确实支持一种或多种颜色,但在很多情况下,最好将图标设置为黑色 (android:fillColor="#FF000000")。通过此方法,您可以为布局中放置的矢量图添加 tint 属性,图标颜色将随之变为 tint 颜色。如果图标颜色不是黑色,图标颜色可能反而与 tint 颜色较为搭配。

为图片资源着色


利用 Android 5.0(API 级别 21)及更高版本,您可为位图以及定义为 Alpha 蒙版的点九图着色。 您可使用颜色资源或分解为颜色资源(例如 ?android:attr/colorPrimary)的主题属性为其着色。 通常,您只有一次机会创建这些资产并自动为其上色以符合您的主题。

您可利用 setTint() 方法为 BitmapDrawable 或 NinePatchDrawable 对象着色。您也可以利用 android:tint 以及 android:tintMode 属性设置您的布局中的着色颜色和模式。

矢量图向后兼容性解决方案

下表归纳了可用于实现向后兼容性的两种技术:

技术
APK 中的可绘制资源
XML VectorDrawable 元素
版本
版本号标志
应用代码
PNG 生成 矢量和光栅 支持的子集

SVG:适用于 Gradle 的 Android 插件 1.5.0 或更高版本

PSD:Android Studio 2.2 或更高版本

默认 支持的各种编码技术
支持库 23.2 或更高版本 矢量 完全支持 适用于 Gradle 的 Android 插件 2.0 或更高版本 需要支持库声明 支持的编码技术子集

对于 Android 5.0(API 级别 21)及更高版本,Vector Asset Studio 支持所有 VectorDrawable 元素。为向后兼容 Android 4.4(API 级别 20)及更低版本,Vector Asset Studio 支持以下 XML 元素:

 

SVG图文件说明

  1. <?xml version="1.0" standalone="no"?>  
  2. <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"   
  3. "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">  
  4.   
  5. <svg width="100%" height="100%" version="1.1"  
  6. xmlns="http://www.w3.org/2000/svg">  
  7.   
  8. <path d="M250 150 L150 350 L350 350 Z" />  
  9.   

10. </svg>  

上面有一个path 标签,里面用到了 M 和 Z 指令,M 就相当于 android Path 里的moveTo(),Z 则相当于 Path 里的close();

我们先看下SVG 里关于path 有哪些指令:

  1. M = moveto   相当于 android Path 里的moveTo(),用于移动起始点  
  2. L = lineto   相当于 android Path 里的lineTo(),用于画线  
  3. H = horizontal lineto     用于画水平线  
  4. V = vertical lineto       用于画竖直线  
  5. C = curveto               相当于cubicTo(),三次贝塞尔曲线  
  6. S = smooth curveto        同样三次贝塞尔曲线,更平滑  
  7. Q = quadratic Belzier curve             quadTo(),二次贝塞尔曲线  
  8. T = smooth quadratic Belzier curveto    同样二次贝塞尔曲线,更平滑  
  9. A = elliptical Arc   相当于arcTo(),用于画弧  

10. Z = closepath     相当于closeTo(),关闭path  

支持库

此技术需要 Android 支持库 23.2 或更高版本、适用于 Gradle 的 Android 插件 2.0 或更高版本,且仅使用矢量图。利用支持库中的 VectorDrawableCompat 类,可实现在 Android 2.1(API 级别 7)及更高版本中支持 VectorDrawable

在使用 Vector Asset Studio 之前,您必须向 build.gradle 文件添加一条声明:

android {
   defaultConfig {
     vectorDrawables.useSupportLibrary = true
   }
}
 
dependencies {
   compile 'com.android.support:appcompat-v7:23.2.0'
}

您还必须使用与支持库兼容的编码技术,例如对矢量图使用 app:srcCompat 属性,而不是 android:src 属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值