3

到目前为止,使用pdfimagesmupdf/的图像提取工作正常。mutool

使用 FreePDF 生成的 PDF 中的图像总是被切片,因此一个图像会产生多个图像文件。

有什么技巧可以避免这种情况吗?我怎样才能使用 的结果pdfshow?将 PDF 转换为 PNG 或 JPEG 后,是否有坐标可以知道剪切/裁剪图像的位置、高度和宽度?

4

2 回答 2

6

您的图像在提取后被“切片”的最可能原因是:它们在提取它们之前已经被“切片” - 作为它们在 PDF 文件本身中的生活方式。

不要问我为什么某些 PDF 生成软件会这样做。

1x1MS Powerpoint 因这一点而臭名昭著——显示一些渐变的背景图像通常会在 PDF中被分割成数万像素1x21x8类似大小的迷你图像。


更新

1. 确定问题的范围

可以使用pdfimages -list命令识别示例 PDF 的图像片段(这需要pdfimages基于 Poppler fork 的最新版本,而不是那个xpdf!):

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%

因为 1 页只有 20 个不同的片段,所以很容易...

  1. ...首先将它们全部提取并将它们转换为 JPEG,然后
  2. ...然后再次将它们缝合在一起。

2. 将片段提取为 JPEG

以下命令将提取片段并尝试将它们保存为 JPEG ( -j) 28023312

pdfimages so-28023312-test1.pdf 28023312

有 3 张图像以 PPM 形式出现。使用 ImageMagickconvert从它们制作 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

剖析命令:

  1. +append 图像运算符以水平顺序附加所有列出的图像。

  2. 这些\( ... \)线表示图像堆栈的相应部分的“备用”处理(需要用转义的括号分隔)。然后,此水平附加操作的结果将替换当前图像堆栈中的各个片段。

  3. 最后的-append 图像操作符垂直附加当前图像。

这是生成的 JPEG,再次完全拼接在一起:

拼接在一起:最终图像

这可以自动化吗?

理论上,我们可以自动化这个过程。为此,我们必须分析 PDF 源代码。然而,这是相当困难的,因为内容流可能被压缩。

为了解压缩所有或大部分内容流并更好地表示 PDF 文件结构,我们可以使用mutool clean -d,podofouncompressqpdf --qdf.

我更喜欢qpdf,即“结构化的、保留内容的 PDF 文件转换器”。这是命令:

qpdf --qdf --object-streams=disable so-28023312-test1.pdf qdf.pdf

生成的 PDF 文件qdf.pdf更易于分析,因为大多数(但不是全部)以前的二进制部分现在都是 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

所有的/ImNN Do行都插入图像(/Fm0 Do行是指表单对象而不是图像)。

前面几行,例如490 0 0 369 4238 3406.67 cm设置当前的变换矩阵。仅从这一行,有时就可以推断出图像的位置及其大小。在这个文件的情况下,这还不够——为了确定当前的“绘图位置”,还需要更多前行的内容。

于 2015-01-19T14:56:11.833 回答
2

FreePDF 使用 Ghostscript 并创建一个“虚拟打印机”。当您“打印到 PDF”时,实际发生的是您的应用程序打印到 Windows 打印管道,该管道将图形基元发送到 Windows PostScript 打印机驱动程序,后者将 PostScript 发送到端口监视器。FreePDF 端口监视器将此 PostScript 程序存储在磁盘上。输出完成后,它会启动 Ghostscript,它会解释 PostScript 并生成 PDF 文件。

现在,除非您使用的是非常老的 Ghostscript 版本(这可能的,您应该检查一下!)这将获取输入中的任何内容并将其放入输出中。它不会分割图像。

这意味着,正如 Kurt 和 David 上面所说的,问题的真正原因是 PostScript 程序在 Ghostscript 看到它之前就已经将其中的图像分割了。

现在我知道通常情况并非如此,但这在很大程度上取决于您安装的 PostScript 打印机驱动程序、其配置方式、您使用的 Windows 版本以及驱动打印机的应用程序是什么。

正如大卫所说的那样,Microsoft Office 应用程序有一个以这种方式绘制某些类型图案的坏习惯(为了获得“半透明效果”,他们使用单元格是图像掩码的图案,“白色”像素是透明的)。

此外,如果您有大照片(例如)并且 PostScript 打印机配置了最小内存,驱动程序可能会拆分图像,以免耗尽打印机的内存。显然这是一个配置问题,因为在台式电脑上,您必须使用怪物图像来压倒 Ghostscript。

因此,基本上,我们需要您提供更多信息才能完全回答这个问题,但原则是损坏在它到达 FreePDF 之前就已经造成。用于创建 PDF 文件的 Ghostscript 版本将在 PDF 文件元数据中,除非 FreePDF 选择擦除/覆盖它。

最后,正如 Kurt 所指出的,您应该发布指向 PDF 文件的链接,最好是发布用于生成 PDF 的应用程序文件和中间 PostScript 文件。

于 2015-01-19T15:24:18.617 回答