106 lines
3.3 KiB
Python
Executable File
106 lines
3.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
'''
|
|
Enhanced example of watermarking using form xobjects (pdfrw).
|
|
|
|
usage: fancy_watermark.py [-u] my.pdf single_page.pdf
|
|
|
|
Creates watermark.my.pdf, with every page overlaid with
|
|
first page from single_page.pdf. If -u is selected, watermark
|
|
will be placed underneath page (painted first).
|
|
|
|
The stock watermark.py program assumes all pages are the same
|
|
size. This example deals with pages of differing sizes in order
|
|
to show some concepts of positioning and scaling.
|
|
|
|
This version applies the watermark such that the upper right
|
|
corner of the watermark is at the upper right corner of the
|
|
document page for odd pages, and at the upper left corner
|
|
of the document page for even pages, for each page of the
|
|
document.
|
|
|
|
It also rescales the size of the watermark if the watermark
|
|
is too wide for the page.
|
|
|
|
These scaling and positioning adjustments can easily
|
|
be customized for any particular application.
|
|
|
|
To handle documents with different page sizes, a cache is
|
|
maintained of a modified intermediate watermark object
|
|
for each page size.
|
|
'''
|
|
|
|
import sys
|
|
import os
|
|
|
|
from pdfrw import PdfReader, PdfWriter, PageMerge
|
|
|
|
# Get all the filenames
|
|
|
|
argv = sys.argv[1:]
|
|
underneath = '-u' in argv
|
|
if underneath:
|
|
del argv[argv.index('-u')]
|
|
inpfn, wmarkfn = argv
|
|
outfn = 'watermark.' + os.path.basename(inpfn)
|
|
|
|
# Open both the source files
|
|
wmark_trailer = PdfReader(wmarkfn)
|
|
trailer = PdfReader(inpfn)
|
|
|
|
# Handle different sized pages in same document with
|
|
# a memoization cache, so we don't create more watermark
|
|
# objects than we need to (typically only one per document).
|
|
|
|
wmark_page = wmark_trailer.pages[0]
|
|
wmark_cache = {}
|
|
|
|
# Process every page
|
|
for pagenum, page in enumerate(trailer.pages, 1):
|
|
|
|
# Get the media box of the page, and see
|
|
# if we have a matching watermark in the cache
|
|
mbox = tuple(float(x) for x in page.MediaBox)
|
|
odd = pagenum & 1
|
|
key = mbox, odd
|
|
wmark = wmark_cache.get(key)
|
|
if wmark is None:
|
|
|
|
# Create and cache a new watermark object.
|
|
wmark = wmark_cache[key] = PageMerge().add(wmark_page)[0]
|
|
|
|
# The math is more complete than it probably needs to be,
|
|
# because the origin of all pages is almost always (0, 0).
|
|
# Nonetheless, we illustrate all the values and their names.
|
|
|
|
page_x, page_y, page_x1, page_y1 = mbox
|
|
page_w = page_x1 - page_x
|
|
page_h = page_y1 - page_y # For illustration, not used
|
|
|
|
# Scale the watermark if it is too wide for the page
|
|
# (Could do the same for height instead if needed)
|
|
if wmark.w > page_w:
|
|
wmark.scale(1.0 * page_w / wmark.w)
|
|
|
|
# Always put watermark at the top of the page
|
|
# (but see horizontal positioning for other ideas)
|
|
wmark.y += page_y1 - wmark.h
|
|
|
|
# For odd pages, put it at the left of the page,
|
|
# and for even pages, put it on the right of the page.
|
|
if odd:
|
|
wmark.x = page_x
|
|
else:
|
|
wmark.x += page_x1 - wmark.w
|
|
|
|
# Optimize the case where the watermark is same width
|
|
# as page.
|
|
if page_w == wmark.w:
|
|
wmark_cache[mbox, not odd] = wmark
|
|
|
|
# Add the watermark to the page
|
|
PageMerge(page).add(wmark, prepend=underneath).render()
|
|
|
|
# Write out the destination file
|
|
PdfWriter(outfn, trailer=trailer).write()
|