Como processar em lote todas as imagens em um pdf usando ferramentas de linha de comando?

5

Existe uma ferramenta de linha de comando para Linux que permite extrair todos os objetos de imagem rasterizados / Subtype / Image de um PDF, permite processá-los usando outra ferramenta de terceiros e, em seguida, reinseri-los no PDF original?

O pacote Debian poppler-utils traz a ferramenta pdfimages que me permite extrair todas as imagens de um PDF, mas não posso reinseri-las facilmente no PDF depois de alterá-las.

Eu escrevi parsers simples para PDF antes, então minha opinião atual sobre esse problema seria

  1. execute pdfclean (do pacote mupdf) no PDF para descompactar todos os fluxos e, assim, tornar a análise mais fácil
  2. analise o pdf com um simples analisador (certamente isso não será capaz de analisar a maioria dos PDFs, mas contanto que funcione para meu PDF, estou feliz) e extraia todas as imagens como bitmaps com o id do objeto em seu nome
  3. faça algumas imagens nas imagens usando um programa de terceiros
  4. analise o pdf original novamente, mas desta vez substitua as imagens internas por modificadas, adaptando o / Length e / Filter conforme necessário
  5. execute o pdfclean novamente para corrigir todos os deslocamentos na tabela de refexs

Mas talvez exista uma ferramenta que permita tudo isso e não esteja limitada às capacidades de um simples analisador escrito por mim?

Se você disser que tal ferramenta não existe, então não há problema em me dizer uma biblioteca que permite extrair e depois substituir imagens.

    
por josch 02.07.2013 / 22:22

2 respostas

5

Parece que isso não é (ainda) possível de fazer na linha de comando, mas eu achei uma maneira fácil de fazer o script em python usando o módulo python pdfrw assim:

#!/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)

Você pode implementar o que quiser na função process_images e até coisas complicadas como chamar programas externos para modificar a imagem atual podem ser facilmente executadas. Neste exemplo, usamos apenas o PIL para reencodificar imagens jpeg com uma qualidade de 45.

    
por 19.12.2013 / 23:48
4

você pode tentar usar o inkscape na linha de comando

inkscape -S # show all the object inside  the document
inkscape --select=YouImage --verb=YourTransformation 
inkscape --verb-list #to obtain all the possibilities

Ou você pode extrair uma imagem, modificá-la com o que quiser (imagemagick?)  em seguida, substitua-os em seu documento pelo inkscape.

Atenciosamente

    
por 03.07.2013 / 13:14