Skip to content

Commit

Permalink
Don’t resize the same image twice when the --dpi option is set
Browse files Browse the repository at this point in the history
It also avoids crashes with PNG images, as the incomplete PNG part used in the
PDF was read by Pillow the second time instead of the whole PNG file.
  • Loading branch information
liZe committed May 8, 2023
1 parent b64c369 commit 93df1a5
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 16 deletions.
17 changes: 3 additions & 14 deletions weasyprint/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,28 +94,17 @@ def draw(self, stream, concrete_width, concrete_height, image_rendering):
return

width, height = self.width, self.height
interpolate = 'true' if image_rendering == 'auto' else 'false'
ratio = 1
if self._dpi:
pt_to_in = 4 / 3 / 96
width_inches = abs(concrete_width * stream.ctm[0][0] * pt_to_in)
height_inches = abs(concrete_height * stream.ctm[1][1] * pt_to_in)
dpi = max(self.width / width_inches, self.height / height_inches)
if dpi > self._dpi:
ratio = self._dpi / dpi
image = Image.open(io.BytesIO(self.image_data.data))
width = int(round(self.width * ratio))
height = int(round(self.height * ratio))
image.thumbnail((max(1, width), max(1, height)))
image_file = io.BytesIO()
image.save(
image_file, format=image.format, optimize=self.optimize)
width, height = image.width, image.height
self.image_data = self.cache_image_data(image_file.getvalue())
else:
dpi = None

interpolate = 'true' if image_rendering == 'auto' else 'false'
image_name = stream.add_image(self, width, height, interpolate, ratio)

image_name = stream.add_image(self, width, height, interpolate)
stream.transform(
concrete_width, 0, 0, -concrete_height, 0, concrete_height)
stream.draw_x_object(image_name)
Expand Down
16 changes: 14 additions & 2 deletions weasyprint/pdf/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from fontTools import subset
from fontTools.ttLib import TTFont, TTLibError, ttFont
from fontTools.varLib.mutator import instantiateVariableFont
from PIL import Image

from ..logger import LOGGER
from ..matrix import Matrix
Expand Down Expand Up @@ -361,13 +362,24 @@ def add_group(self, x, y, width, height):
self._x_objects[group.id] = group
return group

def add_image(self, image, width, height, interpolate):
image_name = f'i{image.id}{width}{height}{interpolate}'
def add_image(self, image, width, height, interpolate, ratio):
image_name = f'i{image.id}{width}{height}{interpolate}{ratio}'
self._x_objects[image_name] = None # Set by write_pdf
if image_name in self._images:
# Reuse image already stored in document
return image_name

if ratio != 1:
thumbnail = Image.open(io.BytesIO(image.image_data.data))
width = int(round(image.width * ratio))
height = int(round(image.height * ratio))
thumbnail.thumbnail((max(1, width), max(1, height)))
image_file = io.BytesIO()
thumbnail.save(
image_file, format=thumbnail.format, optimize=image.optimize)
width, height = thumbnail.width, thumbnail.height
image.image_data = image.cache_image_data(image_file.getvalue())

xobject = image.get_xobject(width, height, interpolate)
self._images[image_name] = xobject
return image_name
Expand Down

0 comments on commit 93df1a5

Please sign in to comment.