JPG 图片压缩
质量调节 · 分级预设 · 批量处理 · 浏览器本地
mozjpeg/guetzli 智能优化
质量调节 · 分级预设 · 批量处理 · 浏览器本地
95-100:肉眼无法区分,体积大。专业摄影 / 印刷。
80-90:⭐推荐⭐ 平衡体积与质量,网页 / 社交分享。
60-75:缩略图 / 预览图 / 移动端图。
40-55:极致压缩,明显有损,适合占位。
浏览器 JPEG 编码:使用 Chrome / Firefox 内置 libjpeg。无法启用 mozjpeg 的 trellis quantization 等高级优化,建议追求极致可用桌面 cjpeg -q 80。
了解工具定位 · 使用场景 · 对比优势
上传 JPG 图片,自动应用 mozjpeg 与 Guetzli 算法进行智能压缩,在保持视觉质量的前提下大幅减小文件体积。网站运营者优化页面加载速度、设计师交付轻量素材、摄影师批量处理图片,均适用。处理完全在浏览器内完成,图片不上传至任何服务器。
App 运营人员每天需上传数十张商品图到小程序,原图每张 2-3 MB,加载慢且消耗用户流量。使用本工具批量压缩,在肉眼几乎无感知的前提下将图片体积压缩 60-80%,小程序首屏加载速度从 5 秒降到 1.5 秒,用户跳出率下降明显。
个人站长或企业前端团队,网站首页 Banner 和产品图加起来超过 10 MB,严重影响 Core Web Vitals 中的 LCP 指标。通过本工具对 JPG 进行有损压缩,在保持 90% 以上视觉质量的同时,将图片体积降至原来的 1/3,LCP 从 4.2 秒优化至 1.8 秒,通过 Google PageSpeed 绿色评分。
市场人员需要将多张高清活动照片(单张 5-8 MB)作为邮件附件发送给客户,但企业邮箱附件上限通常为 20 MB。使用本工具压缩后,单张图片降至 1-2 MB,一封邮件可附带 10 张图而不超限,且客户在手机端查看时无需等待加载。
电商运营每天需处理上千张商品主图与详情页图片,原图过大导致上传慢、占用服务器存储。使用本工具批量压缩,单张图片从 3 MB 压缩至 500 KB 左右,存储成本降低 80%,且详情页图片加载速度提升 3 倍,减少用户等待造成的流失。
| 维度 | 本工具 | Squoosh (Google) | 传统方法 (Photoshop) |
|---|---|---|---|
| 处理引擎 | mozjpeg + Guetzli 双算法可选 | MozJPEG 为主,部分实验性编码 | Photoshop 内置 JPEG 压缩算法 |
| 压缩质量 | Guetzli 模式可多轮迭代寻找最优参数 | 单次压缩,质量参数固定 | 依赖手动调整滑块,无自动优化 |
| 处理速度 | Guetzli 模式需 3-10 秒(迭代计算) | 1-3 秒(单次压缩) | 1-5 秒(取决于操作熟练度) |
| 批量处理 | 单张处理 | 单张处理 | 支持动作/脚本批量处理 |
| 数据隐私 | 纯浏览器端处理,不上传 | 纯浏览器端处理,不上传 | 本地软件处理,无上传 |
| 离线可用 | 需首次加载 WASM,后续可离线 | 需首次加载 WASM,后续可离线 | 完全离线 |
| 输出控制 | 可指定输出文件大小目标 | 仅调整质量滑块(0-100) | 可指定文件大小目标,但需手动试错 |
| 文件大小限制 | 浏览器内存限制(通常 50MB 以内) | 浏览器内存限制(通常 50MB 以内) | 取决于本地内存,无实际限制 |
上手步骤 · 输入输出 · 避坑提示
| 输入 | 输出 | 说明 |
|---|---|---|
| photo.jpg | photo-compressed.jpg (65KB, 质量85%, 压缩率60%) | 典型场景:普通照片压缩,平衡质量与体积 |
| screenshot.png | screenshot-compressed.jpg (120KB, 质量90%, 压缩率30%) | 典型场景:截图压缩,保留文字清晰度 |
| logo.png | logo-compressed.jpg (8KB, 质量95%, 压缩率80%) | 边界 case:小尺寸图标,高压缩比下仍清晰 |
| large-banner.jpg (10MB) | large-banner-compressed.jpg (1.2MB, 质量80%, 压缩率88%) | 边界 case:大文件压缩,显著减小体积 |
| grayscale-photo.jpg | grayscale-photo-compressed.jpg (40KB, 质量85%, 压缩率55%) | 边界 case:灰度图压缩,算法保留细节 |
| low-quality.jpg (已压缩过,质量30%) | low-quality-compressed.jpg (28KB, 质量30%, 压缩率10%) | 易错 case:二次压缩效果有限,质量不提升 |
| transparent.png | transparent-compressed.jpg (背景变白,15KB, 压缩率90%) | 易错 case:JPG不支持透明,背景自动填充白色 |
上传一张带透明背景的 PNG 图标到 JPG 压缩器先用 PNG 压缩工具(如 pngquant)压缩,或接受 JPG 输出后透明区域变为白色/黑色JPG 格式不支持 Alpha 通道,透明区域会被填充为背景色(通常白色),导致视觉差异
把一张质量 10% 的 JPG 再次上传压缩只对原始高质量 JPG(质量 80-100%)或未压缩的 PNG/BMP 源文件使用本工具mozjpeg/guetzli 对已严重压缩的图像二次压缩只会增加块状伪影,不会显著减小体积
上传一张 500KB 的 JPG,期望输出也是 500KB 且视觉完全一致接受 10-50% 的文件大小缩减,同时视觉质量几乎不可察觉mozjpeg 和 guetzli 都是有损压缩算法,通过丢弃人眼不敏感的高频信息来减小体积
上传一张 10000×10000 像素的航拍图(约 50MB)先使用图像缩放工具将分辨率降至 4000px 以内,再上传压缩浏览器端处理大图会耗尽内存,WASM 解码/编码过程可能触发 Tab 崩溃或 OOM
将压缩后(质量 60%)的 JPG 直接发送给印刷厂印刷用途保留原始高质量 JPG(质量 90%+)或使用 TIFF/PSD 格式印刷需要高分辨率和高色彩深度,压缩后的 JPG 在放大后会出现明显色块和锯齿
上传包含 GPS 位置、相机型号等 EXIF 信息的照片,压缩后找不到这些信息压缩前手动备份 EXIF 数据(如使用 exiftool),或接受压缩后 EXIF 被清除guetzli 和部分 mozjpeg 配置会丢弃 EXIF/IPTC 元数据以进一步减小文件体积
将压缩后的 200KB JPG 再次压缩,期望得到 100KB只对原始文件压缩一次,或接受第二次压缩仅减少 5-10%有损压缩的边际收益递减:第一次压缩移除大量冗余信息,后续压缩只能移除极少量数据
公式推导 · 流程图解 · 依据出处
SSIM(x, y) = [ (2μ_x μ_y + C1)(2σ_{xy} + C2) ] / [ (μ_x^2 + μ_y^2 + C1)(σ_x^2 + σ_y^2 + C2) ]
x — 原始图像像素块y — 压缩后图像对应像素块μ_x — 原始块像素均值μ_y — 压缩块像素均值σ_x^2 — 原始块像素方差σ_y^2 — 压缩块像素方差σ_{xy} — 原始与压缩块协方差C1, C2 — 稳定常数,防除零原始 8×8 块像素均值 μ_x=128,压缩后 μ_y=126,方差 σ_x^2=400,σ_y^2=380,协方差 σ_{xy}=390,C1=(0.01×255)^2=6.5025,C2=(0.03×255)^2=58.5225。代入得 SSIM = (2×128×126+6.5025)(2×390+58.5225) / ((128^2+126^2+6.5025)(400+380+58.5225)) ≈ 0.994。SSIM 越接近 1 表示压缩后视觉失真越小。
适用于 mozjpeg/guetzli 压缩质量评估,基于 Wang et al. 2004 论文(Image Quality Assessment: From Error Visibility to Structural Similarity)。不适用于纯色块(方差极低时 SSIM 会偏高),建议结合 PSNR 或 VMAF 综合判断。
3 种主流语言 · 复制即用
import subprocess
import sys
# 调用 mozjpeg 的 cjpeg 压缩 JPEG(需安装 mozjpeg)
input_path = "input.jpg"
output_path = "output.jpg"
quality = 80 # 0-100,越低压缩率越高
try:
# cjpeg 从 stdin 读原始图像,输出压缩 JPEG 到 stdout
with open(input_path, "rb") as f_in:
result = subprocess.run(
["cjpeg", "-quality", str(quality), "-outfile", output_path],
stdin=f_in,
capture_output=True,
check=True
)
print(f"压缩完成: {output_path}")
except FileNotFoundError:
print("错误: 未安装 mozjpeg,请先安装 (brew install mozjpeg)", file=sys.stderr)
except subprocess.CalledProcessError as e:
print(f"压缩失败: {e.stderr.decode()}", file=sys.stderr)package main
import (
"fmt"
"image/jpeg"
"os"
)
func main() {
// 使用 Go 标准库 JPEG 编码器模拟 mozjpeg 压缩(仅演示 API 调用方式)
inputPath := "input.jpg"
outputPath := "output.jpg"
quality := 80 // 1-100
fileIn, err := os.Open(inputPath)
if err != nil {
fmt.Fprintf(os.Stderr, "打开输入文件失败: %v\n", err)
return
}
defer fileIn.Close()
img, err := jpeg.Decode(fileIn)
if err != nil {
fmt.Fprintf(os.Stderr, "解码 JPEG 失败: %v\n", err)
return
}
fileOut, err := os.Create(outputPath)
if err != nil {
fmt.Fprintf(os.Stderr, "创建输出文件失败: %v\n", err)
return
}
defer fileOut.Close()
// 设置压缩质量参数
opt := &jpeg.Options{Quality: quality}
if err := jpeg.Encode(fileOut, img, opt); err != nil {
fmt.Fprintf(os.Stderr, "编码 JPEG 失败: %v\n", err)
return
}
fmt.Println("压缩完成:", outputPath)
}// 浏览器端使用 Canvas API 压缩 JPEG(类似 guetzli 的感知优化思路)
function compressJPEG(file, quality = 0.8) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// 以指定质量重新编码为 JPEG
canvas.toBlob(
(blob) => {
if (blob) resolve(blob);
else reject(new Error('编码失败'));
},
'image/jpeg',
quality
);
};
img.onerror = () => reject(new Error('图片加载失败'));
img.src = e.target.result;
};
reader.onerror = () => reject(new Error('文件读取失败'));
reader.readAsDataURL(file);
});
}
// 使用示例(在浏览器控制台运行)
// const fileInput = document.querySelector('input[type="file"]');
// fileInput.addEventListener('change', async (e) => {
// const compressed = await compressJPEG(e.target.files[0], 0.7);
// const url = URL.createObjectURL(compressed);
// console.log('压缩后图片 URL:', url);
// });8 个高频疑问
「压缩 / 优化」下的其他工具