图片格式转换别再上传了:30 张 PNG 转 WebP,体积耗时全实测

举报
deli007 发表于 2026/10/16 01:34:05 2026/10/16
【摘要】 图片格式转换别再上传了:30 张 PNG 转 WebP,体积耗时全实测

30 张 PNG,18.91 MB,拖进去点一下,8.27 秒转完,输出 6.84 MB,体积少了 63.8%。

整个过程页面自己记的网络请求是 0 条,图片没有离开这台机器。

我把其中一张的输出从页面内存里捞出来,用 PIL 复核:文件头 RIFF/WEBP,1920×1080,171422 字节,源图 471842 字节。

图 1:转换完成后的处理队列,每行左边是原图、右边是输出,下面并排给出原体积、输出体积和减小百分比

在线案例与源码:https://atomgit.com/deli007/demo_park/tree/main/codearts-image-format-converter
成品只有一个 index.html,转换在浏览器内存里用 canvas 完成,页面不负责上传。

一、为什么值得自己做:在线转换的第一步就是「上传」

搜图片格式转换,前几页的工具流程几乎一样:选文件、等进度条、下载。

进度条那几秒里,你的截图、证件照、客户给的素材,已经在别人的服务器上落过盘了。

我不介意图片被压缩,介意的是压缩之前先传一遍。

我要的只有一件事:文件在本机算完,页面不负责传。

二、准备环境:进入码道 Web,把需求写成一段话

浏览器打开 https://devcloud.cn-north-4.huaweicloud.com/chat/home ,登录后把需求写进对话框,就能拿到一个能跑的单文件应用。

不用装东西,不用配环境,本文这个工具就是这么来的。

码道有三种使用方式:WebUI(浏览器对话)、TUI(终端命令行)和桌面 IDE(IDE 插件)。本文用 WebUI 版演示。

需求我写了 10 条,事后看最值钱的是这四条:

  • 页面上要有网络请求计数,从打开页面到转换结束,这个数必须一直是 0;
  • 每张图要单独给出原体积、输出体积和减小百分比,不许只给一个总数;
  • 遇到不支持的类型、损坏文件、空文件,要在那一行写清中文原因,不许只打控制台日志;
  • 支持的输入格式写明 PNG / JPG / WebP / GIF / BMP,输出只留 WebP / PNG / JPEG 三种。

第二条是这次排版最省事的决定:逐张的数字摆在那里,写文章时不用去数。

三、一屏看清:能选什么,能看什么

页面分四块:选图片、输出设置、处理队列、汇总统计,最底下还挂着一块网络请求清单。

图 2:工具首屏,从上到下是拖拽选择区、输出格式与质量滑杆、尺寸限制、操作按钮,以及置灰的三个按钮

拖拽区标了五种支持的输入格式,点一下就能选文件,多选不限张数。

输出设置只有三个开关:格式(WebP / PNG / JPEG)、质量滑杆(1 到 100)、尺寸限制(勾选后最长边超过设定值就等比缩小)。

尺寸限制只缩小、不放大,所以小图勾不勾都一样。

选完文件按钮才会亮,队列空的时候「开始转换」是灰的。

四、实测:30 张 PNG 转 WebP,8.27 秒,少 63.8%

输入是我用 PIL 生成的 30 张噪点图,尺寸掺着来:1920×1080、1600×1200、1200×1600、800×600、3840×2160,合计 18.91 MB。

默认设置是 WebP、质量 80,点一下「开始转换」。

图 3:转换进行中,按钮变成「转换中…」,右侧进度条走到 5 / 30,队列里已完成的三行给出逐张对比数字

跑完汇总统计给出四个数:18.91 MB → 6.84 MB,减小 63.8%,总耗时 8.27 秒,平均每张 276 毫秒。

同一批文件我重复跑了三遍,耗时是 8.30、8.28、8.27 秒,稳定在 8.3 秒上下。

逐张看也有规律:1920×1080 那张从 460.8 KB 掉到 167.4 KB,3840×2160 那张从 1.75 MB 掉到 649.1 KB,减小幅度都在 63% 到 64% 之间。

噪点多的图最吃 WebP 的亏,也最能吃到它的便宜。

五、换个设置,数字差多少

同一批 30 张图,我换了六个设置各跑一遍。

输出设置 输出体积 体积变化 总耗时 平均每张
WebP 质量 80 6.84 MB -63.8% 8.27 秒 276 毫秒
WebP 质量 50 4.27 MB -77.4% 8.11 秒 270 毫秒
WebP 质量 100 21.71 MB +14.8% 4.70 秒 157 毫秒
WebP 质量 80 + 最长边 1280 3.59 MB -81.0% 4.43 秒 148 毫秒
JPEG 质量 80 11.44 MB -39.5% 2.95 秒 98 毫秒
PNG(无损) 21.37 MB +13.0% 2.92 秒 97 毫秒

质量 100 的 WebP 比原图还大 14.8%,这一格值得单独说:canvas 的 WebP 编码器在质量拉满时不走有损模式,体积就放飞了。

PNG 输出同样比输入大 13%,因为我的输入图是 PIL 按默认压缩率写出来的,canvas 重编码一遍反而不如原文件紧凑。

所以「输出 PNG」这件事只适合本来就是 PNG 的图,别指望它顺手帮你瘦身。

真正把体积压下去的是两条路:质量降到 50 到 80,或者勾上尺寸限制。

第五行那组最能说明问题:最长边压到 1280,18.91 MB 直接变成 3.59 MB,少了 81%。

代价是分辨率,用之前想清楚这张图要拿去干嘛。

六、不上传这件事,我是怎么验的

页面底部那块清单,从打开页面开始记,凡是页面发出的请求都会逐条列出来,带地址和耗时。

30 张转完,清单是空的:请求 0、上传 0,绿条写着「检测到 0 次图片上传 / 数据外发请求」。

图 4:汇总统计给出总体积、总耗时、平均耗时五个数字,下方展开的网络请求清单是空的,「上传」计数为 0

这个清单是页面自己记的,我不太想直接信,就从外面又对了一遍:performance.getEntriesByType(‘resource’) 在六个设置下都返回 0 条。

页面里也确实没有外部脚本和 CDN,整个 index.html 45066 字节,双击就能打开。

输出的东西我也验了一遍,不是只看页面报的数字。

单张那一路:从页面内存里把输出 blob 取出来,落盘后让 PIL 打开,读出来是 WEBP、1920×1080,文件头 RIFF + WEBP,171422 字节,和页面报的数一致。

打包那一路:把三张图的输出交给页面自带的 ZIP 写入器,拿到 879080 字节,用 Python 的 zipfile 读,三个条目是 photo-00.webp、photo-13.webp、photo-14.webp,逐条用 PIL 打开也都能解码。

顺带看到一个细节:ZIP 条目的压缩方式全是 0(存储),也就是打包不二次压缩,因为图片本身已经压过一遍,再压只会拖时间。

七、四种坏文件,页面各说各的

失败路径我专门造了四个文件:正常图片改名的文本、一个 SVG、一个 4096 字节的随机数据、一个 0 字节的空文件。

图 5:四个坏文件同时拖进去,每一行标红并给出各自的中文原因,「打包下载全部」保持置灰

输入 页面给出的原因
预算表.txt 不支持的文件类型「.txt」:仅支持 PNG / JPG / WebP / GIF / BMP,请移除该文件后重试
vector.svg 不支持的文件类型「.svg」:仅支持 PNG / JPG / WebP / GIF / BMP,请移除该文件后重试
broken.png(4096 字节随机数据) 图片数据损坏或编码异常,浏览器无法解码(可能是下载中断、转码失败或伪装的扩展名)
empty.png(0 字节) 文件大小为 0 字节,属于空文件,无法解码

类型不对的文件在进入队列时就被挡下,不用等点转换。

损坏和空文件是解码阶段才发现的,原因分别落在「解码失败」和「大小为零」两条分支上。

只剩失败项时,「打包下载全部」保持禁用,它不会假装还有东西可下。

八、实测数据汇总

项目 实测值 说明
单个 HTML 文件体积 45066 字节 约 44 KB,无构建步骤,无外部依赖
输入规模 30 张 / 18.91 MB 五种尺寸混排的噪点图
WebP 质量 80 6.84 MB / 8.27 秒 减小 63.8%,平均每张 276 毫秒
WebP 质量 50 4.27 MB 减小 77.4%
WebP 质量 100 21.71 MB 比原图大 14.8%
最长边限制 1280 3.59 MB 减小 81.0%
单张输出复核 171422 字节 / WEBP PIL 读出 1920×1080,源图 471842 字节
打包复核 879080 字节 / 3 个条目 zipfile 校验通过,压缩方式为存储
页面资源请求 0 条 六个设置下都是 0
携带文件内容的请求 0 次 页面自记计数与资源列表都能对上

测试环境是 Chrome 155 内核的一台 Windows 机器,别的浏览器用的是各自的 canvas 编码器,输出体积会有出入。

九、本地复现

生成物只有一个 index.html,双击打开就能用,不需要联网。

也可以起个静态服务看:python -m http.server 8000,然后访问 http://localhost:8000 。

想自己造测试图,用 PIL 几行就能生成一批噪点图,我这轮的输入就是这么来的。

想看它有没有偷偷上传,按 F12 打开网络面板,再点一次转换,里面不会多出任何请求。

下载回来的成品想复核格式和尺寸,也交给 PIL:Image.open 读一遍 format 和 size,跟页面报的数对一下。

十、说点不足

GIF 只取第一帧,动图进去出来就是一张静图。

所有输出都走 canvas,所以原图的 EXIF 信息(拍摄时间、机型、GPS)在转换后全部丢失。

HEIC 和 AVIF 打不开,浏览器能解码的格式它才认。

文件多的时候是串行处理,30 张要 8 秒,300 张就得一分多钟,页面没有做并行。

还有一点得说明白:这是「转换」,不是「压缩工具箱」。它不做批量改名、不做水印、不做裁剪,这些得另找工具。

十一、用码道做这个小工具的体会

这次最值钱的一条需求是「页面上要有网络请求计数,从打开页面到转换结束必须一直是 0」。

这条需求把「不上传」从一句口号变成了一个能看的数字,验收时我只要盯住那块清单。

第二条心得是逐张给数字。汇总统计只有一个总数,写文章时说服力不够;逐张列出原体积和输出体积之后,规律自己就浮出来了。

第三条是失败路径要写在需求里。我写的是「坏文件要给逐条中文原因」,交回来就是四行各不相同的提示,验证时我照着表一条条对。

第四条是尺寸限制这类细节要说清「只缩不放」。需求里不写,实现时很容易顺手把 800×600 的小图放大到 1280,那是帮倒忙。

不足的地方也说一句:这个工具只覆盖格式转换和等比缩小,压缩比、水印、批量改名它一个都接不住。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。