前几天有个需求是需要把一些 JPG 图片转换成 WebP 然后放到客户端里播放动图,主要是想享受 WebP 格式带来的压缩率,生成更小的图片文件,节省带宽和下载时间。
webpmux 是什么?
webpmux 是 Google 为其 WebP 出得附属配套工具,专门用来操作 WebP 动图,可以从 WebP 动图里抽出每一帧,也可以从一批图像帧合成成一张 WebP 动图,同时也支持设定循环次数、背景颜色,每一帧的播放时长、暂停时间等等。
为什么解不开?
由于 webpmux 的 file_i +di[+xi+yi[+mi[bi]]]
参数 BLEND
项默认为 +b (BLEND)
所以导致我们生成的 WebP 动图用 SDWebImage 解析不出来。
因为 SDWebImage/UIImage+WebP.m 中判断如果当前帧 为 WEBP_MUX_BLEND
则用 sd_blendWebpImageWithOriginImage
解,否则用 sd_rawWepImageWithData
方法
...
do {
UIImage *image;
if (iter.blend_method == WEBP_MUX_BLEND) {
image = [self sd_blendWebpImageWithOriginImage:[images lastObject] iterator:iter];
} else {
image = [self sd_rawWepImageWithData:iter.fragment];
}
if (!image) {
continue;
}
[images addObject:image];
duration += iter.duration / 1000.0f;
} while (WebPDemuxNextFrame(&iter));
...
而 sd_blendWebpImageWithOriginImage
又需要取到上一帧做 blend 叠加,由于第一帧被指定成了 BLEND
,所以导致后面所有帧都解不出来。
+ (nullable UIImage *)sd_blendWebpImageWithOriginImage:(nullable UIImage *)originImage iterator:(WebPIterator)iter {
if (!originImage) {
return nil;
}
...
}
解决办法
解决办法就是显示指定 webpmux 的 BLEND
参数为 -b (NO_BLEND)
,让第一帧不使用混合模式,SDWebImage 就能正确解析了。
webpmux -frame 0.webp +100+0+0+0-b \
-frame 1.webp +100+0+0+0-b \
-frame 2.webp +100+0+0+0-b \
-frame 3.webp +100+0+0+0-b \
-o anim.webp
另外 YYWebImage
的 WebP 解码方式好像是有些不太一样,没有细看,所以用 YY 应该是没问题的。