将图像放在 PDF 上

Posted

技术标签:

【中文标题】将图像放在 PDF 上【英文标题】:Place image over PDF 【发布时间】:2011-02-24 21:52:56 【问题描述】:

如何将图像放置在特定坐标位置的现有 PDF 文件上。 pdf 代表一页的图纸。图像将被缩放。我正在检查 ReportLab,但找不到答案。谢谢。

【问题讨论】:

图片总是出现在同一个位置吗? 是的,基本就是左下角附近的邮票。 下面的答案够吗?如果不是,那它有什么问题? 有没有办法在上面放一张图片(比如 png、jpg、gif)?在特定坐标?还是将 2 个 pdf 混合在一起的唯一解决方案? 【参考方案1】:

已经 5 年了,我认为这些答案需要一些 TLC。这是一个完整的解决方案。

以下是用 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的新家: http://mstamy2.github.io/PyPDF2/

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

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

【讨论】:

当您更新答案时,pdfrw 库也可以以非常相似的方式watermark,也可以采用另一种方式——允许您使用 pre-现有的 PDF 就好像它们是您 build with reportlab 的 PDF 中的图像(没有光栅化它们)。免责声明:我是pdfrw作者... @PatrickMaupin 您可以使用 pdfrw 的现成答案吗?这将非常有用。 @PatrickMaupin pdfrw 可以从使用 png 或 jpeg 文件并在特定坐标处添加水印的水印示例中受益匪浅。目前可以吗?【参考方案2】:

http://pybrary.net/pyPdf/:

from pyPdf import PdfFileWriter, PdfFileReader

output = PdfFileWriter()
input1 = PdfFileReader(file("document1.pdf", "rb"))
watermark = PdfFileReader(file("watermark.pdf", "rb"))

input1.mergePage(watermark.getPage(0))

# finally, write "output" to document-output.pdf
outputStream = file("document-output.pdf", "wb")
output.write(input1)
outputStream.close()

我认为它就像watermark,请参阅手册以获得更好的想法

【讨论】:

感谢它运行良好,刚刚检查了文档中的 PdfFileReader.getPage() 和 PdfFileWriter.addPage() 方法。 似乎 PyPdf 不再维护,宣布的延续站点也不再维护。从长远来看,还有什么其他解决方案? page4 是从哪里来的? @lalebarde: PyPDF2 是继任者。【参考方案3】:

我结合了 ReportLab (http://www.reportlab.com/software/opensource/rl-toolkit/download/) 和 pyPDF (http://pybrary.net/pyPdf/) 直接插入图像而无需预先生成 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"))

【讨论】:

【参考方案4】:

感谢之前的答案。 python3.4 我的方式

# -*- 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 构造函数的问题。坐标好像不能正常工作,只能倒过来插入图片。 原点 (0, 0) 从左上角开始,这与其他一些可能从左下角开始的库不同(尽管我遇到了一些来源奇怪的 PDF)。我想知道你的 y 坐标是否倒置了。 我已经尝试过了,但它不起作用。任何想法为什么?看起来很整洁!【参考方案6】:

这对我有用

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)

【讨论】:

【参考方案7】:

既然是现有的pdf,最简单的方法是:

    将 pdf 转换为 .doc 或 .odt(检查 http://www.zamzar.com/) 根据需要将图像添加到转换后的文件中。 转换回 PDF(openoffice 和 libreoffice 可以轻松保存 pdf)

PS:如果pdf文件需要进一步编辑,请始终保留源.doc文件的备份,以便轻松进行更改,过多的转换会影响文件质量。

【讨论】:

以上是关于将图像放在 PDF 上的主要内容,如果未能解决你的问题,请参考以下文章

将反应项目部署到 github 页面面临公共文件夹中图像的问题

Android:给定原始图像的Uri,获取SD卡上图像的缩略图

使用 itextsharp 将图像 html 旁边的文本放置到 pdf

像图像或 PDF 文件这样的 MIME 类型不需要 base64 或以其他方式编码吗?

如何将 PDF 文件页面呈现为图像?

Matlab 将 PDF 作为图像数组访问