5

Does there exist a commandline tool for Linux which allows me to extract all /Subtype /Image raster image objects from a PDF, allows me to process them using another 3rd party tool and then is able to reinsert them into the original PDF?

The Debian package poppler-utils brings the tool pdfimages which allows me to extract all images from a PDF but I can't easily re-insert them into the PDF after I changed them.

I wrote simple parsers for PDF before so my current take on this problem would be to

  1. run pdfclean (from the mupdf package) on the PDF to decompress all streams and thus make parsing easier
  2. parse the pdf with a simple parser (surely this will not be able to parse most PDF but as long as it works for my PDF I'm happy) and extract all images as bitmaps with the object id in their name
  3. do some foo on the images using a 3rd party program
  4. parse the original pdf again but this time replace the images inside with the modified ones, adapting the /Length and /Filter as necessary
  5. run pdfclean again to correct all offsets in the xref table

But maybe a tool which allows all this and is not limited to the capabilties of a simple parser written by me already exists?

If you say such a tool does not exist, then it is also okay to tell me a library which allows to extract and later replace images.

2 Answers 2

5

you can try to use inkscape in command line

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

Or you can extract image, modify them with anything you want (imagemagick?) then replace them in your document with inkscape.

Regards

2
  • Yes, I can freely edit PDFs and replace images in them using inkscape and many other free and non-free tools. But they all only allow me to manually select and modify images not to automatically batch process all pages and all images inside.
    – josch
    Jul 3, 2013 at 15:41
  • 1
    Cool; didn't know that inkscape has such non-GUI capabilities. But in my case I have to wait till inkscape allows to choice a certain page from the input file via command line.
    – u_Ltd.
    Jul 5, 2017 at 12:07
5

It seems this is not (yet) possible to do in the commandline but I found an easy way to script it in python using the pdfrw python module like this:

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

You can potentially implement whatever you want in the process_images function and even complicated things like calling external programs to modify the current image can easily be done. In this example we just use PIL to reencode jpeg images with a quality of 45.

2
  • Works for my project with some adaptions: main point is that rasterized images use FlateDecode in my file. I guess in your files as well - that's the reason for importing zlib, am I right?
    – u_Ltd.
    Jul 5, 2017 at 12:05
  • Indeed that is a leftover import zlib from when I used the code to work with FlateDecode images. If you like, feel free to suggest how the demo code could be extended to be more useful.
    – josch
    Jul 5, 2017 at 15:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .