图像在提取后被“切片”的最可能原因是:它们在提取之前就已经被“切片”了——作为它们在 PDF 文件本身中的生存方式。
不要问我为什么有些 PDF 生成软件会这样做。
MS Powerpoint 因这一点而臭名昭著——显示某些渐变的背景图像经常被分割成数万个1x1
, 1x2
or 1x8
PDF 中的像素和类似大小的迷你图像。
Update
1. 确定问题的范围
样本 PDF 的图像片段可以通过pdfimages -list
命令(这需要最新版本的pdfimages
基于 Poppler 叉子,而不是xpdf
one!):
pdfimages -list so-28023312-test1.pdf
page num type width height color comp bpc enc interp objectID x-ppi y-ppi size ratio
------------------------------------------------------------------------------------------
1 0 image 271 271 rgb 3 8 jpeg no 18 0 163 163 26.7K 12%
1 1 image 271 271 rgb 3 8 jpeg no 19 0 163 163 21.7K 10%
1 2 image 271 271 rgb 3 8 jpeg no 30 0 163 163 22.9K 11%
1 3 image 271 271 rgb 3 8 jpeg no 31 0 163 163 21.8K 10%
1 4 image 132 271 rgb 3 8 jpeg no 32 0 162 163 9895B 9.2%
1 5 image 271 271 rgb 3 8 jpeg no 33 0 163 163 22.5K 10%
1 6 image 271 271 rgb 3 8 jpeg no 34 0 163 163 16.5K 7.7%
1 7 image 271 271 rgb 3 8 jpeg no 35 0 163 163 16.9K 7.9%
1 8 image 271 271 rgb 3 8 jpeg no 36 0 163 163 20.3K 9.4%
1 9 image 132 271 rgb 3 8 jpeg no 37 0 162 163 14.5K 14%
1 10 image 271 271 rgb 3 8 jpeg no 20 0 163 163 17.1K 8.0%
1 11 image 271 271 rgb 3 8 image no 21 0 163 163 107K 50%
1 12 image 271 271 rgb 3 8 image no 22 0 163 163 96.7K 45%
1 13 image 271 271 rgb 3 8 image no 23 0 163 163 119K 56%
1 14 image 132 271 rgb 3 8 jpeg no 24 0 162 163 10.7K 10%
1 15 image 271 99 rgb 3 8 jpeg no 25 0 163 161 7789B 9.7%
1 16 image 271 99 rgb 3 8 jpeg no 26 0 163 161 6456B 8.0%
1 17 image 271 99 rgb 3 8 jpeg no 27 0 163 161 7202B 8.9%
1 18 image 271 99 rgb 3 8 jpeg no 28 0 163 161 8241B 10%
1 19 image 132 99 rgb 3 8 jpeg no 29 0 162 161 5905B 15%
因为一页上只有 20 个不同的片段,所以很容易...
- ...首先将它们全部提取并转换为 JPEG,然后
- ...然后将它们再次缝合在一起。
2. 将片段提取为 JPEG
以下命令将提取片段并尝试将它们保存为 JPEG (-j
) 28023312:
pdfimages so-28023312-test1.pdf 28023312
有 3 个图像以 PPM 形式出现。使用 ImageMagick 的convert
从它们中制作 JPEG(不是严格要求的,但它简化了“拼接”命令行:
for i in 11 12 13; do
convert 28023312-0${i}.ppm 28023312-0${i}.jpg
done
以下是前三个片段:280233312-000.jpg、280233312-001.jpg 和 280233312-002.jpg:
3.将20个碎片再次缝合在一起
ImageMagick 可以将 20 张图像再次拼接在一起。查看 PDF 页面以及 20 个 JPEG 时,很容易确定它们需要放在一起的顺序:
convert \
\( 28023312-0{00,01,02,03,04}.jpg +append \) \
\( 28023312-0{05,06,07,08,09}.jpg +append \) \
\( 28023312-0{10,11,12,13,14}.jpg +append \) \
\( 28023312-0{15,16,17,18,19}.jpg +append \) \
-append \
complete.jpg
剖析命令:
The +append
图像算子按水平顺序附加所有列出的图像。
The \( ... \)
线条表示'aside'处理图像堆栈的相应部分(需要用转义括号分隔)。此水平附加操作的结果将替换当前图像堆栈内的各个片段。
决赛-append
图像算子附加当前图像垂直.
这是生成的 JPEG,再次完全拼接在一起:
这可以自动化吗?
理论上我们可以自动化这个过程。为此,我们必须分析 PDF 源代码。然而,这相当困难,因为内容流可能被压缩。
为了解压缩全部或大部分内容流并获得 PDF 文件结构的更好表示,我们可以使用mutool clean -d
, podofouncompress
or qpdf --qdf
.
我更喜欢qpdf http://qpdf.sf.net/, the “结构性、内容保留的 PDF 文件转换器”。这是命令:
qpdf --qdf --object-streams=disable so-28023312-test1.pdf qdf.pdf
生成的 PDF 文件,qdf.pdf
更容易分析,因为most(但不是all) 以前的二进制部分现在采用 ASCII 格式。当您搜索出现的情况时Do
在这个文件中,您将看到图像插入的位置(但是,我无法在这里为您提供完整的 PDF 分析教程,抱歉...)。
以下命令打印所有行Do
发生,加上前一行 (-B 1
):
grep -a -B 1 " Do" qdf.pdf
1002 0 0 1002 236 5776.67 cm
/Im0 Do
--
1001 0 0 1002 1237 5776.67 cm
/Im1 Do
--
120.12 0 0 120.24 268.44 693.2004 cm
/Im2 Do
--
[...skipping 15 other output segments...]
--
1002 0 0 369 3237 3406.67 cm
/Im18 Do
--
490 0 0 369 4238 3406.67 cm
/Im19 Do
--
1 0 0 1 204.9037018 508.5130005 cm
/Fm0 Do
All the /ImNN Do
行插入图像(/Fm0 Do
线指的是表单对象不是图像)。
例如前面几行490 0 0 369 4238 3406.67 cm
设置当前变换矩阵。仅从这条线,有时就可以推断出图像的位置及其大小。就该文件而言,这还不够——需要更多前面行的内容才能确定当前的“绘图位置”。