PNG 图片压缩
基于颜色量化算法 · 保留透明通道 · 浏览器本地处理
TinyPNG 风格/pngquant + zopfli
基于颜色量化算法 · 保留透明通道 · 浏览器本地处理
了解工具定位 · 使用场景 · 对比优势
将 PNG 图片压缩至原体积的 60%-80%,视觉质量几乎无损。采用 pngquant 有损压缩 + zopfli 无损再压缩的混合策略,适合前端开发者优化网页图片、设计师导出素材、运营压缩上传图片。纯浏览器处理,图片不上传服务器,无需等待,拖拽即压缩。
电商或内容站的首屏加载速度直接影响跳出率。设计师和前端工程师用本工具批量压缩首屏 Banner、产品主图等大尺寸 PNG,在肉眼几乎不可察觉的色差下将文件体积缩小 60%-80%,配合 pngquant 的量化精度控制,确保 Retina 屏上依然清晰锐利。
iOS/Android 开发者在打包前需要将大量启动图、图标、UI 切图从设计稿导出为 PNG。本工具的单张压缩模式适合快速处理零散素材,zopfli 的二次压缩能在不增加失真前提下再减 5%-10% 体积,直接减少安装包大小,降低用户下载门槛。
独立游戏开发者用 PNG 存储角色精灵、UI 元素和场景贴图,但原生文件过大导致加载黑屏。本工具支持批量拖拽处理,pngquant 的调色板优化将 256 色以下贴图压缩至原体积的 1/3,且保留 Alpha 通道透明背景,适合 Cocos/Unity 等引擎直接导入。
市场或产品团队在做路演 PPT 时,嵌入大量高分辨率截图和流程图 PNG 导致文件超过 100MB,邮件发送失败。本工具可将单张 5MB 的流程图压缩至 800KB 以内,zopfli 的逐像素优化确保文字边缘无锯齿,演示时外接投影仪依然清晰可读。
技术写作者在撰写产品手册或 API 文档时,需要嵌入大量界面截图 PNG。本工具处理 1920×1080 的全屏截图,pngquant 将 24 位色深降至 8 位(保留关键 UI 色彩),体积从 2.3MB 降至 400KB,同时保持按钮文字和图标边缘不模糊,适合嵌入 PDF 或在线文档。
| 维度 | 本工具 | TinyPNG (tinypng.com) | 本地 Photoshop 导出 |
|---|---|---|---|
| 数据隐私 | 纯浏览器处理,图片不上传服务器 | 图片上传至云端服务器处理 | 图片完全保留在本地设备 |
| 处理速度 | 1-3 秒(取决于图片大小) | 5-15 秒(含上传+排队+下载) | 30 秒-数分钟(手动操作) |
| 离线可用 | 完全离线,无需网络 | 必须联网 | 完全离线 |
| 单文件大小限制 | 无限制(由浏览器内存决定) | 5 MB | 无限制 |
| 收费模式 | 完全免费,无水印 | 每月 500 张免费,超出需付费 | 需购买 Photoshop 许可证 |
| 批量处理 | 单张处理 | 支持批量上传 | 需手动操作或录制动作 |
| 压缩算法透明度 | 明确使用 pngquant + zopfli | 未公开具体算法 | 使用 Photoshop 内置压缩算法 |
上手步骤 · 输入输出 · 避坑提示
| 输入 | 输出 | 说明 |
|---|---|---|
| screenshot.png (2.3 MB, 1920x1080, 24-bit PNG) | screenshot.png (压缩后 680 KB, 压缩率 70%) | 典型场景:高分辨率截图(大面积纯色区域,压缩率高) |
| photo.png (5.1 MB, 4000x3000, 24-bit PNG, 含渐变天空和复杂纹理) | photo.png (压缩后 1.8 MB, 压缩率 65%) | 典型场景:照片类 PNG(渐变和纹理区域压缩率略低) |
| logo.png (50 KB, 200x200, 8-bit 索引色 PNG, 仅 4 种颜色) | logo.png (压缩后 12 KB, 压缩率 76%) | 典型场景:小尺寸图标/Logo(索引色 PNG 压缩空间有限) |
| transparent.png (1.2 MB, 1000x1000, 32-bit RGBA PNG, 含半透明渐变) | transparent.png (压缩后 520 KB, 压缩率 57%) | 边界 case:带 Alpha 通道的 PNG(透明度区域影响压缩效率) |
| tiny.png (1 KB, 10x10, 纯色单像素 PNG) | tiny.png (压缩后 0.8 KB, 压缩率 20%) | 边界 case:极小文件(文件头开销占比大,压缩率有限) |
| huge.png (50 MB, 10000x10000, 24-bit PNG, 复杂风景照片) | huge.png (压缩后 18 MB, 压缩率 64%) | 边界 case:超大文件(浏览器内存限制,需注意加载时间) |
| already_compressed.png (300 KB, 已用 OptiPNG 无损压缩过) | already_compressed.png (压缩后 285 KB, 压缩率 5%) | 易错 case:已压缩过的文件(二次压缩收益极低) |
| grayscale.png (800 KB, 2000x2000, 8-bit 灰度 PNG, 含文字和线条) | grayscale.png (压缩后 320 KB, 压缩率 60%) | 易错 case:灰度 PNG(用户常误以为灰度图无法再压缩) |
上传 .jpg / .webp / .gif 文件上传 .png 文件(或先转换为 PNG 再上传)本工具仅处理 PNG 格式;其他格式的压缩算法(如 JPEG 的 DCT、WebP 的 VP8)与 pngquant/zopfli 不兼容,强行处理会报错或输出无效文件
把 TinyPNG 或 pngquant 已压缩过的 PNG 再次上传上传原始 PNG 或仅经过无损压缩(如 OptiPNG)的 PNGpngquant 对有损压缩过的图片二次压缩时,颜色量化会进一步丢失细节,且 zopfli 对已压缩的 IDAT 流收益极低;重复压缩只会增加画质损失
上传 12000×8000 像素、32MB 的 PNG上传前先用图像处理软件缩小到合理尺寸(如 1920×1080)pngquant 处理超大图片时内存占用呈线性增长,浏览器端 WASM 版本可能因内存不足崩溃;zopfli 对超大文件耗时可达数分钟
认为压缩后像素应与原图 100% 一致接受 pngquant 将 24 位真彩色降为 8 位索引色(最多 256 色)带来的轻微色差pngquant 是有损压缩:通过减少颜色数量(颜色量化)来缩小文件体积;zopfli 是后续无损重压缩。若需完全无损,应使用 OptiPNG/PNGcrush
上传 RGBA PNG,期望透明区域在压缩后保持完全透明确认原图透明通道正确(非全黑/全白),压缩后检查透明区域是否出现色块pngquant 在处理透明通道时,会将 alpha 值参与颜色量化;若原图透明区域有半透明像素(alpha < 255),量化后可能出现色斑或边缘锯齿
上传一个已为 8 位索引色(如 GIF 转 PNG)的图片索引色 PNG 直接使用 zopfli 无损压缩(压缩率通常 5%-15%),而非 pngquant 有损压缩pngquant 对索引色输入会自动跳过颜色量化步骤,仅调用 zopfli 进行 deflate 重压缩;此时压缩率取决于原图 IDAT 流的冗余度,不会出现 70%+ 的压缩率
上传 300 DPI 的代码截图或 UI 设计稿对文字/图表截图使用无损压缩(如 OptiPNG)或保存为 PNG-8 索引色pngquant 的颜色量化会合并相近颜色,导致文字边缘出现锯齿或颜色混叠;文字/图表需要精确颜色边界,有损压缩会破坏可读性
点击上传后立刻关闭页面或切换标签页等待页面显示「处理完成」或下载按钮出现后再操作本工具在浏览器端 WASM 中完成压缩(pngquant+zopfli),处理期间若关闭标签页,浏览器会终止 Web Worker,导致已压缩的数据丢失
公式推导 · 流程图解 · 依据出处
S = (1 - (F / O)) × 100%
S — 压缩率(百分比)F — 压缩后文件大小(字节)O — 原始文件大小(字节)原始 PNG 图片 512 KB(O=524,288 字节),经 pngquant 量化 + zopfli 无损重压缩后得到 128 KB(F=131,072 字节)。S = (1 - 131072/524288) × 100% = (1 - 0.25) × 100% = 75%。即压缩率为 75%,文件减小至原大小的 25%。
适用于 pngquant 有损量化(减少颜色数)配合 zopfli 无损压缩的流程。对于已高度压缩的 PNG(如摄影图含大量噪点),压缩率可能低于 10%;对于索引色或低色彩图片(图标、截图),压缩率可达 80% 以上。
3 种主流语言 · 复制即用
import subprocess
import os
# 使用 pngquant 压缩 PNG(有损量化,颜色数降至 256 色以内)
input_path = "input.png"
output_path = "compressed.png"
# pngquant 参数:--speed=1 最高压缩率,--quality=65-80 质量范围
result = subprocess.run(
["pngquant", "--speed=1", "--quality=65-80", "--output", output_path, input_path],
capture_output=True,
text=True
)
if result.returncode == 0:
original_size = os.path.getsize(input_path)
compressed_size = os.path.getsize(output_path)
print(f"原始: {original_size} bytes → 压缩后: {compressed_size} bytes")
print(f"压缩率: {(1 - compressed_size / original_size) * 100:.1f}%")
else:
print(f"压缩失败: {result.stderr}")package main
import (
"fmt"
"image/png"
"os"
"github.com/tdewolff/minify/v2"
"github.com/tdewolff/minify/v2/png"
)
func main() {
// 使用 go 的 png 库进行无损压缩(类似 zopfli 的优化)
inputFile, err := os.Open("input.png")
if err != nil {
panic(err)
}
defer inputFile.Close()
img, err := png.Decode(inputFile)
if err != nil {
panic(err)
}
outputFile, err := os.Create("compressed.png")
if err != nil {
panic(err)
}
defer outputFile.Close()
// 使用 minify 库进行 PNG 压缩(优化过滤器和压缩级别)
m := minify.New()
m.Add("image/png", &png.Minifier{})
if err := m.Minify("image/png", outputFile, inputFile); err != nil {
panic(err)
}
fmt.Println("PNG 压缩完成")
}const sharp = require('sharp');
const fs = require('fs');
// 使用 sharp 库进行 PNG 压缩(类似 TinyPNG 的量化 + 优化)
async function compressPNG(inputPath, outputPath) {
try {
const originalSize = fs.statSync(inputPath).size;
// sharp 默认使用 pngquant 风格的量化,并优化过滤器和 zlib 压缩
await sharp(inputPath)
.png({
compressionLevel: 9, // 最大压缩级别
palette: true, // 启用调色板量化(减少颜色数)
quality: 80, // 质量范围 0-100
adaptiveFiltering: true, // 自适应过滤优化
force: true // 强制输出 PNG
})
.toFile(outputPath);
const compressedSize = fs.statSync(outputPath).size;
console.log(`原始: ${originalSize} bytes → 压缩后: ${compressedSize} bytes`);
console.log(`节省: ${((originalSize - compressedSize) / originalSize * 100).toFixed(1)}%`);
} catch (err) {
console.error('压缩失败:', err.message);
}
}
compressPNG('input.png', 'compressed.png');8 个高频疑问
「压缩 / 优化」下的其他工具