☰
图片格式转换别再上传了:30 张 PNG 转 WebP,体积耗时全实测
2026/10/17 2:52:31 网站建设 项目流程

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

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

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

在线案例与源码: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 三种。

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

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

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

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

输出设置只有三个开关:格式(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,点一下「开始转换」。

跑完汇总统计给出四个数: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 质量 806.84 MB-63.8%8.27 秒276 毫秒
WebP 质量 504.27 MB-77.4%8.11 秒270 毫秒
WebP 质量 10021.71 MB+14.8%4.70 秒157 毫秒
WebP 质量 80 + 最长边 12803.59 MB-81.0%4.43 秒148 毫秒
JPEG 质量 8011.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 次图片上传 / 数据外发请求」。

这个清单是页面自己记的,我不太想直接信,就从外面又对了一遍: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 字节的空文件。

输入页面给出的原因
预算表.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 质量 806.84 MB / 8.27 秒减小 63.8%,平均每张 276 毫秒
WebP 质量 504.27 MB减小 77.4%
WebP 质量 10021.71 MB比原图大 14.8%
最长边限制 12803.59 MB减小 81.0%
单张输出复核171422 字节 / WEBPPIL 读出 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,那是帮倒忙。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询