PDF: when merging bg.pdf with fg.pdf use the higher PDF-version (#4171)

This commit is contained in:
Richard Schreiber
2024-06-11 12:16:57 +02:00
committed by GitHub
parent b55bd8f75a
commit 3b48b0782d

View File

@@ -1068,36 +1068,72 @@ class Renderer:
canvas.showPage() canvas.showPage()
def render_background(self, buffer, title=_('Ticket')): def render_background(self, buffer, title=_('Ticket')):
buffer.seek(0)
fg_pdf = PdfReader(buffer)
if settings.PDFTK: if settings.PDFTK:
buffer.seek(0)
with tempfile.TemporaryDirectory() as d: with tempfile.TemporaryDirectory() as d:
with open(os.path.join(d, 'back.pdf'), 'wb') as f: fg_filename = os.path.join(d, 'fg.pdf')
f.write(self.bg_bytes) bg_filename = os.path.join(d, 'bg.pdf')
with open(os.path.join(d, 'front.pdf'), 'wb') as f: out_filename = os.path.join(d, 'out.pdf')
buffer.seek(0)
with open(fg_filename, 'wb') as f:
f.write(buffer.read()) f.write(buffer.read())
subprocess.run([ # pdf_header is a string like "%pdf-X.X"
settings.PDFTK, if float(self.bg_pdf.pdf_header[5:]) > float(fg_pdf.pdf_header[5:]):
os.path.join(d, 'front.pdf'), # To fix issues with pdftk and background-PDF using pdf-version greater
'multibackground', # than foreground-PDF, we stamp front onto back instead.
os.path.join(d, 'back.pdf'), # Just changing PDF-version in fg.pdf to match the version of
'output', # bg.pdf as we do with pypdf, does not work with pdftk.
os.path.join(d, 'out.pdf'), #
'compress' # Make sure that bg.pdf matches the number of pages of fg.pdf
], check=True) # note: self.bg_pdf is a PdfReader(), not a PdfWriter()
with open(os.path.join(d, 'out.pdf'), 'rb') as f: fg_num_pages = fg_pdf.get_num_pages()
bg_num_pages = self.bg_pdf.get_num_pages()
bg_pdf_to_merge = PdfWriter()
bg_pdf_to_merge.append(self.bg_pdf, pages=(0, min(bg_num_pages, fg_num_pages)))
if fg_num_pages > bg_num_pages:
# repeat last page in bg_pdf to match fg_pdf
bg_pdf_to_merge.append(bg_pdf_to_merge, pages=[bg_num_pages - 1] * (fg_num_pages - bg_num_pages))
bg_pdf_to_merge.write(bg_filename)
pdftk_cmd = [
settings.PDFTK,
bg_filename,
'multistamp',
fg_filename
]
else:
with open(bg_filename, 'wb') as f:
f.write(self.bg_bytes)
pdftk_cmd = [
settings.PDFTK,
fg_filename,
'multibackground',
bg_filename
]
pdftk_cmd.extend(('output', out_filename, 'compress'))
subprocess.run(pdftk_cmd, check=True)
with open(out_filename, 'rb') as f:
return BytesIO(f.read()) return BytesIO(f.read())
else: else:
buffer.seek(0)
new_pdf = PdfReader(buffer)
output = PdfWriter() output = PdfWriter()
for i, page in enumerate(new_pdf.pages): for i, page in enumerate(fg_pdf.pages):
bg_page = self.bg_pdf.pages[i] bg_page = self.bg_pdf.pages[i]
if bg_page.rotation != 0: if bg_page.rotation != 0:
bg_page.transfer_rotation_to_content() bg_page.transfer_rotation_to_content()
page.merge_page(bg_page, over=False) page.merge_page(bg_page, over=False)
output.add_page(page) output.add_page(page)
# pdf_header is a string like "%pdf-X.X"
if float(self.bg_pdf.pdf_header[5:]) > float(fg_pdf.pdf_header[5:]):
output.pdf_header = self.bg_pdf.pdf_header
output.add_metadata({ output.add_metadata({
'/Title': str(title), '/Title': str(title),
'/Creator': 'pretix', '/Creator': 'pretix',
@@ -1108,33 +1144,61 @@ class Renderer:
return outbuffer return outbuffer
def merge_background(fg_pdf, bg_pdf, out_file, compress): def merge_background(fg_pdf: PdfWriter, bg_pdf: PdfWriter, out_file, compress):
if settings.PDFTK: if settings.PDFTK:
with tempfile.TemporaryDirectory() as d: with tempfile.TemporaryDirectory() as d:
fg_filename = os.path.join(d, 'fg.pdf') fg_filename = os.path.join(d, 'fg.pdf')
bg_filename = os.path.join(d, 'bg.pdf') bg_filename = os.path.join(d, 'bg.pdf')
fg_pdf.write(fg_filename)
bg_pdf.write(bg_filename) # pdf_header is a string like "%pdf-X.X"
pdftk_cmd = [ if float(bg_pdf.pdf_header[5:]) > float(fg_pdf.pdf_header[5:]):
settings.PDFTK, # To fix issues with pdftk and background-PDF using pdf-version greater
fg_filename, # than foreground-PDF, we stamp front onto back instead.
'multibackground', # Just changing PDF-version in fg.pdf to match the version of
bg_filename, # bg.pdf as we do with pypdf, does not work with pdftk.
'output',
'-', # Make sure that bg.pdf matches the number of pages of fg.pdf
] fg_num_pages = fg_pdf.get_num_pages()
bg_num_pages = bg_pdf.get_num_pages()
if fg_num_pages > bg_num_pages:
# repeat last page in bg_pdf to match fg_pdf
bg_pdf.append(bg_pdf, pages=[bg_num_pages - 1] * (fg_num_pages - bg_num_pages))
bg_pdf.write(bg_filename)
pdftk_cmd = [
settings.PDFTK,
bg_filename,
'multistamp',
fg_filename,
]
else:
pdftk_cmd = [
settings.PDFTK,
fg_filename,
'multibackground',
bg_filename
]
pdftk_cmd.extend(('output', '-'))
if compress: if compress:
pdftk_cmd.append('compress') pdftk_cmd.append('compress')
fg_pdf.write(fg_filename)
bg_pdf.write(bg_filename)
subprocess.run(pdftk_cmd, check=True, stdout=out_file) subprocess.run(pdftk_cmd, check=True, stdout=out_file)
else: else:
output = PdfWriter()
for i, page in enumerate(fg_pdf.pages): for i, page in enumerate(fg_pdf.pages):
bg_page = bg_pdf.pages[i] bg_page = bg_pdf.pages[i]
if bg_page.rotation != 0: if bg_page.rotation != 0:
bg_page.transfer_rotation_to_content() bg_page.transfer_rotation_to_content()
page.merge_page(bg_page, over=False) page.merge_page(bg_page, over=False)
output.add_page(page)
output.write(out_file) # pdf_header is a string like "%pdf-X.X"
if float(bg_pdf.pdf_header[5:]) > float(fg_pdf.pdf_header[5:]):
fg_pdf.pdf_header = bg_pdf.pdf_header
fg_pdf.write(out_file)
@deconstructible @deconstructible