在开发网站、整理设计素材或者向不同平台上传图片时,我们经常会遇到这些问题:一张 PNG 截图体积太大,怎么转换成 JPG?网站里的图片想减小体积,应该换成 WebP 吗?下载到的 WebP 无法被旧软件打开,又该如何处理?
这些需求看起来只是修改文件后缀,实际上涉及图片的重新解码与编码。不同格式在压缩方式、透明背景和使用场景上都有明显区别,选错格式不仅可能让文件变大,还可能丢失透明背景或降低画质。
最近我做了一个在线图片格式转换工具,支持 PNG、JPG、WebP 和 AVIF 相互转换、批量处理以及输出质量调节。本文借这个工具的开发过程,聊一聊常见图片格式应该如何选择,以及怎样只使用浏览器 API 完成本地图片转换。
PNG、JPG 和 WebP 有什么区别
虽然三种格式都能保存图片,但它们解决的问题并不相同。
| 格式 | 压缩方式 | 透明背景 | 典型场景 |
|---|---|---|---|
| PNG | 无损压缩 | 支持 | Logo、图标、截图、带透明背景的素材 |
| JPG/JPEG | 有损压缩 | 不支持 | 照片、封面图、色彩变化丰富的图片 |
| WebP | 支持有损和无损压缩 | 支持 | 网站配图、电商图片、需要优化加载速度的页面 |
PNG:清晰,但体积可能较大
PNG 使用无损压缩,保存后不会因为压缩算法产生新的画质损失,并且支持 Alpha 透明通道。因此,界面截图、Logo、二维码和需要透明背景的图片通常适合使用 PNG。
它的不足也很明显:面对照片这类颜色复杂的图片时,文件体积往往比 JPG 和 WebP 大得多。如果透明背景并不是必须的,将大尺寸 PNG 转成 JPG 或 WebP,通常可以明显减小文件大小。
JPG:兼容性好,适合照片
JPG 通过有损压缩减少文件体积,非常适合照片、文章封面和社交平台配图。输出质量越低,文件通常越小,但压缩痕迹也会更明显。
需要注意的是,JPG 不支持透明背景。把透明 PNG 转成 JPG 时,必须先为透明区域指定一种颜色,否则不同实现可能出现黑色背景。本文实现的转换工具会主动将透明区域填充为白色。
WebP:更适合现代网站
WebP 同时支持有损压缩、无损压缩和透明通道。在许多网页场景中,它能在保持可接受画质的同时得到更小的文件体积,因此很适合用来优化页面加载速度。
不过,一些旧软件、内容管理系统或上传平台仍然不能很好地处理 WebP。遇到兼容问题时,可以将 WebP 转成 PNG 或 JPG,再交给目标软件使用。
图片格式转换不是修改后缀
把 photo.png 直接重命名为 photo.jpg 并不会完成格式转换。文件内部仍然保存着 PNG 编码的数据,只是文件名发生了变化,部分软件甚至会因此无法识别它。
真正的转换过程可以概括为:
读取源文件 → 解码为像素数据 → 绘制到 Canvas → 按目标格式重新编码 → 生成下载文件
浏览器已经具备图片解码、像素绘制和常见格式编码能力,因此普通的 PNG、JPG 和 WebP 转换不一定需要上传到服务器,也不必额外安装桌面软件。
使用浏览器实现图片格式转换
1. 读取用户选择的图片
首先通过文件选择框获取 File 对象,再使用 URL.createObjectURL() 创建一个只在当前页面有效的临时地址。
<input
id="fileInput"
type="file"
accept="image/png,image/jpeg,image/webp"
multiple
>
function loadImage(file) {
return new Promise((resolve, reject) => {
const objectUrl = URL.createObjectURL(file);
const image = new Image();
image.onload = () => resolve({
image, objectUrl });
image.onerror = () => {
URL.revokeObjectURL(objectUrl);
reject(new Error('浏览器无法读取这张图片'));
};
image.src = objectUrl;
});
}
这里没有网络请求。图片数据来自用户设备,临时 URL 也只指向浏览器内存中的对象。
2. 将图片绘制到 Canvas
图片加载完成后,创建一个与原图宽高一致的 Canvas,并把图片绘制进去。
function drawToCanvas(image, targetType) {
const canvas = document.createElement('canvas');
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
const context = canvas.getContext('2d', {
alpha: targetType !== 'image/jpeg'
});
if (targetType === 'image/jpeg') {
context.fillStyle = '#ffffff';
context.fillRect(0, 0, canvas.width, canvas.height);
}
context.drawImage(image, 0, 0);
return canvas;
}
Canvas 的尺寸直接使用原图尺寸,因此格式转换不会主动缩放图片。目标格式为 JPG 时,先绘制白色背景,再绘制原图,就能避免透明像素变黑。
需要特别说明的是:JPG 转 PNG 只会改变文件的编码格式,不会凭空恢复透明背景。原图中已经被保存为白色的区域,转换后仍然是白色。
3. 按目标格式编码为 Blob
Canvas 的 toBlob() 方法可以将画布内容编码为 PNG、JPG 或 WebP。对于有损格式,还可以传入 0 到 1 之间的质量参数。
function canvasToBlob(canvas, type, quality = 0.85) {
return new Promise((resolve, reject) => {
canvas.toBlob((blob) => {
if (!blob) {
reject(new Error('图片编码失败'));
return;
}
resolve(blob);
}, type, quality);
});
}
PNG 是无损格式,质量参数通常不会起作用;JPG 和 WebP 则可以通过质量参数在画质与体积之间做取舍。对网页图片来说,可以先从 0.8 到 0.9 的范围尝试,再根据实际画面和文件大小调整。
4. 生成可下载文件
编码完成后,再为结果 Blob 创建临时地址,并触发浏览器下载。
function downloadBlob(blob, fileName) {
const resultUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = resultUrl;
link.download = fileName;
link.click();
setTimeout(() => URL.revokeObjectURL(resultUrl), 1000);
}
完整的单张图片转换逻辑可以组合为:
async function convertImage(file, targetType, quality = 0.85) {
const {
image, objectUrl } = await loadImage(file);
try {
const canvas = drawToCanvas(image, targetType);
return await canvasToBlob(canvas, targetType, quality);
} finally {
URL.revokeObjectURL(objectUrl);
}
}
批量转换还需要处理哪些问题
将单张转换扩展成批量工具,除了遍历文件列表,还需要考虑一些实际体验问题。
文件校验
应该同时检查文件类型和文件大小,避免把无法解码的文件放入任务队列。工具目前支持 PNG、JPG、WebP、AVIF,单张图片限制为 50 MB。
防止重复添加
可以使用文件名、文件大小和 lastModified 组合判断用户是否重复选择了同一文件。这虽然不是严格的内容去重,但对本地批量工具已经足够实用。
显示转换结果
转换完成后,不只要显示“成功”,还可以同时展示原始体积、转换后体积以及变化百分比。用户能够立即判断当前格式和质量设置是否真正带来了优化。
及时释放临时地址
URL.createObjectURL() 创建的地址会占用内存。删除任务、重新转换或离开页面前,应通过 URL.revokeObjectURL() 释放不再使用的地址。处理大量高分辨率图片时,这一点尤其重要。
为什么选择在浏览器本地处理
传统的在线转换服务通常需要先把图片上传到服务器,服务端完成转换后再将结果传回。对于几十张图片,这意味着额外的上传时间、下载时间和服务器成本。
浏览器本地转换则有几个直接优势:
- 隐私更清晰:图片不离开用户设备,也不会被服务器存储。
- 等待更少:不受上传带宽影响,选择图片后即可开始处理。
- 服务端零处理压力:静态页面就能提供完整功能。
- 部署简单:HTML、CSS 和 JavaScript 可以直接部署到静态托管或 CDN。
它也并非适合所有场景。超大图片会占用较多内存,浏览器对新格式的编码能力可能存在差异,复杂的压缩参数和专业色彩管理仍然更适合服务端工具或桌面软件。
常见转换场景应该怎么选
PNG 转 JPG
适合不需要透明背景的截图、文章配图和普通上传场景。通常可以减小文件体积,并获得很好的软件兼容性。
JPG 转 PNG
适合目标平台明确要求 PNG 的情况,但转换不会提升原图画质,也不会恢复已经丢失的透明信息,文件体积还可能变大。
PNG 或 JPG 转 WebP
适合网站图片优化。它通常能在可接受的画质下减少传输体积,PNG 转 WebP 时还可以保留透明背景。
WebP 转 PNG 或 JPG
适合解决旧软件打不开 WebP、平台不允许上传 WebP 等兼容问题。需要透明背景时选择 PNG,不需要透明背景且更关心文件大小时选择 JPG。
在线体验
如果只是临时转换图片,不需要为此编写一遍代码,可以直接使用我做的在线图片格式转换工具:
- 支持 PNG、JPG、WebP、AVIF 相互转换
- 支持一次添加多张图片
- 支持调节 JPG、WebP、AVIF 输出质量
- 保持图片原始像素尺寸
- 显示转换前后的文件体积
- 全程在浏览器本地处理,不上传图片
- 无需注册,也不需要安装软件
使用方法很简单:拖入图片,选择目标格式和输出质量,点击“全部转换”,完成后即可逐张下载结果。
总结
PNG、JPG 和 WebP 没有绝对的好坏,关键是根据图片内容和使用场景选择:需要无损和透明背景时使用 PNG,照片和高兼容场景使用 JPG,网站性能优化则优先考虑 WebP。
浏览器端图片转换的核心并不复杂:使用 File 和 Object URL 读取图片,通过 Canvas 获得像素内容,再用 toBlob() 按目标格式重新编码。结合文件校验、批量队列、质量调节和内存释放,就可以完成一个真正实用的本地图片转换工具。
如果这篇文章解决了你的图片格式问题,欢迎收藏并把图片格式转换工具分享给有需要的朋友。
相关工具: