如何在不创建临时中间文件的情况下将Tkinter小部件附加到现有pdf



我想将Tkinter小部件的内容附加到现有pdf的末尾。

首先,我将小部件捕获为PIL图像。然后,当使用PyPDF2从图像创建中间临时文件时,似乎需要这样做,这感觉是不必要的。相反,我想直接附加图像,或者至少将图像转换为可以附加的东西,而无需写入文件。

在下面的代码片段中,我将图像保存到一个临时pdf中,然后打开pdf并附加。这是有效的,但不是一个非常优雅的解决方案。

import tkinter as tk
from PIL import ImageGrab
import os
import PyPDF2
def process_pdf(widget, pdf_filepath):
""""Append Tkinter widget to pdf"""
# capture the widget
img = capture_widget(widget)
# create pdf merger object
merger = PyPDF2.PdfMerger()
# creating a pdf file object of original pdf and add to output
pdf_org = open(pdf_filepath, 'rb')
merger.append(pdf_org)

# NOTE I want to get rid of this step
# create temporary file, read it, append it to output, delete it.
temp_filename = pdf_filepath[:-4] + "_temp.pdf"
img.save(temp_filename)
pdf_temp = open(temp_filename, 'rb')
merger.append(pdf_temp)
pdf_temp.close()
# write
outputfile = open(pdf_filepath, "wb")
merger.write(outputfile)
# clean up
pdf_org.close()
outputfile.close()
os.remove(temp_filename)

def capture_widget(widget):
"""Take screenshot of the passed widget"""
x0 = widget.winfo_rootx()
y0 = widget.winfo_rooty()
x1 = x0 + widget.winfo_width()
y1 = y0 + widget.winfo_height()
img = ImageGrab.grab((x0, y0, x1, y1))
return img

有人有一个更优雅的解决方案,不需要中间文件,同时保留PyPDF2提供的灵活性吗?

谢谢。

所以我能够自己找到解决方案。诀窍是将PIL图像写入字节数组(请参阅此问题(,然后使用img2pdf将其转换为pdf。对于img2pdf,要求使用格式=";jpeg";保存到字节数组期间的参数。

随后,img2pdf的结果可以写入另一个io.BytesIO((流。由于它实现了.read((方法,PyPDF2.PdfMerger((可以读取它.

下面是代码,希望这能帮助到别人。

import io
import PyPDF2
import img2pdf
def process_pdf(widget, pdf_filepath):
""""Append Tkinter widget to pdf"""
# create pdf merger object
merger = PyPDF2.PdfMerger()
# creating a pdf file object of original pdf and add to output
pdf_org = open(pdf_filepath, 'rb')
merger.append(pdf_org)
pdf_org.close()

# capture the widget and rotate
img = capture_widget(widget)
# create img bytearray
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format = "jpeg", quality=100)
img_byte_arr = img_byte_arr.getvalue()
# create a pdf bytearray and do formatting using img2pdf
pdf_byte_arr = io.BytesIO()
layout_fun = img2pdf.get_layout_fun((img2pdf.mm_to_pt(210),img2pdf.mm_to_pt(297)))
pdf_byte_arr.write(img2pdf.convert(img_byte_arr, layout_fun=layout_fun))
merger.append(pdf_byte_arr)
# write
outputfile = open(pdf_filepath[:-4] + "_appended.pdf", "wb")
merger.write(outputfile)
outputfile.close()

最新更新