☰
PDF转长图清晰度优化:分辨率、渲染拼接与压缩避坑
2026/10/28 6:32:01 网站建设 项目流程

PDF转长图,最怕的不是转不出来,而是转出来之后字糊了。手机上缩着一看还行,手指一放大,笔画黏成一团,标题带毛边,正文像被水泡过。前两天 A同学 把一份二十来页的产品手册转成一张长图发出去,对方回了一句“能不能发个清楚的”,他前后重做了三遍,一次比一次糊,最后怀疑是软件的问题。我拿过来看了一眼原文件——文字是矢量的,一点问题没有,糊的环节全在“转”和“发”这两步上。

这事我踩过太多回。问题基本不出在工具本身,十有八九是三个地方出了岔子:渲染时的像素密度没算对、拼接和保存时被重采样了一遍、发布平台对超大长图又做了二次压缩。这篇就把这三件事拆开讲,给出三条实际能跑通的路线——本地高分辨率渲染后精确拼接、矢量中转拼接、在线工具加事后补救,每条都给到能直接抄的参数和命令。经常要把合同、手册、课件、票据、简历、方案转成长图的人,不管会不会命令行,都能找到适合自己的一条。

1. PDF转长图为什么会糊:先把病根找出来

1.1 三种“糊”长得不一样,处理方式完全不同

很多人把“糊”当成一个笼统的问题,其实它至少有三种形态,对应的解法完全不同。第一种是边缘发虚,文字还能认,但笔画周围有一圈灰蒙蒙的过渡,放大看像用毛笔写的。这种多半是渲染分辨率勉强够、又在保存时被有损压缩削了一刀,属于“差一点”的情况,把像素密度提上去、换成无损格式基本能解决。

第二种是笔画粘连,小字号的中文尤其明显,“口”字中间那一点糊成实心,“日”字三条横挤成一条。这是像素根本不够用,一个汉字在几十个像素宽的空间里表达不出来,软件只能硬凑,结果就是结构崩掉。这种必须从源头提高渲染宽度,后期再怎么锐化都是往糊上抹粉。

第三种是块状马赛克,放大之后能清楚看到一个个方块,文字边缘呈阶梯状。这说明图片已经被重采样过至少一次,比如原图 3000 像素宽,上传后被平台压到 1080 像素,再放大就全露馅了。这种情况最冤,因为你本地转出来的图可能非常清楚,是“发出去”这一步毁掉的。

判断方法很简单:把转出来的长图放大到 300% 到 400%,盯着一个笔画复杂的字看。边缘有细腻的灰阶过渡,是第一种;整个字的结构已经糊死,是第二种;能看到明显的方格,是第三种。先分清是哪一种,再决定改渲染参数、改输出格式,还是改发布尺寸,能省掉一大半无谓的试错。

1.2 分辨率不是越高越好:算一笔实在账

新手最容易掉进的坑,是觉得“既然糊,那就把 DPI 拉到最高”。我见过有人把一份十页文档按 600 DPI 转成长图,单张图 5000 多像素宽、四万多像素高,文件八九十兆,本地打开清清楚楚,发出去之后对方看到的还是一团浆糊。为什么?因为平台对图片有尺寸和体积上限,超出就强制重采样压缩,你多出来的那些像素不但白费,还因为压缩率更高,反而比一开始就按目标尺寸输出更糊。

所以第一步得先算清楚:我这张长图最终要在多大的屏幕上显示。手机竖屏的物理像素宽度普遍在 1080 到 1440 之间,一张长图在手机上全屏显示时,图片宽度被压缩到屏幕宽度,你给 1200 像素宽和给 4000 像素宽,观感是一样的,但后者会触发平台压缩。

换算关系其实很简单,PDF 的页面尺寸单位是点(pt),1 英寸等于 72 点,所以:

输出像素宽 = 页面宽度(pt) × DPI ÷ 72

拿最常见的 A4 举例,宽 595 点:

渲染 DPI单页像素尺寸(A4)适合场景
72595 × 842仅屏幕预览,文字必糊
96794 × 1123在线工具默认值,勉强能看
120992 × 1403手机查看的下限
1501240 × 1754手机端长图的主力档位
2001654 × 2339平板查看、需要局部放大
3002480 × 3508打印、存档、OCR 识别
6004960 × 7016除非要印刷,否则纯属浪费

我的习惯是:发到聊天软件或内容平台的长图,宽度锁定 1240 像素,也就是 A4 按 150 DPI 渲染。这个宽度比主流手机屏宽出一点点,缩放时是缩小而非放大,文字边缘干净;文件体积也可控。如果是给平板看、或者图里有很多小字表格需要读者放大看的,就上到 1654 像素宽。

还有一个容易被忽略的约束是总高度。十页 A4 按 150 DPI 拼起来,总高 17540 像素,这时候单张图的像素总量是 1240 × 17540 ≈ 2174 万,还算正常。但如果你按 300 DPI 拼二十页,总高会到 7 万像素,像素总量过亿,不但本地处理时内存吃紧,绝大多数平台也会直接拒绝或者裁切。我的经验阈值是:单张长图总高度控制在 15000 像素以内,超过就切成两张,宁可发两条,也别发一条被压成马赛克的。

1.3 藏在渲染环节的四个隐形杀手

除了分辨率,还有四个细节在悄悄影响清晰度,很多“明明参数设对了还是糊”的情况都出在这。

第一个是抗锯齿策略。渲染器把矢量文字转成像素时,边缘要不要做灰度过渡,是有开关的。开启后边缘柔和,缩小显示时观感好;但当你的输出像素密度远超实际显示尺寸时,多余的灰度过渡在缩放时会被再次平均,反而显得发虚。我的做法是:目标宽度接近显示宽度时,抗锯齿开灰度模式即可;如果输出宽度是显示宽度的两倍以上,可以试着关掉矢量抗锯齿,让边缘更“硬”,缩放时反而更锐利。这个差异在小字号上特别明显,值得各试一次对比。

第二个是 JPEG 的色度抽样。这是最隐蔽的一个。JPEG 默认采用 4:2:0 抽样,意思是对亮度保留全部信息,对色度只保留四分之一。黑白文字受影响不大,但一旦文字带颜色,或者页面有彩色背景,笔画边缘就会出现红蓝色的小杂边,放大看就是“发虚”的元凶之一。解决办法是保存 JPEG 时把抽样关掉(4:4:4),或者干脆存 PNG。

第三个是字体替换。PDF 里如果字体没有完整嵌入,渲染器会找系统里的近似字体顶上。中文字体的字形差异很大,替换之后笔画粗细、字面大小都可能变,严重时相邻笔画直接粘在一起。表现是“同一份文档,在别人电脑上转就清楚,在你这儿就糊”。这种情况只能装字体,或者换用对字体回退处理更保守的渲染器。

第四个是 CropBox 与 MediaBox 不一致。有些 PDF 页面带着裁切框,实际可见区域比页面定义小。渲染时不读裁切框,就会把周围的空白也转进来,白白浪费像素预算,等于变相降低了有效分辨率。这个坑在从排版软件导出的 PDF 上特别常见。

2. 方法一:本地高分辨率渲染后精确拼接

2.1 这条路线为什么最稳

本地渲染拼接是我日常的主力方案,原因不复杂:整个过程每一步都可控、可复现、可批量。渲染器读的是 PDF 里的矢量指令,文字在原文件里是数学描述,不是像素,所以只要渲染时的像素密度给够,转出来的文字就是“原生锐利”的,不存在放大失真的问题。这和截图、拍照、录屏那些“先有像素再处理”的路线有本质区别。

另一个好处是数据不出本机。合同、报价单、内部资料这类东西,往在线转换站一传,等于把内容交给了不认识的服务器,风险不值当。本地跑一遍,几分钟的事。

这条路线唯一的门槛是要动手敲几条命令或者跑个脚本。但说实话,常用的就那么几条,抄一次存下来,以后改个文件名就能用,比反复在网页上点来点去省时间。下面我把命令行的快捷版和脚本的精确版都给出来,赶时间用前者,要批量、要控制细节用后者。

2.2 参数计算:目标宽度、渲染倍数与总高度

动手之前先把三个数算出来,后面所有操作都围绕它们。

目标宽度:按 1.2 节的表,手机端取 1240,平板端取 1654。如果你的 PDF 不是 A4 而是 A3 或者自定义尺寸,别死记数字,用公式反推:先用工具查一下页面宽度是多少点,然后用目标宽度 ÷ 页面宽度 × 72算出该用多少 DPI。比如一份宽 842 点(A3)的文档,想要 1500 像素宽,就是 1500 ÷ 842 × 72 ≈ 128 DPI。

总高度:把每页按目标宽度等比缩放后的高度加起来,再加上页间距。十页 A4 按 1240 宽算,每页高 1754,总高 17540,加 9 个 20 像素的间隙就是 17720。这个数决定了后面要不要切片。

内存预估:拼接时内存占用大致等于 宽 × 高 × 每像素字节数。RGB 是 3 字节,加上中间过程翻一倍比较保险。上面那个例子是 1240 × 17720 × 3 ≈ 66 MB,翻倍也就 130 MB,毫无压力。但如果有人想按 300 DPI 拼五十页,那就是 2480 × 87700 × 3 ≈ 650 MB,翻倍后过 G,这时候脚本容易崩,必须切片处理。

提示:切片不是“没办法才做的事”,而是常规操作。切成两三张高 8000 到 12000 像素的图,用户滑动阅读的体验反而更好,加载也快,还不容易被平台压缩。

2.3 命令行一步到位:渲染加拼接

系统上装了 poppler 工具集的话,一条命令就能把 PDF 拆成逐页 PNG:

pdftoppm -png -r 150 -aa yes -aaVector yes -cropbox input.pdf page

参数逐个说清楚:-r 150是渲染 DPI,A4 出来正好 1240 像素宽;-aa yes开启图形抗锯齿,-aaVector yes专门针对矢量元素(文字和线条)开启抗锯齿,这两个对文字观感影响很大;-cropbox让渲染按裁切框来,避免把页面外的空白也吃进像素预算里。

跑完会得到 page-1.png、page-2.png 这样一串文件。接下来拼接:

magick $(ls page-*.png | sort -V) -append long.png

这里有个必须注意的坑:如果直接写magick page-*.png -append long.png,shell 展开时是按字符串排序的,page-10.png 会排在 page-2.png 前面,拼出来的长图页序就乱了。我第一次遇到这问题时排查了半天,以为是渲染出错。正确做法是用sort -V做自然排序,或者干脆在渲染时就用-d之外的方式补零命名。这个小细节值不值得单拎出来说?值得,因为我见过不止一个人被它坑过,而且症状很迷惑——图能拼出来,就是中间几页顺序不对。

用 ImageMagick 还有可能撞上安全策略限制,报“not authorized”之类的错,那是因为默认配置对单图宽度、高度、面积设了上限。改配置或者在命令里加-limit memory 2GiB -limit map 4GiB可以绕过一部分,但改配置文件更彻底。如果嫌麻烦,直接用下面的脚本方案,不受这些限制。

2.4 用脚本精确控制:完整可运行的实现

需要精细控制的时候,我一般用 Python 写十几行,好处是每一页的尺寸、对齐、间隙、背景色都能自己说了算,而且能顺手做切片。

import fitz # PyMuPDF from PIL import Image SRC = "input.pdf" TARGET_W = 1240 # 目标宽度像素 GAP = 20 # 页间距 MAX_SLICE_H = 15000 # 单张最大高度 BG = (255, 255, 255) # 白底,避免透明通道 doc = fitz.open(SRC) pages = [] for page in doc: rect = page.rect zoom = TARGET_W / rect.width # 以宽度为准等比缩放 pix = page.get_pixmap( matrix=fitz.Matrix(zoom, zoom), alpha=False, # 关键:不留透明通道 colorspace=fitz.csRGB, # 关键:统一 sRGB ) im = Image.frombytes("RGB", (pix.width, pix.height), pix.samples) if im.width != TARGET_W: # 浮点误差导致差 1px,补齐 im = im.resize((TARGET_W, im.height), Image.LANCZOS) pages.append(im) total_h = sum(p.height for p in pages) + GAP * (len(pages) - 1) canvas = Image.new("RGB", (TARGET_W, total_h), BG) y = 0 for p in pages: canvas.paste(p, (0, y)) y += p.height + GAP if total_h <= MAX_SLICE_H: canvas.save("long.png", optimize=True) else: parts = (total_h + MAX_SLICE_H - 1) // MAX_SLICE_H step = total_h // parts for i in range(parts): top = i * step bottom = total_h if i == parts - 1 else (i + 1) * step canvas.crop((0, top, TARGET_W, bottom)).save(f"long_{i+1}.png", optimize=True)

几个参数值得单独解释。alpha=False是必须的,如果开了透明通道,导出的 PNG 在某些平台上会被填成黑底,白纸黑字直接变成黑纸白字,非常尴尬。colorspace=fitz.csRGB是防止个别 PDF 带 CMYK 或灰度色彩空间时,转出来的颜色偏暗偏青。zoom用宽度反推而不是写死 DPI,是为了兼容非 A4、或者页面宽度不统一的文档——同一份 PDF 里混着 A4 和 A3 页面时,按宽度对齐才能保证拼出来左右边缘是齐的。

上面那段if im.width != TARGET_W的补齐也别说它多余。1240 / 595是个除不尽的小数,渲染器四舍五入之后偶尔会给你 1239 或 1241 像素宽,差这一像素,粘到固定宽度的画布上就会在右边留一条一像素的白边,长图放大看就是一溜白线。我吃过这个亏,后来一律加这行代码兜底。

2.5 输出格式与压缩参数的取舍

格式选择上,我的原则是:要再加工、要存档、页面颜色简单,用 PNG;要发出去、体积敏感、有大量照片或渐变,用 JPEG 但必须调参。

PNG 是无损的,文字边缘不会因为压缩产生杂边,缺点是体积大。一份十页的纯文字文档,1240 像素宽的长图存 PNG 大概 3 到 6 MB,大多数平台能接受。如果页面里有大量扫描图片,PNG 体积会飙到几十兆,这时候换 JPEG。

JPEG 的关键参数有两个:

canvas.save("long.jpg", quality=95, subsampling=0, optimize=True)

quality=95是文字类图片的甜点值,再低就开始出现方块状噪点,再高体积涨得快而观感提升有限。subsampling=0就是 1.3 节说的关闭色度抽样,采用 4:4:4,这一项对彩色文字边缘的锐度提升非常明显,代价是体积增大约三分之一,但对长图来说完全值得。

注意:别用“质量 80、优化体积”那一套默认配置去处理文字长图。80 质量对照片够用,对文字就是灾难,笔画边缘会出现明显的振铃噪点,放大看一圈一圈的。

3. 方法二:走矢量中转,先存成 SVG 再拼

3.1 矢量路线的适用前提

方法一是“按需要的尺寸渲染一次”,方法二是“先保持矢量,需要多大再出多大”。区别在于,前者一旦渲染成像素,尺寸就定死了;后者把页面转成 SVG 之后,文字和线条仍然是数学描述,理论上可以用任意倍率输出,永远不会糊。

这条路线适合两类场景。一类是超长或超宽的展示需求,比如要做一面墙的展示图、要放到大屏上循环播放,尺寸远超常规长图,用方法一渲染会导致单张图像素量爆炸。另一类是需要多次复用同一份内容,比如同一份文档既要出手机版长图,又要出印刷版,矢量的中间文件可以反复出不同尺寸,不用每次从 PDF 重来。

前提也很明确:PDF 里的文字必须是矢量的。如果原文件本身就是扫描件、或者里面的文字是贴进去的图片,转成 SVG 之后拿到的还是位图,这条路线等于白走。判断方法是用 PDF 阅读器试着选中一段文字,能选中、能复制,说明是矢量的;选不中就基本是图。

3.2 转换与拼接的具体做法

先把每页转成独立 SVG:

pdftocairo -svg input.pdf page

会得到 page-1.svg、page-2.svg 这样一串文件。然后用一小段脚本把它们垂直拼成一个大 SVG:

import re, glob def svg_size(fp): s = open(fp, encoding="utf-8").read(2000) w = float(re.search(r'width="([\d.]+)pt"', s).group(1)) h = float(re.search(r'height="([\d.]+)pt"', s).group(1)) return w, h files = sorted( glob.glob("page-*.svg"), key=lambda x: int(re.search(r'-(\d+)\.svg', x).group(1)) ) sizes = [svg_size(f) for f in files] W = max(w for w, _ in sizes) H = sum(h for _, h in sizes) body, y = [], 0 for f, (w, h) in zip(files, sizes): inner = open(f, encoding="utf-8").read() inner = re.sub(r'^.*?<svg[^>]*>', '', inner, flags=re.S) inner = inner.rsplit('</svg>', 1)[0] body.append(f'<g transform="translate(0,{y})">{inner}</g>') y += h out = ( f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}pt" height="{H}pt" ' f'viewBox="0 0 {W} {H}">{"".join(body)}</svg>' ) open("long.svg", "w", encoding="utf-8").write(out)

拼好的 long.svg 可以用任意矢量渲染器按需要的宽度出图:

rsvg-convert -w 1240 -o long.png long.svg

想要 3000 像素宽就改-w 3000,文字依然是锐利的。这就是矢量路线最大的价值:同一份中间产物,出多少种尺寸都不掉质量。

3.3 哪些PDF不适合走矢量

矢量路线不是万能的,几种情况会翻车,提前知道能省时间。

字体没有嵌入的 PDF。转成 SVG 时,文字会被替换成路径或者引用外部字体。如果是路径,那没问题,形状固定;如果是引用字体名,渲染时找不到就变成方块或者回退字体,字形全变。这种情况得先装字体,或者退回方法一用系统字体渲染。

带复杂透明度、混合模式、滤镜的页面。SVG 对这些特性的支持不如 PDF 完整,转换后可能出现色块错位、阴影丢失、图层顺序乱掉。表现是“文字很清楚,但背景的图全乱了”,比糊更难受。遇到这类文档,老老实实用方法一。

页数很多的文档。二十页拼出来的 SVG 可能几十兆,渲染器打开就卡,编辑起来更别提。这种情况要么分批处理,要么直接用方法一。

扫描件。前面说过了,再强调一次:判断标准是能不能选中文字,选不中就走方法一,别浪费时间。

4. 方法三:在线工具与已糊图的补救

4.1 在线工具怎么挑、怎么验

在线转换站是省事的路子,打开网页、传文件、点转换、下载,一分钟搞定。但这类工具的质量差异极大,同一份文档,有的转出来清清楚楚,有的糊得没法看,差别就在几个参数上。

选的时候我会看三个东西。第一,有没有输出尺寸或者 DPI 的选项。只能“一键转换”不给参数的,默认值通常是 96 DPI,A4 出来只有 794 像素宽,中文小字必糊。给到“高清”“超清”档位的相对靠谱,但仍要验证。第二,页面数上限和体积上限。很多站免费版限 10 页、10 MB,超了就自动压缩,这个压缩过程你完全看不见,出来就是糊的。第三,有没有水印。有些站在长图角落加个小标识,正式发出去很难看。

下载之后别急着用,先验一下。右键查看图片属性,看实际像素宽度。如果 CAT 出来只有 800 出头,那基本是 96 DPI,小字肯定不行;如果给了 1200 以上,再放大到 200% 看看笔画有没有粘连。这一步花十秒钟,能避免发出去被人说“看不清”。

隐私这块得说一句实在话:合同、票据、内部资料、带个人信息的表单,不要往不认识的站点传。你没法确认它转完之后是删了还是留着。这类内容一律走方法一。

4.2 已经糊了还能救回来多少

如果图已经转糊了、原 PDF 又拿不到,能救回来多少取决于糊的类型。回到 1.1 节的三种形态:

边缘发虚型(有细腻灰阶过渡、结构还在)有救,而且效果不错。思路是先放大再锐化,用重采样把模糊的边缘重新“聚”起来。命令行一行就能做:

magick in.png -filter Lanczos -resize 150% -unsharp 0x0.75+0.75+0.008 out.png

-filter Lanczos是放大时用的插值算法,比默认的双线性锐利得多;-unsharp 0x0.75+0.75+0.008是反锐化掩模,三个参数分别是半径、强度、阈值——半径 0.75 适合文字这种细线条,强度 0.75 是中等偏轻,阈值 0.008 是让平坦区域不参与锐化,避免白底出现噪点。这个组合我试过很多次,对轻微发虚的文字提升明显,再往上加强度就会出现白边(晕影),反而更难看。

笔画粘连型基本没救。结构信息已经丢了,锐化只会让粘连处出现更难看的黑块。这种只能回源头重转,或者用 OCR 把文字识别出来重新排版——但重新排版意味着版式全变,通常不划算。

块状马赛克型也没救。重采样把高频信息彻底抹掉了,放大只是把方块变大。唯一能做的是拿到原始大图,或者重新从 PDF 转。

提示:判断有没有救,用一个简单方法——把图放大到 400%,看边缘是“渐变”还是“台阶”。渐变说明信息还在,只是被柔化了,能救;台阶说明信息已经丢了,别浪费时间。

4.3 轻量锐化的参数边界

锐化是个双刃剑,参数过了比不锐化更糟。我总结的边界是:

场景半径强度阈值说明
轻微发虚的文字0.60.50.01保守,几乎无副作用
明显发虚的文字0.750.750.008常用档位
极度发虚、字号大1.01.00.005上限,再高出白边
有照片混合0.50.40.02避免照片噪点被放大

超过这个范围,白字周围会先出现一圈亮边,深色字周围出现暗边,整体观感是“扎眼”,比糊还难看。另外锐化一定要在放大之后做,先锐化再放大会把噪点一起放大,效果差很多。

5. 三种方法实测对比与选型清单

5.1 实测数据对比

拿一份二十页 A4、纯文字加少量表格的文档做了一轮对比,输出目标宽度统一 1240 像素,结果如下:

维度方法一 本地渲染拼接方法二 矢量中转方法三 在线工具
文字锐度高,边缘干净最高,任意尺寸重出看站点,多数中等
处理耗时约 15 秒约 40 秒看网速,1 到 3 分钟
总高度可控完全可控,可切片完全可控多数不可控
批量能力强,脚本一次跑完强弱,逐个传
数据是否出本机否否是
上手门槛中,需命令行高,需改脚本低
翻车概率低中,字体和图形易出问题高,参数不透明

耗时差异主要来自矢量转换那一步,SVG 文件的解析和重写比直接渲染慢不少。但如果考虑“返工成本”,方法一其实最省时间——一次配对参数,后面就是复制粘贴,不用反复试。

5.2 按场景选型

不用纠结哪个“最好”,按场景挑就行:

  • 日常发聊天软件、发内容平台:方法一,宽度 1240,PNG 或高质量 JPEG,高度超 15000 就切两张。
  • 要给平板看、图里小字多:方法一,宽度提到 1654,总高控制在 12000 以内。
  • 要做大屏展示、要印刷:方法二,矢量中间文件出大尺寸。
  • 同一份内容要出多种尺寸:方法二,一次转换多次输出。
  • 临时应急、内容不敏感:方法三,但下载后必须验像素宽度。
  • 扫描件:只能方法一,而且要考虑 OCR 重排,因为原图本身就没有矢量信息。
  • 已经糊了、原文件丢了:方法三的补救流程,先判断类型再决定救不救。

5.3 长图发布前的最后一道校验

图做完了别直接发,花三十秒走一遍自检:

  1. 看像素宽度:右键属性,确认是 1200 以上,不是 800 出头。
  2. 看文件体积:超过平台常见上限(多数在 5 到 10 MB)就先压一压或者切片。
  3. 放大到 200% 扫一眼:重点看小字号、数字、标点,这几类最容易糊。
  4. 检查页序:从第一页翻到最后一页,确认sort -V那个坑没踩。
  5. 检查首尾:第一条和最后一条有没有被裁掉,切片的图尤其要看接缝处。

6. 常见问题与排查速查表

6.1 症状对照表

症状最可能的原因处理方式
小字笔画粘连,大字正常渲染像素宽度不足目标宽度提到 1240 以上
彩色文字边缘有红蓝杂边JPEG 4:2:0 色度抽样存 PNG 或subsampling=0
长图中间出现一像素白线拼接高度计算差 1px 或有间隙精确累加高度,统一补齐宽度
页序错乱,第 10 页跑到第 2 页前文件名按字符串排序sort -V或提取数字排序
部分页面整页空白CropBox 与 MediaBox 不一致渲染时加-cropbox
中文字体变方块或字形怪异字体未嵌入,被替换安装字体或换渲染器
本地清楚,发出去变糊平台二次压缩输出宽度降到平台基准附近
导出时报内存不足单张图过高切片输出,单张限 15000 像素
透明背景导出变黑底保留了 alpha 通道alpha=False,铺白底
整体颜色发暗发青源文件是 CMYK 色彩空间渲染时指定 sRGB
放大后有台阶状锯齿已被重采样过回源头重转,无法事后修复
文字周围有一圈白边锐化过度降低强度到 0.5 以下

6.2 几个我实实在在踩过的坑

第一个坑:以为 DPI 越高越清楚。早期我把一份文档按 600 DPI 转出来,本地打开完美,发给对方却被压成了糊图。后来才想明白,平台不管你原图多大,只看最终展示尺寸,多出来的像素不但没用,还因为压缩比更高,损失更严重。现在的习惯是“按显示宽度出图”,一步到位。

第二个坑:忽略 JPEG 的色度抽样。有一份带蓝色标题的文档,怎么转标题边缘都有一圈紫红色的毛边,我一度以为是字体渲染的问题,换了三个渲染器都没用。后来把保存参数改成subsampling=0,毛边立刻消失。这个参数藏得很深,但效果立竿见影。

第三个坑:拼接时的浮点误差。每页高度乘以缩放倍率之后是个小数,取整时每一页都可能差一像素,十页累积下来,接缝处就会出现细白线或者一像素的重叠黑线。解决办法就是在拼接时统一把每页 resize 到精确的目标宽度,高度按整数累加,别指望渲染器给你整数。

第四个坑:切片位置切在文字中间。自动按固定高度切片,很容易一刀切在一行字上,上下两张各留半行,读起来很难受。如果在意观感,可以在切片前先扫一遍,找出接近切点的整行空白位置作为切分点,稍微复杂一点,但体验好很多。懒人做法是切片时留一点点重叠,让读者自己接上。

第五个坑:把扫描件当矢量件处理。有次接到一份 PDF,看着排版规整,转出来怎么都糊,试遍了所有参数。最后用阅读器试着选中文字,才发现根本选不中——整份文档就是一张张扫描图贴进去的。这类文件唯一的出路是提高扫描源的分辨率,或者做 OCR 重排,在“转长图”这个环节上再怎么调参数都是徒劳。

第六个坑:忘了检查最后一页。用pdftoppm渲染时,如果中途出错,可能只生成了前十几页的 PNG,后面的缺失。拼接脚本不会报错,它只是把现有的文件拼起来,结果长图少了几页,你不从头翻到尾根本发现不了。现在的习惯是渲染完先ls | wc -l数一下文件数量,跟 PDF 页数对一遍再拼接。

这套流程跑顺之后,一份二十页的文档从转出到发出,前后不到两分钟,而且基本不会返工。真正的成本从来不在敲命令那几下,而在于一开始没搞清楚糊的到底是哪一环,对着工具反复试参数。先判断类型,再算参数,最后才动手,这个顺序反过来,省下来的时间够你把整份文档重排一遍。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询