PDF 压缩
在浏览器本地重新编码 PDF 里的内嵌 JPEG 图像(降质 + 限边长),扫描合同、拍照课件、相册导出这类「图重型」PDF 体积通常明显下降;纯文字型 PDF 的体积大头不在图像,工具会如实提示压缩空间有限,不夸大。全程不上传服务器。
邮箱附件限 20 MB、上传系统卡 10 MB、微信传扫描件转不成——大部分「PDF 太大」其实都是「PDF 里的照片太大」。本工具的做法是:先在本地扫描字节,认出内嵌 JPEG 图像,再按你选的档位重新编码这些图像(降低画质上限、限制最长边),文字与矢量内容原样保留。扫描页数、图像张数会先列出来,压缩前后各多大也如实对比。
如实口径:收益完全取决于文件构成。含 JPEG 图像的 PDF(扫描、拍照、相册导出)收益明显;文字主要由系统字体绘制的 PDF 体积大头在字体与结构,压缩率通常只有几个百分点;图像已被 Flate 无损封装的 PDF 本版不重编码,同样会明确提示。带打开密码的 PDF 无法处理。
这个工具解决你的问题了吗?
提交后会把工具名、你的输入与当前结果发送到服务器;请勿填写身份证号、手机号等隐私信息。
AI 助手 会结合你当前的输入与结果回答
追问会再次把当前输入与结果发送到服务器;请勿填写隐私信息。
使用步骤
- 「选择 PDF」选中要压缩的文件(或直接点示例用内置演示文档)。
- 查看扫描结果:页数与内嵌 JPEG 张数,并确认提示的适用档位。
- 选压缩档位(轻度/标准/极限),点「开始压缩」。
- 等待浏览器本地重编码完成,出现下载按钮后保存,并核对压缩前后大小。
计算原理与示例
怎么压缩 PDF 体积
选中 PDF 后先看扫描结果:页数和内嵌 JPEG 张数决定这文件「值不值得压」。挑档位(轻度/标准/极限)点「开始压缩」,浏览器本地重编码图像后出现下载按钮,压缩前后大小直接对比。
为什么有的 PDF 压不动
PDF 的体积来源不同:图像(可重编码压缩)、字体(本工具不动)、页面结构(本来就几十 KB)。纯文字 PDF 没有 JPEG 可换,所以压不动;扫描照片类几乎全是 JPEG,收益最大。页面提示会如实区分这两种情况。
三个档位怎么选
轻度适合仍要打印/看细节的文件(画质上限高);标准适合邮箱附件、上传系统限大小的日常场景;极限适合只在屏幕上看缩略内容的超大扫描件。拿不准先用标准档试一次,看结果再决定要不要极限档。
画质会损失多少
只影响内嵌图像,文字与矢量始终原样。轻度档人眼几乎看不出差别;标准档在 100% 屏幕放大对比时能看出轻微压缩纹;极限档明显牺牲细节,只推荐做「能传出去」为唯一目标的场合。
代码示例
JavaScript pdf-lib 重编码内嵌 JPEG(浏览器内,不上传)
import { PDFDocument, PDFName, PDFNumber, PDFRawStream } from 'pdf-lib';
const doc = await PDFDocument.load(bytes, { ignoreEncryption: true });
const ctx = doc.context;
for (const [ref, obj] of ctx.enumerateIndirectObjects()) {
if (!obj?.dict) continue;
if (String(obj.dict.lookup(PDFName.of('Subtype'))) !== '/Image') continue;
if (String(obj.dict.lookup(PDFName.of('Filter'))) !== '/DCTDecode') continue;
if (obj.dict.has(PDFName.of('SMask'))) continue; // 带透明通道的跳过
const jpeg = await reEncode(obj.contents, 0.55, 1600); // canvas 解码→限边长→重压
obj.dict.set(PDFName.of('Width'), PDFNumber.of(jpeg.w));
obj.dict.set(PDFName.of('Height'), PDFNumber.of(jpeg.h));
ctx.assign(ref, PDFRawStream.of(obj.dict, jpeg.bytes));
}
const smaller = await doc.save();
Python pikepdf + Pillow 压缩图像流
import io
from PIL import Image
import pikepdf
pdf = pikepdf.open('input.pdf')
for page in pdf.pages:
for name, image in list(page.Resources.get('/XObject', {}).items()):
if image.get('/Filter') == '/DCTDecode':
im = Image.open(io.BytesIO(image.read_bytes()))
im.thumbnail((1600, 1600))
buf = io.BytesIO()
im.convert('RGB').save(buf, 'JPEG', quality=55)
pdf.objects[image].write(buf.getvalue()) # 原样替换 JPEG 流
pdf.save('output.pdf')
常见问题
压缩时 PDF 会上传到服务器吗?
不会。扫描、重编码、组装新文件全在浏览器里完成,没有任何网络传输;关掉网页文件也不曾离开设备。身份证扫描件、合同这类敏感材料可以放心处理。
什么样的 PDF 压缩收益最大?
内嵌 JPEG 图像占比高的文件:手机拍照生成的扫描件、相机直出的相册 PDF、PPT 大量贴图导出的 PDF。工具会先扫描并在结果里写明是否属于这一类,不用猜。
为什么我的 PDF 压缩后几乎没变小?
两种常见原因:一是纯文字/矢量型 PDF,体积大头是嵌入字体,本工具不动字体;二是图像已被 Flate 无损封装(部分手机「打印为 PDF」的产物),本版只重编码 JPEG 图像流,遇到这种情况会明确提示。
压缩会破坏文字清晰度或可选中搜索吗?
不会。只有内嵌图像被重新编码,文字层始终是原始矢量数据,清晰度、可选中、可搜索都不受影响——这也是把扫描件里照片压小、正文保持锐利的意义。
带密码的 PDF 能压缩吗?
带打开密码的不能,浏览器读不到内容;只有权限密码(禁止复制/打印)的文件一般可以正常处理。处理前建议先自己验证文件能正常打开。
单个文件多大以内可以处理?
当前限制单个 30 MB。压缩要在内存里解码每一幅图像,超过这个体积的低配设备可能卡顿或失败;更大的文件建议先用拆分工具分段处理再合并。
扫描件本来就是模糊的照片,压缩后还能看清吗?
标准档对「屏幕阅读 + 打印留档」通常无感;极限档会限制最长边到约 1100 像素,A4 打印时能看出颗粒感。重要文书建议轻度或标准档,压缩后放大检查关键页再用。
和「图片转 PDF」「PDF 合并」这些工具怎么配合?
常见链路是:拍照图片先用图片转 PDF 合成文件,发现太大再来这里压缩;多个已压缩的文件再用 PDF 合并拼成一份。反过来,合并后想整体瘦身,直接对合并结果跑一次压缩也可以。
延伸阅读
来自本站原创文章,讲清这个工具背后的算法与口径。