How to create a PDF document from a batch of images ?


Belowis what I tried before posting this question:

The ImageMagick way, but the PDF document generated is too big:

convert *.ppm book.pdf

The Preview tool way, the created document is much smaller but it creates margins.

The sips way, not working for some reason:

sips -s format pdf *.ppm --out 'book.pdf' 1>/dev/null 2>&1

There also img2pdf which looks good but I couldn't install it on mac (it's not in brew's list of packages).

  • Automator has a "create PDF from images" action (and one to compress images within PDFs).
    – nohillside
    Jan 3, 2019 at 8:55
  • Have you considered converting the .ppm files to jpegs or something similar then working with regular image files?
    – Natsfan
    Jan 3, 2019 at 16:17
  • sips may not work on ppm files.
    – Natsfan
    Jan 3, 2019 at 16:21

1 Answer 1


Apple's own Automator action uses a python script to access Core Graphics. It works, but it's slow. Here's a better python script which uses Apple's newer PDFKit framework.

You can use this from the Terminal with filenames as arguments, or you can stick it in an Automator Run Shell Script Action.

No installations or dependencies.

# coding: utf-8
# IMAGE2PDF v.2.0 : Convert image files to one PDF.
# by Ben Byram-Wigfield 

import sys, os
import Quartz as Quartz
from LaunchServices import kUTTypePDF
from CoreFoundation import NSImage

def getFilename(filepath, basename):
    fullname = basename + ".pdf"
    while os.path.exists(os.path.join(filepath, fullname)):
        i += 1
        fullname = basename + " %02d.pdf"%i
    return os.path.join(filepath, fullname)

def imageToPdf(argv):
    prefix = os.path.dirname(argv[0]) 
    filename = "Combined"
    pdfout = getFilename(prefix, filename)

    for index, eachFile in enumerate(argv):
        image = NSImage.alloc().initWithContentsOfFile_(eachFile)
        if image:
            page = Quartz.PDFPage.alloc().initWithImage_(image)
            if index == 0:
                pageData = page.dataRepresentation()
                pdf = Quartz.PDFDocument.alloc().initWithData_(pageData)
                pdf.insertPage_atIndex_(page, index)


if __name__ == "__main__":

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