lingsen.zeng

移动端如何使用 WebP(下)

1. 图片编解码原理

图片的编码过程是将 YUV 或者 RGB 像素格式的原始图片编码为压缩格式如 WebP 或者 JPG。图片的解码过程是将压缩格式还原为 YUV 或者 RGB 的原始图片。图片在控件或者屏幕上的渲染展示只能使用原始像素格式,也就是压缩格式的图片必须解码之后才能展示。

2. WebP 解码

我们参考 iOS-WebP 工程,简单了解一下 WebP 的解码过程。

可见这个解码函数的作用是将 WebP 图片 Data 转换成 UIImage。整个解码功能的实现是依赖于 libwebp 库。解码第一步是调用 WebPGetInfo 函数从 WebpData 中读取图片长宽等信息。第二步是配置解码参数 WebPDecoderConfig ,其中一个重要的参数是 output.colorspace ,即设置解码之后图片的像素格式。示例代码中设置为 MODE_RGBA,从 enum WEBP_CSP_MODE 类型的定义看,解码设置支持多种的 RGB 和 YUV 类型格式。另外的还可以配置图片剪裁、缩放等参数,具体可看考 libwebp API。 接下来,第三步将 WebP 数据解码为 RGBA 数据, 第四步将 RGBA 组装为 UIImage。

编码过程与解码相似,需要注意的是 WebP 的有损压缩方式只支持压缩 YUV 数据,如果原始格式是 RGB 可以通过转换为 YUV 数据之后再进行压缩编码。libwebp 也内置了一个转换函数可供使用。

3. 使用 UIImageView 展示 WebP 图片

在 UIImageView 中使用 WebP 格式图片的最佳实践是依赖 SDWebImage 库。

安装 SDWebImage(支持 WebP):

使用方法:

SDWebImage 安装之后内置 libwebp 源码,并在 UIImage+WebP.m 封装实现了 WebP 格式的解码功能。通过 SDWebImage 我们可以非常方便的在 UIImageView 中使用 WebP 格式的图片。

4. 使用 UIWebView 展示 WebP 图片

在以 Native 方式开发的 App 中也会大量使用的 UIWebView 来展示一些简单页面,然而 Safari 及 UIWebView 当前并不支持 WebP 格式。若是想在 UIWebView 中也把图片显示出来,一个解决思路就是:拦截替换。拦截 WebP 图片然后转换为 jpg 或者 png 再交给 UIWebView 进行渲染和展示。

拦截替换 WebP 有两种具体实现方式。

方式 1:

通过 UIWebView 代理函数给出的页面加载时机进行 WebP 图片的拦截和替换。这种方式首先要遍历获取 HTML 文档中的所有 WebP 图片链接。获取图片链接过程需要依赖第三方 HTML parser 来解析 HTML 文档,或者通过提前协商好的 HTML 内嵌 js 函数进行通信。在得到所有的 WebP 图片链接之后,将 WebP 下载解码并转换为 jpg 或者其他图片 data,然后再 base64 编码成字符串内嵌到 <img> 标签,让 UIWebView 进行加载。

方式 2:

通过 NSURLProtocol 全局拦截和过滤所有 HTTP 请求,将 WebP 数据直接转换为其他格式图片数据,再封装为 response body 吐给原来的 HTTP 请求。代码示例:

这样就可以达到以透明的方式使用 WebP 图片。但是由于 NSURLProtocol 的全局性质,影响范围大,这种方式存在潜在的风险,需要严格的过滤和限制 WebP 请求的拦截。NSURLProtocol 作用的叠加性质,也无法保证与其它第三方代码的兼容。虽然这种方式有很多代码可以参考,本文附带的 demo 也有此种方式的实现,但是在具体工程中使用还需要谨慎和完善。

注意:上文已经提到这种全局 NSURLProtocol 拦截的方式存在较大风险。一些网络文章也普遍的引用这种实现方式,但是这段代码是不严谨的,原因在于 NSURLSession 支持流式的 HTTP 请求,或者在 response body 体积比较大的时候,从 didReceiveData 回调回来的一次数据仅仅是整个 response body 的一部分。

5. 总结

在 iOS 平台使用 SDWebImage 结合又拍云图片处理 API,在原始图片 URL 后面拼接后缀 !/format/webp,不需要其他任何改变,就可以简单快捷的利用 WebP 格式来大幅度减少图片请求流量,提高图片加载体验。

如果是在 iOS 上使用浏览器访问 WebP 图片怎么办?请移步《移动端如何使用 WebP(上)》。

One thought on “移动端如何使用 WebP(下)

  1. Pingback: 移动端如何使用 WebP(上) |

发表评论

电子邮件地址不会被公开。 必填项已用*标注