从大PDF中提取页面大小

时间:2018-07-25 17:48:48

标签: python-2.7 pdf

我需要使用Python从pdf文件中提取页面数及其大小(以px / mm / cm / some-unit为单位)(不幸的是,因为它是一个遗留项目,所以为2.7)。问题在于文件可能真的很大(数百个MiB),因为它们将包含大图像。

我不在乎这些内容,我真的只希望从文件中获取页面大小的列表,并且尽可能少地消耗RAM。

我发现很多库可以做到这一点(包括但不限于答案here中的库),但是没有一个库提供有关内存使用的任何注释,我怀疑其中大多数-如果不是全部-在执行任何操作之前先读取内存中的整个文件,这不符合我的目的。

有没有只提取结构并提供我所需数据而又不会阻塞RAM的库?

2 个答案:

答案 0 :(得分:1)

pyvips可以做到这一点。当您打开PDF时,它会加载文件结构,而仅当您要求像素时才渲染每个页面。

例如:

#!/usr/bin/python

import sys
import pyvips

i = 0
while True:
    try:
        x = pyvips.Image.new_from_file(sys.argv[1], dpi=300, page=i)
        print("page =", i)
        print("width =", x.width)
        print("height =", x.height)
    except:
        break

    i += 1

libvips 8.7大约需要一周的时间,它添加了一个名为n-pages的新元数据项,可用于获取文档的长度。在此发布之前,尽管您只需要不断增加页码,直到遇到错误为止即可。

使用this PDF,当我运行程序时,我看到:

$ /usr/bin/time -f %M:%e ./sizes.py ~/pics/r8.pdf 
page = 0
width = 2480
height = 2480
page = 1
width = 2480
height = 2480
page = 2
width = 4960
height = 4960
...
page = 49
width = 2480
height = 2480
55400:0.19

因此它以0.2s的实时速度打开了50页,总峰值内存使用量为55mb。与py3一起使用,但也可以与py2一起使用。尺寸以像素为单位,像素为300 DPI。

如果将page设置为-1,它将把文档中的所有页面加载为一个非常高的图像。遗憾的是,所有页面的大小都必须相同。

答案 1 :(得分:0)

other answer的启发,我发现那里建议的libvips使用poppler(如果找不到poppler,它可以退回到其他库中)。

因此,我没有使用poppler,它具有多个Python库,而pyvips似乎对多种类型的文档都很有用,而没有使用它。我选择了pdflib,并提出了以下解决方案:

from sys import argv

from pdflib import Document


doc = Document(argv[1])
for num, page in enumerate(doc, start=1):
    print(num, tuple(2.54 * x / 72 for x in page.size))

2.54 * x / 72部分从px转换为cm

对264MiB文件进行速度和内存测试,每页一张大图像:

$ /usr/bin/time -f %M\ %e python t2.py big.pdf 
1 (27.99926666666667, 20.997333333333337)
2 (27.99926666666667, 20.997333333333337)
...
56 (27.99926666666667, 20.997333333333337)
21856 0.09

仅供参考,如果有人在寻找纯Python解决方案,我会提供here可用的粗略解决方案。没有经过全面测试,并且比这慢得多(上述速度大约30秒)。