如何使用命令行工具批量处理 pdf 中的每个图像?

jos*_*sch 5 linux pdf batch command-line images

是否存在适用于 Linux 的命令行工具,它允许我从 PDF 中提取所有 /Subtype /Image 光栅图像对象,允许我使用另一个 3rd 方工具处理它们,然后能够将它们重新插入原始 PDF?

Debian 软件包 poppler-utils 带来了 pdfimages 工具,它允许我从 PDF 中提取所有图像,但在更改它们后我无法轻松地将它们重新插入 PDF。

我之前为 PDF 编写了简单的解析器,所以我目前对这个问题的看法是

  1. 在 PDF 上运行 pdfclean(来自 mupdf 包)以解压缩所有流,从而使解析更容易
  2. 用一个简单的解析器解析 pdf(当然这将无法解析大多数 PDF,但只要它适用于我的 PDF 我很高兴)并将所有图像提取为位图,并在其名称中包含对象 id
  3. 使用 3rd 方程序在图像上做一些 foo
  4. 再次解析原始 pdf,但这次用修改后的图像替换里面的图像,根据需要调整 /Length 和 /Filter
  5. 再次运行 pdfclean 以更正外部参照表中的所有偏移

但也许一个允许所有这些并且不限于我编写的简单解析器的功能的工具已经存在?

如果你说这样的工具不存在,那么告诉我一个允许提取和稍后替换图像的库也是可以的。

tra*_*rax 5

您可以尝试在命令行中使用inkscape

inkscape -S # show all the object inside  the document
inkscape --select=YouImage --verb=YourTransformation 
inkscape --verb-list #to obtain all the possibilities
Run Code Online (Sandbox Code Playgroud)

或者你可以提取图像,用你想要的任何东西修改它们(imagemagick?),然后在你的文档中用inkscape替换它们。

问候


jos*_*sch 5

这似乎(还)不可能在命令行中执行,但我找到了一种使用pdfrw python 模块在 python 中编写脚本的简单方法,如下所示:

#!/usr/bin/env python
import sys
import os
import zlib
import Image
import StringIO

from pdfrw import PdfReader, PdfDict, PdfArray, PdfName, PdfWriter

def process_image(image):
    if image["/Filter"] == PdfName("FlateDecode"):
        pass
    elif image["/Filter"] == PdfName("DCTDecode"):
        im = Image.open(StringIO.StringIO(image.stream))
        outf = StringIO.StringIO()
        im.save(outf, "JPEG", quality=45)
        image.stream = outf.getvalue()
        outf.close()

def find_images(obj, visited=set()):
    if not isinstance(obj, (PdfDict, PdfArray)):
        return
    myid = id(obj)
    if myid in visited:
        return
    visited.add(myid)

    if isinstance(obj, PdfDict):
        if obj.Type == PdfName.XObject and obj.Subtype == PdfName.Image:
            process_image(obj)
        obj = obj.itervalues()

    for item in obj:
        find_images(item, visited)

if __name__ == '__main__':
    inpfn,outfn = sys.argv[1:]
    reader = PdfReader(inpfn)
    find_images(reader)
    PdfWriter().addpages(reader.pages).write(outfn)
Run Code Online (Sandbox Code Playgroud)

您可以在process_images函数中实现您想要的任何内容,甚至可以轻松完成诸如调用外部程序来修改当前图像之类的复杂事情。在本例中,我们仅使用 PIL 对质量为 45 的 jpeg 图像进行重新编码。