Skip to content

Commit

Permalink
Merge pull request #5476 from radarhere/dpi_rounding
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk committed May 16, 2021
2 parents d53a664 + 18e204d commit a72ae68
Show file tree
Hide file tree
Showing 8 changed files with 18 additions and 52 deletions.
Binary file removed Tests/images/hopper_roundDown.bmp
Binary file not shown.
Binary file removed Tests/images/iptc_roundDown.jpg
Binary file not shown.
27 changes: 7 additions & 20 deletions Tests/test_file_bmp.py
Expand Up @@ -63,46 +63,33 @@ def test_dpi():

output.seek(0)
with Image.open(output) as reloaded:
assert reloaded.info["dpi"] == dpi
assert reloaded.info["dpi"] == (72.008961115161, 72.008961115161)


def test_save_bmp_with_dpi(tmp_path):
# Test for #1301
# Arrange
outfile = str(tmp_path / "temp.jpg")
with Image.open("Tests/images/hopper.bmp") as im:
assert im.info["dpi"] == (95.98654816726399, 95.98654816726399)

# Act
im.save(outfile, "JPEG", dpi=im.info["dpi"])

# Assert
with Image.open(outfile) as reloaded:
reloaded.load()
assert im.info["dpi"] == reloaded.info["dpi"]
assert im.size == reloaded.size
assert reloaded.info["dpi"] == (96, 96)
assert reloaded.size == im.size
assert reloaded.format == "JPEG"


def test_load_dpi_rounding():
# Round up
with Image.open("Tests/images/hopper.bmp") as im:
assert im.info["dpi"] == (96, 96)

# Round down
with Image.open("Tests/images/hopper_roundDown.bmp") as im:
assert im.info["dpi"] == (72, 72)


def test_save_dpi_rounding(tmp_path):
def test_save_float_dpi(tmp_path):
outfile = str(tmp_path / "temp.bmp")
with Image.open("Tests/images/hopper.bmp") as im:
im.save(outfile, dpi=(72.2, 72.2))
im.save(outfile, dpi=(72.21216100543306, 72.21216100543306))
with Image.open(outfile) as reloaded:
assert reloaded.info["dpi"] == (72, 72)

im.save(outfile, dpi=(72.8, 72.8))
with Image.open(outfile) as reloaded:
assert reloaded.info["dpi"] == (73, 73)
assert reloaded.info["dpi"] == (72.21216100543306, 72.21216100543306)


def test_load_dib():
Expand Down
9 changes: 0 additions & 9 deletions Tests/test_file_jpeg.py
Expand Up @@ -656,15 +656,6 @@ def test_save_tiff_with_dpi(self, tmp_path):
reloaded.load()
assert im.info["dpi"] == reloaded.info["dpi"]

def test_load_dpi_rounding(self):
# Round up
with Image.open("Tests/images/iptc_roundUp.jpg") as im:
assert im.info["dpi"] == (44, 44)

# Round down
with Image.open("Tests/images/iptc_roundDown.jpg") as im:
assert im.info["dpi"] == (2, 2)

def test_save_dpi_rounding(self, tmp_path):
outfile = str(tmp_path / "temp.jpg")
with Image.open("Tests/images/hopper.jpg") as im:
Expand Down
21 changes: 4 additions & 17 deletions Tests/test_file_png.py
Expand Up @@ -386,25 +386,12 @@ def test_roundtrip_dpi(self):
# Check dpi roundtripping

with Image.open(TEST_PNG_FILE) as im:
im = roundtrip(im, dpi=(100, 100))
assert im.info["dpi"] == (100, 100)
im = roundtrip(im, dpi=(100.33, 100.33))
assert im.info["dpi"] == (100.33, 100.33)

def test_load_dpi_rounding(self):
# Round up
def test_load_float_dpi(self):
with Image.open(TEST_PNG_FILE) as im:
assert im.info["dpi"] == (96, 96)

# Round down
with Image.open("Tests/images/icc_profile_none.png") as im:
assert im.info["dpi"] == (72, 72)

def test_save_dpi_rounding(self):
with Image.open(TEST_PNG_FILE) as im:
im = roundtrip(im, dpi=(72.2, 72.2))
assert im.info["dpi"] == (72, 72)

im = roundtrip(im, dpi=(72.8, 72.8))
assert im.info["dpi"] == (73, 73)
assert im.info["dpi"] == (95.9866, 95.9866)

def test_roundtrip_text(self):
# Check text roundtripping
Expand Down
4 changes: 1 addition & 3 deletions src/PIL/BmpImagePlugin.py
Expand Up @@ -115,9 +115,7 @@ def _bitmap(self, header=0, offset=0):
)
file_info["colors"] = i32(header_data, 28)
file_info["palette_padding"] = 4
self.info["dpi"] = tuple(
int(x / 39.3701 + 0.5) for x in file_info["pixels_per_meter"]
)
self.info["dpi"] = tuple(x / 39.3701 for x in file_info["pixels_per_meter"])
if file_info["compression"] == self.BITFIELDS:
if len(header_data) >= 52:
for idx, mask in enumerate(
Expand Down
7 changes: 5 additions & 2 deletions src/PIL/JpegImagePlugin.py
Expand Up @@ -33,6 +33,7 @@
#
import array
import io
import math
import os
import struct
import subprocess
Expand Down Expand Up @@ -162,15 +163,17 @@ def APP(self, marker):
dpi = float(x_resolution[0]) / x_resolution[1]
except TypeError:
dpi = x_resolution
if math.isnan(dpi):
raise ValueError
if resolution_unit == 3: # cm
# 1 dpcm = 2.54 dpi
dpi *= 2.54
self.info["dpi"] = int(dpi + 0.5), int(dpi + 0.5)
self.info["dpi"] = dpi, dpi
except (KeyError, SyntaxError, ValueError, ZeroDivisionError):
# SyntaxError for invalid/unreadable EXIF
# KeyError for dpi not included
# ZeroDivisionError for invalid dpi rational value
# ValueError for x_resolution[0] being an invalid float
# ValueError for dpi being an invalid float
self.info["dpi"] = 72, 72


Expand Down
2 changes: 1 addition & 1 deletion src/PIL/PngImagePlugin.py
Expand Up @@ -500,7 +500,7 @@ def chunk_pHYs(self, pos, length):
px, py = i32(s, 0), i32(s, 4)
unit = s[8]
if unit == 1: # meter
dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5)
dpi = px * 0.0254, py * 0.0254
self.im_info["dpi"] = dpi
elif unit == 0:
self.im_info["aspect"] = px, py
Expand Down

0 comments on commit a72ae68

Please sign in to comment.