将图像放置在PDF上方

36

我该如何在PDF文件的特定坐标位置放置一张图像呢?这个PDF文件表示一张绘图纸,只有一页。图片将被缩放。我正在查看ReportLab,但找不到答案。谢谢。


图片是否总是出现在相同的位置? - Graham Chiu
是的,基本上它就是位于左下角附近的一个印章。 - Eric Acevedo
以下答案是否足够?如果不是,那么它有什么问题? - theheadofabroom
4
有没有办法在特定的坐标上放置图片(如png,jpg,gif)?还是唯一的解决方案是将两个pdf合并在一起? - Auston
6个回答

53

已经过去了5年,我认为这些答案需要一些关爱。下面是完整的解决方案。

以下内容经过Python 2.7测试

安装依赖项

pip install reportlab 
pip install pypdf2

施展魔法

from reportlab.pdfgen import canvas
from PyPDF2 import PdfFileWriter, PdfFileReader

# Create the watermark from an image
c = canvas.Canvas('watermark.pdf')

# Draw the image at x, y. I positioned the x,y to be where i like here
c.drawImage('test.png', 15, 720)

# Add some custom text for good measure
c.drawString(15, 720,"Hello World")
c.save()

# Get the watermark file you just created
watermark = PdfFileReader(open("watermark.pdf", "rb"))

# Get our files ready
output_file = PdfFileWriter()
input_file = PdfFileReader(open("test2.pdf", "rb"))

# Number of pages in input document
page_count = input_file.getNumPages()

# Go through all the input file pages to add a watermark to them
for page_number in range(page_count):
    print "Watermarking page {} of {}".format(page_number, page_count)
    # merge the watermark with the page
    input_page = input_file.getPage(page_number)
    input_page.mergePage(watermark.getPage(0))
    # add page from input file to output document
    output_file.addPage(input_page)
   
# finally, write "output" to document-output.pdf
with open("document-output.pdf", "wb") as outputStream:
    output_file.write(outputStream)

参考资料:

pypdf 项目页面: https://pypi.org/project/pypdf/

Reportlab 文档: http://www.reportlab.com/apis/reportlab/2.4/pdfgen.html

Reportlab 完整用户指南: https://www.reportlab.com/docs/reportlab-userguide.pdf


3
在更新答案时,pdfrw库可以像之前提到的PyPDF2一样进行水印处理,而且它还可以实现相反的功能 - 允许您在使用reportlab创建的PDF中将预先存在的PDF作为图像使用(而不需光栅化)。声明:我是pdfrw作者。 - Patrick Maupin
@PatrickMaupin 你能否使用pdfrw的现成答案?这将非常有用。 - Basj
@PatrickMaupin pdfrw 可以从一个使用 png 或 jpeg 文件并在特定坐标处添加水印的示例中受益匪浅。目前是否已经实现了这个功能? - DrMaxB

29

https://pypi.org/project/pypdf/:

from pypdf import PdfWriter, PdfReader

writer = PdfWriter()
reader = PdfReader("document1.pdf")
watermark = PdfReader("watermark.pdf")

page = reader.pages[0]
page.merge_page(watermark.pages[0])
writer.add_page(page)

# finally, write the results to disk
with open("document-output.pdf", "wb") as fp:
    writer.write(fp)

我认为它类似于水印,详细信息请查看文档


谢谢,它很好用,我只是查看了文档中的PdfFileReader.getPage()和PdfFileWriter.addPage()方法。 - Eric Acevedo
看起来PyPdf不再维护,也没有宣布的继承者网站。从长远来看还有什么其他解决方案? - lalebarde
5
page4来自哪里? - Ethan Furman
2
@lalebarde: PyPDF2 是其后继者。 - Ethan Furman
我是pypdf和PyPDF2的维护者。该项目将继续使用pypdf :-) - Martin Thoma

14
我将ReportLabpypdf<3.0.0结合起来,直接插入图像,而无需先生成PDF。
from pyPdf import PdfFileWriter, PdfFileReader
from reportlab.pdfgen import canvas
from StringIO import StringIO


# Using ReportLab to insert image into PDF
imgTemp = StringIO()
imgDoc = canvas.Canvas(imgTemp)

# Draw image on Canvas and save PDF in buffer
imgPath = "path/to/img.png"
imgDoc.drawImage(imgPath, 399, 760, 160, 160)    ## at (399,760) with size 160x160
imgDoc.save()

# Use PyPDF to merge the image-PDF into the template
page = PdfFileReader(file("document.pdf","rb")).getPage(0)
overlay = PdfFileReader(StringIO(imgTemp.getvalue())).getPage(0)
page.mergePage(overlay)

#Save the result
output = PdfFileWriter()
output.addPage(page)
output.write(file("output.pdf","w"))

6
感谢之前的回答。我使用Python 3.4和PyPDF2<3.0.0这个库来解决问题。
# -*- coding: utf-8 -*-
from io import BytesIO
from PyPDF2 import PdfFileWriter, PdfFileReader
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4

def gen_pdf():
    # there are 66 slides (1.jpg, 2.jpg, 3.jpg...)
    path = 'slades/{0}.jpg'
    pdf = PdfFileWriter()

    for num in range(1, 67):  # for each slide
        # Using ReportLab Canvas to insert image into PDF
        imgTemp = BytesIO()
        imgDoc = canvas.Canvas(imgTemp, pagesize=A4)
        # Draw image on Canvas and save PDF in buffer
        imgDoc.drawImage(path.format(num), -25, -45)
        # x, y - start position
        # in my case -25, -45 needed
        imgDoc.save()
        # Use PyPDF to merge the image-PDF into the template
        pdf.addPage(PdfFileReader(BytesIO(imgTemp.getvalue())).getPage(0))

    pdf.write(open("output.pdf","wb"))


if __name__ == '__main__':
    gen_pdf()

5

使用PyMuPDF很容易做到在不合并两个PDF的情况下完成此操作:

import fitz

src_pdf_filename = 'source.pdf'
dst_pdf_filename = 'destination.pdf'
img_filename = 'barcode.jpg'

# http://pymupdf.readthedocs.io/en/latest/rect/
# Set position and size according to your needs
img_rect = fitz.Rect(100, 100, 120, 120)

document = fitz.open(src_pdf_filename)

# We'll put image on first page only but you could put it elsewhere
page = document[0]
page.insertImage(img_rect, filename=img_filename)

# See http://pymupdf.readthedocs.io/en/latest/document/#Document.save and
# http://pymupdf.readthedocs.io/en/latest/document/#Document.saveIncr for
# additional parameters, especially if you want to overwrite existing PDF
# instead of writing new PDF
document.save(dst_pdf_filename)

document.close()

@j-owens - 我一直在使用Rect构造函数时遇到问题。似乎坐标不正确,只能倒置插入图像。 - atm
1
原点(0, 0)位于左上角,不同于其他一些库可能从左下角开始(尽管我遇到过一些具有奇怪原点的PDF文件)。我想知道您是否颠倒了y坐标。 - J. Owens
我已经尝试过了,但它不起作用。有什么想法为什么会这样?看起来很整洁! - Dusan J.
在较新版本的PyMuPDF中,驼峰命名法已被替换为蛇形命名法,并且page.insertImage应改为page.insert_image。将此添加给其他尝试上述示例(如我所做)的人。 - most200

0

这是对我有效的

from PyPDF2 import PdfFileWriter, PdfFileReader

def watermarks(temp, watermar,new_file):
    template = PdfFileReader(open(temp, 'rb'))
    wpdf = PdfFileReader(open(watermar, 'rb'))
    watermark = wpdf.getPage(0)

    for i in xrange(template.getNumPages()):
        page = template.getPage(i)
        page.mergePage(watermark)
        output.addPage(page)

        with open(new_file, 'wb') as f:
            output.write(f)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接