ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

浏览器导出JPEG,质量参数其实只有101档

浏览器导出JPEG,质量参数其实只有101档 前端做「上传前把图压到指定大小」时常见的写法是对导出质量做二分也就是 canvas 的quality参数。这轮我在测二分法要找到多精确时顺手把 JPEG 的质量从 0.950 到 0.970 一格一格试了一遍。0.955、0.959、0.960、0.961、0.964 这五个值编出来的文件都是 362 299 字节。一个字节都不差二分要是把精度收到 0.001后面几次编码其实是在反复生成同一个文件。这组数据的样本是一张文字加界面的 1440×2400 截图。截图样本我用的是图映 ImgIng一个在线的免费图片处理工具PNG 压缩说明页的整页截图。机器是一台 Apple M4 / 16 GB 的 Mac。浏览器用的是 Chromium 149 开源构建JPEG 走它内置的 libjpeg-turboWebP 走内置的 libwebp。0.950 和 0.951 出来都是 336 289 字节。0.955 到 0.964 这五个值都是 362 299 字节。0.965、0.969、0.970 三个又是同一个文件393 304 字节。从实测看浏览器像是把 0 到 1 的小数乘 100、四舍五入成整数再交给 libjpeg。0.951 还算 95 档0.955 已经算成 96 档。这是我从字节数反推出来的Chromium 里具体是哪一行做的取整我没去翻。这个行为我不意外我以前在音视频 SDK 公司做了三年编解码。libjpeg 的质量接口本身就收整数。它拿这个整数去缩放量化表小数根本进不去。浏览器给 JS 的却是 0 到 1 的浮点参数中间总得有人把它变成整数。这么算下来 JPEG 的质量最多只有 0 到 100 共 101 个取值。两端的 0 和 1 会不会被夹成同一档我没测。0.955 这种正好压在 .5 上的数在浮点里往哪边走我也没拆。这张图是复现页跑完的字节表要看的是 JPEG 那一列。同一个字节数连着出现好几行每一段正好对应一个整数档。WebP 那一列在 0.960 和 0.961 之间就变了两列放在一起对比最直观。截图是单次运行的结果。换成 WebP 就不一样。同一张截图在 0.960 是 193 098 字节0.961 是 195 376 字节。0.964 又变成 197 578 字节。它的质量参数能吃进小数。不过它也有几段是平的0.955 到 0.960 三个值输出一样大0.969 和 0.970 也一样。真正要小心的是顶端。WebP 在 0.999 时是 222 292 字节到 1.0 一下跳到 771 126 字节前者的 3.5 倍。我把 1.0 编出来的文件解码回来和源图逐个对过13 824 000 个通道值差异为 0。说明那一档已经切成无损了。JPEG 的顶端也有台阶0.99 是 512 151 字节0.995 却已经被算成 100 档和 1.0 一样是 791 712 字节。搞清楚取整之后二分的写法就好定了。我拿一张系统自带的风景照3840×2160压 JPEG 到 2MB 做对比。质量取小数的浮点二分一直找到区间小于 0.01 才停一共编了 8 次、用了 259 ms最后停在质量 0.962。质量只取整数的二分编了 6 次、用了 189 ms停在质量 96。两个结果是同一个文件都只用掉了额度的 96.7%。多出来的两次编码只是在同一个整数档里来回。WebP 的浮点二分偶尔能多挤出一点。拿程序生成的 24MP 仿照片图压 WebP 到 2MB浮点二分找到的文件能用掉额度的 99.7%整数二分是 95.8%。代价是这张图用 WebP 编一次的中位数接近 1 秒。多编两次用户就多等两秒左右。为了这点额度多等不值得。我跑下来觉得整数二分对 WebP 也够用。上限反而要单独处理。限制很松时整数二分会一路走到 100。那张截图压成 2MB 以内的 WebP 时整数二分就停在了 1.0拿到一个 753 KB 的无损文件浮点二分停在 0.995只有 217 KB。上限我会封在 0.99。另一个办法是先比一下原图已经小于目标就不重编。图映的压缩界面给的是 30 到 100 的整数质量滑杆按内容推荐的质量值也都是整数。这块编码归我管。整数刻度跟编码器实际能分辨的档位是对得上的。想在自己的浏览器里验证取整可以打开浏览器控制台找一张图画到 canvas 上再调 toBlob 导出。在 0.95 附近按 0.001 的间隔编十来次并把每次的 blob.size 打出来。打出来的 JPEG 字节数会一段一段地重复。如果你的二分还在取两个小数的中点就先改成整数再二分编过的整数档直接复用结果。上限封在 0.99WebP 那一档无损大文件就不会冒出来。以上只在 Chromium 149 上验证过。别的浏览器怎么取整我手上没有数据。
返回列表