python - Python/wand 代码在转换大型 PDF 时导致“Killed”
问题描述
我一直在努力使用 Python 3.6.3 和 wand 库设置 PDF 转换为 png 和裁剪脚本。
我试过枕头,但它缺少转换部分。我正在尝试提取 alpha 通道,因为我想稍后将图像提供给 OCR,所以我转向尝试这个 SO answer中提供的代码。
出现了几个问题:第一个是如果文件很大,我会从终端收到一条“Killed”消息。第二个是文件看起来相当挑剔,即通过命令行中的 imagemagick 的 convert 或 pdftoppm 正确转换的文件,使用 wand 会引发错误。
不过,我最关心的是第一个,并且非常感谢知识渊博的编码人员的检查。我怀疑它可能来自循环的结构方式:
from wand.image import Image
from wand.color import Color
def convert_pdf(filename, path, resolution=300):
all_pages = Image(filename=path+filename, resolution=resolution)
for i, page in enumerate(all_pages.sequence):
with Image(page) as img:
img.format = 'png'
img.background_color = Color('white')
img.alpha_channel = 'remove'
image_filename = '{}.png'.format(i)
img.save(filename=path+image_filename)
我注意到脚本在进程结束时输出所有文件,而不是一个一个地输出,我猜这可能会给内存带来不必要的负担,并最终导致 SEGFAULT 或类似的东西。
感谢您查看我的问题以及任何提示。
解决方案
是的,您的线路:
all_pages = Image(filename=path+filename, resolution=resolution)
将启动 GhostScript 进程以将整个 PDF 渲染为/tmp
. 然后,Wand 会将那个庞大的文件加载到内存中,并在循环时从中分发页面。
MagickCore 的 C API 允许您指定要加载的页面,因此您可以一次渲染一个页面,但我不知道如何让 Python wand 接口来执行此操作。
你可以试试pyvips。它通过直接调用libpoppler以增量方式呈现 PDF ,因此没有正在启动和停止的进程,也没有临时文件。
例子:
#!/usr/bin/python3
import sys
import pyvips
def convert_pdf(filename, resolution=300):
# n is number of pages to load, -1 means load all pages
all_pages = pyvips.Image.new_from_file(filename, dpi=resolution, n=-1, \
access="sequential")
# That'll be RGBA ... flatten out the alpha
all_pages = all_pages.flatten(background=255)
# the PDF is loaded as a very tall, thin image, with the pages joined
# top-to-bottom ... we loop down the image cutting out each page
n_pages = all_pages.get("n-pages")
page_width = all_pages.width
page_height = all_pages.height / n_pages
for i in range(0, n_pages):
page = all_pages.crop(0, i * page_height, page_width, page_height)
print("writing {}.tif ..".format(i))
page.write_to_file("{}.tif".format(i))
convert_pdf(sys.argv[1])
在这台带有巨大 PDF的 2015 年笔记本电脑上,我看到:
$ /usr/bin/time -f %M:%e ../pages.py ~/pics/Audi_US\ R8_2017-2.pdf
writing 0.tif ..
writing 1.tif ..
....
writing 20.tif ..
720788:35.95
因此以 300dpi 渲染整个文档需要 35 秒,峰值内存使用量为 720MB。
推荐阅读
- php - 日期未在数据表中提交
- javascript - AdminLTE 与 React 和 JQuery 的集成在我刷新几次之前无法工作
- bash - 如果没有获得任何流更新,如何停止 ffmpeg m3u8 下载?
- cassandra - CosmosDB Cassandra API - 在查询中选择抛出异常
- python - 我们在 keras 聊天机器人中使用推理模型的原因是什么?
- javascript - React Hooks/上下文和弹性 UI。函数组件中获取数据 (REST) 的问题
- node.js - 无法将数据从 node.js 存储到 mongoDB atlas 下面是代码片段
- oracle - 检查是否使用 FORCE 选项创建了视图
- laravel - 在 Laravel 项目中将 .doc 转换为 .pdf 的更好方法?
- sql - SQL 函数在上半月(1 到 15)和下半月(16 到 30/31)之间分割日期