А вот и подоспела версия на Python. Код работает для страниц любых размеров. Предварительно устанавливаем следующие пакеты:
sudo apt-get install python-reportlab python-pip
sudo pip2 install pypdf2
sudo pip2 install python-magic
#!/usr/bin/env python2
import argparse
import PyPDF2
import magic
import mimetypes
import os, sys
import StringIO
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from reportlab.lib.colors import HexColor
def is_pdf(path, check):
if check == 'lazy':
return is_pad_lazy(path)
else:
return is_pdf_trustworthy(path)
def is_pdf_lazy(path):
mime_type = mimetypes.guess_type(path)
if mime_type[0] and mime_type[0] == "application/pdf":
return True
return False
def is_pdf_trustworthy(path):
if is_pdf_lazy(path):
if 'PDF' in magic.from_file(path):
return True
return False
def make_list_pdfs_by(path, validate, recursive=False):
pdfs = []
for rootdir, dirs, filenames in os.walk(path):
full_filenames = [os.path.join(rootdir, filename).decode('utf-8') for filename in filenames]
pdfs.extend([full_filename for full_filename in full_filenames if is_pdf(full_filename, validate)])
if not recursive:
break
return pdfs
def make_overlay_pdf(watermark, position, font, fontsize, mediabox):
lowerLeft = (mediabox.lowerLeft[0].as_numeric(), mediabox.lowerLeft[1].as_numeric())
lowerRight = (mediabox.lowerRight[0].as_numeric(), mediabox.lowerRight[1].as_numeric())
upperLeft = (mediabox.upperLeft[0].as_numeric(), mediabox.upperLeft[1].as_numeric())
upperRight = (mediabox.upperRight[0].as_numeric(), mediabox.upperRight[1].as_numeric())
width_page = lowerRight[0] - lowerLeft[0]
height_page = upperLeft[1] - lowerLeft[1]
margin = {'top': 0.5*cm, 'right': 1*cm, 'bottom': 1*cm, 'left': 1*cm} # margin for top right bottom left in cm
packet = StringIO.StringIO()
canva = canvas.Canvas(packet, pagesize=(width_page, height_page))
canva.setFont(font, fontsize)
watermark_width = canva.stringWidth(watermark, font, fontsize)
canva.setFillColor(HexColor(0x0645AD))
if position == 'top-left':
x = upperLeft[0] + margin['left']
y = upperLeft[1] - margin['top'] - fontsize
elif position == 'top-right':
x = upperRight[0] - (margin['right'] + watermark_width)
y = upperRight[1] - margin['top'] - fontsize
elif position == 'bottom-left':
x = lowerLeft[0] + margin['left']
y = lowerLeft[1] + margin['bottom']
elif position == 'bottom-right':
x = lowerRight[0] - (margin['right'] + watermark_width)
y = lowerRight[1] + margin['bottom']
elif position == 'top-middle':
x = upperLeft[0] + (upperRight[0]-upperLeft[0])/2.0 - watermark_width/2.0
y = upperRight[1] - margin['top'] - fontsize
elif position == 'bottom-middle':
x = lowerLeft[0] + (lowerRight[0] - lowerLeft[0])/2.0 - watermark_width/2.0
y = lowerLeft[1] + margin['bottom']
canva.drawString(x, y, watermark)
canva.linkURL(watermark, (x, y, x+watermark_width, y+fontsize))
canva.save()
packet.seek(0)
return PyPDF2.PdfFileReader(packet)
def make_watermark(args):
watermark = args.watermark
position = args.pos_watermark
font = args.font
fontsize = int(args.fontsize)
for filename in make_list_pdfs_by(args.PDFs, args.validate, args.recursive):
existing_pdf = PyPDF2.PdfFileReader(file(filename, "rb"))
page = existing_pdf.getPage(0)
overlay_pdf = make_overlay_pdf(watermark, position, font, fontsize, page.mediaBox)
page.mergePage(overlay_pdf.getPage(0))
page.mergePage(overlay_pdf.getPage(0))
output_pdf = PyPDF2.PdfFileWriter()
output_pdf.appendPagesFromReader(existing_pdf)
outputStream = file(os.path.join(os.path.dirname(filename), args.prefix+'_'+os.path.basename(filename)), "wb")
output_pdf.write(outputStream)
outputStream.close()
print "Processing completed for %s" % (filename)
def parse_args():
parser = argparse.ArgumentParser(usage="%s -w https://forum.ubuntu.ru [-i ~/docs] [-f Times-Roman] "
"[-s 24] [-p (top-left|top-middle|top-right|bottom-left|bottom-middle|bottom-right)] "
"[-r] [--prefix your_prefix] [--validate trustworthy]" % (os.path.basename(sys.argv[0])))
parser.add_argument("-i", "--input", action="store", dest="PDFs", default=".")
parser.add_argument("-w", "--watermark", action="store", dest="watermark", required=True)
parser.add_argument("-s", "--font-size", action="store", dest="fontsize", default="18")
parser.add_argument("-f", "--font", action="store", dest="font", default="Times-Roman")
parser.add_argument("-p", "--position", action="store", dest="pos_watermark",
metavar="position watermark", choices=["top-left", "top-middle", "top-right", "bottom-left", "bottom-middle", "bottom-right"], default='top-left')
parser.add_argument("-r", "--recursive", action="store_true", dest="recursive", default=False)
parser.add_argument("--prefix", action="store", dest="prefix", default="overlayed")
parser.add_argument("--validate", action="store", dest="validate", choices=['lazy', 'trustworthy'], default='lazy')
return parser.parse_args()
if __name__ == "__main__":
args = parse_args()
make_watermark(args)
Пример использования:
./overlaylink2pdf.py -w
https://forum.ubuntu.ru -f Times-Roman -s 24 -p top-middle -i /path/to/pdf/ -r --prefix myprefix --validate trustworthy
Опции такие:
-w/--watermark - задает внешнюю ссылку (опция обязательна)
-f/--font - шрифт (укзывать необязательно, по умолчанию используется шрифт Times-Roman)
-s/--font-size - размер шрифта (указывать необязательно, по умолчанию 18 пт.)
-p/--position - позиция ссылки на странице; допускаются следующие значения - top-left, top-middle, top-right, bottom-left, bottom-middle, bottom-right. (указывать необязательно; по умолчанию top-left)
-i/--input - каталог с документами pdf (указывать необязательно; по умолчанию используется текущий каталог)
-r/--recursive - рекурсивно обработать каталог, заданный в опции -i (указывать необязательно; по умолчанию используется нерекурсивная обработка)
--prefix - задает префикс для имен обработанных документов (указывать необязательно, по умолчанию overlayed)
Цвет ссылки (задается как триада однобайтных чисел в шестнадцатеричном формате), а также отступы сверху, снизу, слева, справа (в сантиметрах) можно задать в самом скрипте (лень было выносить в параметры).
--validate - задает способ проверки истинности pdf-файла ("ленивый" и "надежный"); по умолчанию используется ленивая проверка. "Ленивая" проверка основа на проверке MIME-типа по расширению файла, что увеличивает быстродействие и снижает надежность проверки. Таким образом, при ленивой проверке любой файл, созданный командой touch myfile.pdf, будет считаться истинным pdf-файлом, что приведет к необработанному исключению. "Надежный" способ основан на проверке magic number файла, что увеличивает надежность при небольшом снижении производительности.
UPDATE: были устранены ошибки в работе опции --validate и устранены проблемы при обработке файлов, чьи имена содержат кириллицу.
P.S. Дико извиняюсь за очень грубый код.