8

I'm using PdfPages from matplotlib and I can loop through each figure object and save each one as a separate page in the same PDF:

from matplotlib.backends.backend_pdf import PdfPages
pp = PdfPages('output.pdf')
for fig in figs:
    pp.savefig(fig)
pp.close()

This works great. But is there a way for me to add a page number for each page in the PDF?

Thanks.

mortada
  • 1,518
  • 1
  • 12
  • 12
  • I don't know of any direct way to do it, here's a brief outline of another possible solution. Save the plot as an image, insert the image into a word document, add pages to the word doc, then save it as a pdf. Its a little roundabout, but if you think this might be a good way to go let me know and I can flush it out into an actual answer – wnnmaw Aug 06 '14 at 15:56
  • I need to do this once a day with a lot of images, so I'd really need an automated way – mortada Aug 06 '14 at 20:27
  • 2
    It could be automated, but maybe look into [this question](http://stackoverflow.com/questions/1180115/add-text-to-existing-pdf-using-python) to work with the pdf directly – wnnmaw Aug 06 '14 at 20:40

4 Answers4

7

A nice solution using reportlib and PyPDF (base on this):

from reportlab.lib.units import mm
from reportlab.pdfgen import canvas
import os
from PyPDF4.pdf import PdfFileReader, PdfFileWriter


def createPagePdf(num, tmp):
    c = canvas.Canvas(tmp)
    for i in range(1, num + 1):
        c.drawString((210 // 2) * mm, (4) * mm, str(i))
        c.showPage()
    c.save()


def add_page_numgers(pdf_path):
    """
    Add page numbers to a pdf, save the result as a new pdf
    @param pdf_path: path to pdf
    """
    tmp = "__tmp.pdf"

    output = PdfFileWriter()
    with open(pdf_path, 'rb') as f:
        pdf = PdfFileReader(f, strict=False)
        n = pdf.getNumPages()

        # create new PDF with page numbers
        createPagePdf(n, tmp)

        with open(tmp, 'rb') as ftmp:
            numberPdf = PdfFileReader(ftmp)
            # iterarte pages
            for p in range(n):
                page = pdf.getPage(p)
                numberLayer = numberPdf.getPage(p)
                # merge number page with actual page
                page.mergePage(numberLayer)
                output.addPage(page)

            # write result
            if output.getNumPages():
                newpath = pdf_path[:-4] + "_numbered.pdf"
                with open(newpath, 'wb') as f:
                    output.write(f)
        os.remove(tmp)
ofir dubi
  • 523
  • 2
  • 6
  • 13
5

Something like this:

from matplotlib.backends.backend_pdf import PdfPages
pp = PdfPages('output.pdf')
for n, fig in enumerate(figs):
    fig.text(4.25/8.5, 0.5/11., str(n+1), ha='center', fontsize=8)
    pp.savefig(fig)
pp.close()
Steve Schulist
  • 831
  • 1
  • 10
  • 16
1

Either PyPDF2 or pdfrw will let you overlay two PDFs (so, for example, you can generate a PDF which is only page numbers, and use it to watermark your images). pdfrw has a watermark example that uses a single watermark page, but this could easily be modified to use a set of watermark pages, one for each page number.

If you want to get fancier, you can use reportlab to generate these pages on the fly.

pdfrw also has a facility that allows you to import a PDF page into reportlab as if it were an image. There are a couple of examples around that do this dynamically -- here is a good starting point.

Finally, rst2pdf (which is not all that well maintained but works well for simple cases) also lets you import PDFs as images -- it uses pdfrw and reportlab under the hood -- so you can easily use restructuredText to create documents with your images embedded. AFAIK, the best reportlab to use with the released version of rst2pdf is 2.7.

(Disclaimer: I am the pdfrw author and have made contributions to rst2pdf.)

Community
  • 1
  • 1
Patrick Maupin
  • 7,761
  • 2
  • 22
  • 42
1

Use numbering2pdf library.

from numbering2pdf import add_numbering_to_pdf

add_numbering_to_pdf("old_file.pdf", "new_file.pdf")