Badges: reduce memory usage when placing multiple per page (Z#23125583) (#3472)

Co-authored-by: Raphael Michel <michel@rami.io>
This commit is contained in:
Richard Schreiber
2023-07-17 12:50:48 +02:00
committed by GitHub
parent 7b5789b110
commit 0969abb460
4 changed files with 255 additions and 56 deletions

View File

@@ -140,7 +140,7 @@ class BaseExporter:
"""
return {}
def render(self, form_data: dict) -> Tuple[str, str, bytes]:
def render(self, form_data: dict) -> Tuple[str, str, Optional[bytes]]:
"""
Render the exported file and return a tuple consisting of a filename, a file type
and file content.

View File

@@ -61,7 +61,8 @@ from django.utils.html import conditional_escape
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _, pgettext
from i18nfield.strings import LazyI18nString
from pypdf import PdfReader
from pypdf import PdfReader, PdfWriter, Transformation
from pypdf.generic import RectangleObject
from reportlab.graphics import renderPDF
from reportlab.graphics.barcode.qr import QrCodeWidget
from reportlab.graphics.shapes import Drawing
@@ -1027,14 +1028,12 @@ class Renderer:
with open(os.path.join(d, 'out.pdf'), 'rb') as f:
return BytesIO(f.read())
else:
from pypdf import PdfReader, PdfWriter, Transformation
from pypdf.generic import RectangleObject
buffer.seek(0)
new_pdf = PdfReader(buffer)
output = PdfWriter()
for i, page in enumerate(new_pdf.pages):
bg_page = copy.copy(self.bg_pdf.pages[i])
bg_page = copy.deepcopy(self.bg_pdf.pages[i])
bg_rotation = bg_page.get('/Rotate')
if bg_rotation:
# /Rotate is clockwise, transformation.rotate is counter-clockwise
@@ -1071,6 +1070,56 @@ class Renderer:
return outbuffer
def merge_background(fg_pdf, bg_pdf, out_file, compress):
if settings.PDFTK:
with tempfile.TemporaryDirectory() as d:
fg_filename = os.path.join(d, 'fg.pdf')
bg_filename = os.path.join(d, 'bg.pdf')
fg_pdf.write(fg_filename)
bg_pdf.write(bg_filename)
pdftk_cmd = [
settings.PDFTK,
fg_filename,
'multibackground',
bg_filename,
'output',
'-',
]
if compress:
pdftk_cmd.append('compress')
subprocess.run(pdftk_cmd, check=True, stdout=out_file)
else:
output = PdfWriter()
for i, page in enumerate(fg_pdf.pages):
bg_page = copy.deepcopy(bg_pdf.pages[i])
bg_rotation = bg_page.get('/Rotate')
if bg_rotation:
# /Rotate is clockwise, transformation.rotate is counter-clockwise
t = Transformation().rotate(bg_rotation)
w = float(page.mediabox.getWidth())
h = float(page.mediabox.getHeight())
if bg_rotation in (90, 270):
# offset due to rotation base
if bg_rotation == 90:
t = t.translate(h, 0)
else:
t = t.translate(0, w)
# rotate mediabox as well
page.mediabox = RectangleObject((
page.mediabox.left.as_numeric(),
page.mediabox.bottom.as_numeric(),
page.mediabox.top.as_numeric(),
page.mediabox.right.as_numeric(),
))
page.trimbox = page.mediabox
elif bg_rotation == 180:
t = t.translate(w, h)
page.add_transformation(t)
bg_page.merge_page(page)
output.add_page(bg_page)
output.write(out_file)
@deconstructible
class PdfLayoutValidator:
def __call__(self, value):