PNG 智能压缩

TinyPNG 风格/pngquant + zopfli

422 次访问
PNG MINIFIER · LOSSY QUANTIZATION

PNG 图片压缩

基于颜色量化算法 · 保留透明通道 · 浏览器本地处理

上传 PNG

🖼

拖入或点击选择 PNG(可多选)

原理

颜色量化:PNG 是无损格式,浏览器原生 toBlob('image/png') 不支持质量调节。本工具通过减少 RGBA 颜色数(256 / 128 / 64 / 32)来减小体积,类似 pngquant 算法。

Floyd-Steinberg 抖动:经典误差扩散算法,将量化误差分布到周围像素,避免色块感。

透明保留:PNG 的 Alpha 通道完整保留,适合带透明背景的 LOGO / 图标。

极致压缩:建议先用本工具量化,再用桌面 pngquant + zopfli 进一步压缩 10-20%。

关于本工具

了解工具定位 · 使用场景 · 对比优势

将 PNG 图片压缩至原体积的 60%-80%,视觉质量几乎无损。采用 pngquant 有损压缩 + zopfli 无损再压缩的混合策略,适合前端开发者优化网页图片、设计师导出素材、运营压缩上传图片。纯浏览器处理,图片不上传服务器,无需等待,拖拽即压缩。

使用场景

🌐

网站首屏优化

电商或内容站的首屏加载速度直接影响跳出率。设计师和前端工程师用本工具批量压缩首屏 Banner、产品主图等大尺寸 PNG,在肉眼几乎不可察觉的色差下将文件体积缩小 60%-80%,配合 pngquant 的量化精度控制,确保 Retina 屏上依然清晰锐利。

📱

移动端 App 素材

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 或在线文档。

对比矩阵本工具 vs 竞品 vs 传统方法

维度本工具TinyPNG (tinypng.com)本地 Photoshop 导出
数据隐私纯浏览器处理,图片不上传服务器图片上传至云端服务器处理图片完全保留在本地设备
处理速度1-3 秒(取决于图片大小)5-15 秒(含上传+排队+下载)30 秒-数分钟(手动操作)
离线可用完全离线,无需网络必须联网完全离线
单文件大小限制无限制(由浏览器内存决定)5 MB无限制
收费模式完全免费,无水印每月 500 张免费,超出需付费需购买 Photoshop 许可证
批量处理单张处理支持批量上传需手动操作或录制动作
压缩算法透明度明确使用 pngquant + zopfli未公开具体算法使用 Photoshop 内置压缩算法

使用指南

上手步骤 · 输入输出 · 避坑提示

使用步骤

  1. 拖拽或点击上传 PNG 图片,支持多张同时上传,单张 ≤ 20MB
  2. 工具自动使用 pngquant 算法压缩,保留透明通道
  3. 压缩完成后,点击图片下方的「下载」按钮保存单张
  4. 如需批量保存,点击顶部「全部下载」打包为 ZIP 文件

输入输出示例8 个典型场景,覆盖常规、边界与易错

输入输出说明
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(用户常误以为灰度图无法再压缩)

常见错误对照8 个常踩的坑 · 错误 → 修复

1. 上传非 PNG 格式图片

错误
上传 .jpg / .webp / .gif 文件
修复
上传 .png 文件(或先转换为 PNG 再上传)

本工具仅处理 PNG 格式;其他格式的压缩算法(如 JPEG 的 DCT、WebP 的 VP8)与 pngquant/zopfli 不兼容,强行处理会报错或输出无效文件

2. 上传已高度压缩的 PNG(如 TinyPNG 二次压缩)

错误
把 TinyPNG 或 pngquant 已压缩过的 PNG 再次上传
修复
上传原始 PNG 或仅经过无损压缩(如 OptiPNG)的 PNG

pngquant 对有损压缩过的图片二次压缩时,颜色量化会进一步丢失细节,且 zopfli 对已压缩的 IDAT 流收益极低;重复压缩只会增加画质损失

3. 上传超大尺寸图片(如 10000×10000 像素)

错误
上传 12000×8000 像素、32MB 的 PNG
修复
上传前先用图像处理软件缩小到合理尺寸(如 1920×1080)

pngquant 处理超大图片时内存占用呈线性增长,浏览器端 WASM 版本可能因内存不足崩溃;zopfli 对超大文件耗时可达数分钟

4. 期望无损压缩所有 PNG(不理解有损 vs 无损区别)

错误
认为压缩后像素应与原图 100% 一致
修复
接受 pngquant 将 24 位真彩色降为 8 位索引色(最多 256 色)带来的轻微色差

pngquant 是有损压缩:通过减少颜色数量(颜色量化)来缩小文件体积;zopfli 是后续无损重压缩。若需完全无损,应使用 OptiPNG/PNGcrush

5. 上传带透明通道的 PNG 但期望背景色不变

错误
上传 RGBA PNG,期望透明区域在压缩后保持完全透明
修复
确认原图透明通道正确(非全黑/全白),压缩后检查透明区域是否出现色块

pngquant 在处理透明通道时,会将 alpha 值参与颜色量化;若原图透明区域有半透明像素(alpha < 255),量化后可能出现色斑或边缘锯齿

6. 上传索引色 PNG(256 色以下)期望进一步大幅压缩

错误
上传一个已为 8 位索引色(如 GIF 转 PNG)的图片
修复
索引色 PNG 直接使用 zopfli 无损压缩(压缩率通常 5%-15%),而非 pngquant 有损压缩

pngquant 对索引色输入会自动跳过颜色量化步骤,仅调用 zopfli 进行 deflate 重压缩;此时压缩率取决于原图 IDAT 流的冗余度,不会出现 70%+ 的压缩率

7. 上传包含大量文字/图表的截图期望保持清晰

错误
上传 300 DPI 的代码截图或 UI 设计稿
修复
对文字/图表截图使用无损压缩(如 OptiPNG)或保存为 PNG-8 索引色

pngquant 的颜色量化会合并相近颜色,导致文字边缘出现锯齿或颜色混叠;文字/图表需要精确颜色边界,有损压缩会破坏可读性

8. 上传后立即关闭浏览器标签页,以为下载已完成

错误
点击上传后立刻关闭页面或切换标签页
修复
等待页面显示「处理完成」或下载按钮出现后再操作

本工具在浏览器端 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% 以上。

原理图

上传 PNG拖拽或点击选择pngquant量化颜色zopfli优化压缩下载结果显示压缩率全在浏览器内完成原始文件不上传服务器
用户输入 本地处理(浏览器内 WASM) 输出结果 原始文件(不上传)

开发者集成

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 个高频疑问

压缩后图片变模糊了,怎么调高画质?
这个工具默认用 pngquant 算法把 32 位 PNG 转为 8 位(256 色),这是压缩率最高的模式,但会丢掉颜色细节。如果感觉画质损失太大,可以这样操作:① 在工具界面找「压缩强度」或「颜色数」滑块,把颜色数从 256 调到 1280 或 4096,画质会明显提升,但压缩率会下降。② 如果原图已经是 8 位 PNG(颜色很少),工具不会进一步降色,画质基本不变。③ 建议先用默认参数压一张,对比文件大小和视觉效果,再决定是否调参——大部分网页用图,256 色肉眼看不出来区别。
为什么上传 PNG 后压缩比例很小,甚至比原图还大?
两种情况最常见:① 原图已经是高度压缩过的——比如从微信、QQ 截图保存的 PNG,或者用 Photoshop「存储为 Web 所用格式」时已经压过一次。pngquant 对这类「二次压缩图」几乎不会再有增益,有时反而因重编码增加文件头开销。② 原图尺寸极小,比如 100×100 像素的图标,pngquant 的调色板元数据占比会偏高。建议:先确认原图是不是从其他压缩工具导出的,如果是,直接跳过本工具;小图标可以试试勾选「去除元数据」选项(如果有)。
这个工具和 TinyPNG 有什么区别?哪个压缩率更高?
核心算法一样——都是 pngquant + zopfli 组合。差别在两点:① 处理方式:TinyPNG 是服务器端压缩,文件上传到他们的 AWS 再下载回来;这个工具完全在浏览器内(WASM 汇编)运行,文件不上传服务器,适合处理敏感图片。② 压缩率:同一张图在两边的结果几乎一致,因为 pngquant 的量化参数和 zopfli 的迭代次数都是标准实现,差异在 1% 以内。如果追求极致压缩,可以手动调整本工具的「zopfli 迭代次数」(如果有此选项),从默认 15 次提到 100 次,但处理时间会从几秒变成几十秒。
压缩后的 PNG 还能再压一次吗?会继续变小吗?
不建议重复压缩。第一次压缩时 pngquant 已经把调色板从 32 位降到 8 位,第二次运行时原图已经是 8 位 PNG,pngquant 检测到颜色数达标会直接跳过量化阶段,只跑 zopfli 再压缩一次。zopfli 是确定性的无损压缩,同一张图跑两次结果完全相同,文件大小不变。如果第一次用了「极低质量」模式压到 64 色,第二次再压才会继续降色,但画质会断崖式下降——等同于把一张 256 色图强行降到 64 色,色块感非常明显。一次到位设定好参数就够了。
压缩后图片颜色变了,特别是红色和蓝色区域有色块条纹?
这是 pngquant 的「抖动」设置引起的。pngquant 默认开启 Floyd-Steinberg 抖动算法,用相邻像素的颜色混合来模拟丢失的颜色信息,在颜色渐变区域(天空、皮肤、渐变背景)会产生规律性的点阵纹理,远看正常,放大看像马赛克条纹。解决办法:① 在工具设置里找到「抖动」选项,调低抖动强度(比如从 1.0 降到 0.3)或直接关闭抖动,色块条纹会消失,但颜色过渡会变生硬(出现明显色阶)。② 如果原图有大量渐变,建议改用 JPEG 或 WebP 压缩,PNG 不适合平滑渐变场景。
压缩后的 PNG 在手机上显示不正常,背景变黑或变白?
检查原图是不是用了「透明通道」(Alpha 通道)。pngquant 默认保留透明通道,但某些旧版手机浏览器(Android 7 以下自带浏览器)对 8 位 PNG 的透明支持不完整,会把透明区域渲染成黑色或白色。解决方法:① 在工具里找「保留透明」选项,如果不需要透明(比如纯色背景图),取消勾选,工具会填充白色背景再压缩。② 如果必须保留透明,压缩后把图片传回电脑用 Photoshop 或 GIMP 打开,确认透明通道是否完整——如果电脑上正常、手机上异常,是手机浏览器兼容问题,不是工具的问题。
这个工具有文件大小或图片尺寸限制吗?最大能压多大?
由于处理完全在浏览器内,限制取决于浏览器的内存上限(通常 2GB 左右)。实测:① 单张 4000×4000 像素、文件大小 15MB 的 PNG 可以正常处理,耗时约 30 秒(取决于 CPU 性能)。② 超过 6000×6000 像素或文件大小超过 50MB 的图片,浏览器可能因内存不足崩溃,建议用桌面版压缩工具处理超大图。③ 手机浏览器内存更小(通常 500MB 上限),建议单张控制在 2000×2000 像素以内。如果上传后页面卡死,可以刷新后换一张小图重试。
压缩后文件下载不下来,或者下载的图片打不开?
最常见的原因是浏览器弹窗拦截或下载目录权限问题。① 检查浏览器地址栏右侧是否有下载被拦截的提示图标(一个带红叉的箭头),点开选择「允许下载」即可。② 下载的 .png 文件如果打不开,用记事本或十六进制编辑器打开看文件头——正常 PNG 文件头以 `‰PNG` 开头(89 50 4E 47),如果文件头是 `data:image/png;base64` 说明下载的是 Base64 文本而非二进制文件,需要手动改后缀为 .txt 再复制内容到在线 Base64 解码器还原。③ 如果以上都正常,可能是浏览器缓存了旧版本文件,清空浏览器缓存后重新压缩一次。
选择 打开 +新窗口 esc关闭