Add Text/String to PDF with pikepdf

1.2k Views Asked by At

I'd like to add a text/string at a specific position to each page to an existing PDFs (multiple pages) in "PDF/A-1b" standard.

I've read the documentation but I can't work it out (probably do not understand it enough so far) how to use streams and how to create the XObject.


Is there a small working example how to add a new string?

It can be an overlay, can be just another content element.


This one doesn't work, since I just created a pikepdf string object, no XObject, which leads to:

TypeError: other object is not something we can convert to Form XObject

    import pikepdf

    file_name ="example.pdf"
    print(f"Current file: {file_name}")
    
    pdf = pikepdf.Pdf.open(file_dict[each_pdf]["path"])
    print("Number of pages:", len(pdf.pages))
    some_text = pikepdf.objects.String('Some date like 20220629')

    destination_page = pikepdf.Page(pdf.pages[0])
    
    destination_page.add_overlay(some_text, pikepdf.Rectangle(0, 0, 300, 300))
    pdf.save("example_with_text.pdf")
    pdf.close()
1

There are 1 best solutions below

0
On

Ok, got it. I've read about a way to 'stamp' the same object to all pages - couldn't find it again.

This solution fits my problem:

from io import BytesIO
import pikepdf
from reportlab.pdfgen import canvas

def generate_stamp(msg, xy):
    x, y = xy
    buf = BytesIO()
    c = canvas.Canvas(buf, bottomup=0)
    c.setFontSize(16)
    c.setFillColorCMYK(0, 0, 0, 0, alpha=0.7)
    c.rect(194, 5, 117, 17, stroke=1, fill=1)
    c.setFillColorCMYK(0, 0, 0, 100, alpha=0.7)
    c.drawString(x, y, msg)
    c.save()
    buf.seek(0)
    return buf

stamp = generate_stamp('SOME TEXT', (200, 20))

with pikepdf.open('[Path to in]/in.pdf') as pdf_orig, pikepdf.open(stamp) as pdf_text:
    formx_text = pdf_orig.copy_foreign(pdf_text.pages[0].as_form_xobject())
    
    for i in range(len(pdf_orig.pages)):
        formx_page = pdf_orig.pages[i]
        formx_name = formx_page.add_resource(formx_text, pikepdf.Name.XObject)    
        stamp_text = pdf_orig.make_stream(b'q 1 0 0 1 0 0 cm %s Do Q' % formx_name)
        
        pdf_orig.pages[i].contents_add(stamp_text)

    pdf_orig.save('[Path to out]/out.pdf')

Wasn't me though, it's just a small adaption of an example from jbarlow83 himself.

If there're ways to improve it, please let me know.