资源优化之使用 WebP 格式

包体瘦身里最立竿见影的一招,就是换图片格式。我入行那会儿还在用 PNG,后来碰到一个项目,启动图占了好几兆,怎么压都压不下去。直到我把那批图全转成 WebP,包体直接少了 3MB——当时我都惊了。今天咱就聊聊 WebP 到底怎么用,踩过哪些坑。

WebP 资源优化决策图 WebP 资源优化决策树 原始图片资源 判断原格式:PNG / JPEG 是否需要透明通道? 有透明通道 WebP 有损 + 透明 无透明通道 WebP 有损压缩 集成到 Android 项目 记得配置 minSdkVersion ≥ 18

WebP 到底能省多少?

我直接给数据吧,这是我自己项目里实测的对比:

图片类型 原格式大小 WebP 大小 压缩比
PNG 32位(带透明) 256 KB 68 KB 73%
JPEG 高质量 1.2 MB 420 KB 65%
启动图 (1920×1080) 3.1 MB 890 KB 71%

你想想看,一张图省 70% 空间,几十张图下来,包体直接瘦一圈。而且 WebP 还支持有损、无损、透明和动图,基本覆盖了大部分 UI 场景。

Android 里怎么用?

早期 Android 对 WebP 支持有限,不过从 Android 4.0(API 14)开始就原生支持基础解码了。但注意,带透明通道的 WebP 需要 Android 4.2.1+(API 18)。我建议你的 minSdkVersion 如果 >= 18,放心大胆用。

第一步:把图片转成 WebP

我个人习惯用 Android Studio 自带的工具——右键图片,选择 Convert to WebP。弹窗里可以选有损/无损,也能直接预览效果。

操作步骤:
1. 在 Project 视图里选中图片(或整个 drawable 文件夹)。
2. 右键 → Convert to WebP。
3. 选择编码方式:
   - Lossy(推荐 UI 大图):质量选 75-90,肉眼几乎看不出区别。
   - Lossless(图标、小图):无损保留细节。
   - 如果图片有透明区域,勾选 "Enable transparency"。
4. 点击 Finish,Studio 会自动替换源文件(或生成新副本)。

我记得有一次我把启动图转成 WebP 有损 85% 质量,包体从 3.1MB 降到 890KB,视觉上完全没问题。不过要注意,极少数旧手机(Android 4.0 以下)不支持解码,那部分用户基本可以忽略,如果你的 app 必须兼容,可以用 Glide 等图片库做 fallback。

关键指标:转 WebP 后包体平均缩减 60%-75%,而且解码速度通常不比 JPEG 慢。我自己测过,同一张 1920×1080 图,WebP 解码耗时约 15ms,JPEG 约 18ms,差不了多少。

代码层面怎么集成?

如果你用 ImageView 加载本地资源,直接把 .webp 文件丢到 res/drawable 或 res/mipmap,系统会自动解码。啥额外代码都不用写。

<!-- 普通使用,跟 PNG 完全一样 -->
<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/my_icon" />   <!-- my_icon.webp 也可以 -->

如果用 Glide 加载网络图片,默认就支持 WebP。不过这里有个坑——我记得早期 Glide 版本(< 4.0)需要额外配置,现在 4.x 以上直接能用:

// Glide 4.x 加载 WebP,无需额外设置
Glide.with(this)
    .load("https://example.com/image.webp")
    .into(imageView);

我曾经踩过的坑:把带透明通道的 PNG 转成 WebP 有损后,发现某些华为旧机型上透明区域出现了锯齿。后来我改用 WebP 无损模式(Lossless),问题就解决了。所以如果你的图片对边缘质量敏感(比如圆形头像、切图),建议用 Lossless。

什么时候不适合用 WebP?

说实话,大部分场景都适合。但有一类情况我不建议——需要频繁编辑的源文件。比如设计师还在反复改稿的设计稿,你转成 WebP 后再改回 PNG 会损失质量。我通常等 UI 定稿后再统一转。另外,动态 GIF 图如果帧数很多,转 WebP 动图后文件可能反而变大——不过这种情况很少见。

批量转换技巧

如果图片太多,一个一个转太慢了。可以用命令行工具 cwebp,它是 Google 官方提供的编码器。我在 CI 脚本里加过这样一行:

# 批量将当前文件夹下所有 png 转成 webp(有损质量 80%)
for f in *.png; do
    cwebp -q 80 "$f" -o "${f%.png}.webp"
done

一个小技巧:质量参数 -q 80 是性能和体积的平衡点。低于 70 肉眼可能能看出瑕疵,高于 90 体积缩减就不明显了。我项目中大部分图用 80,只有启动图这种大图用 85。

好了,WebP 这块就这么简单。别犹豫,下次看到 drawable 里的 PNG,直接右键转掉吧。