From 9d72542c08b2bea805ebfb3389b1ab40b88bafdc Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 7 May 2021 20:39:05 +1000 Subject: [PATCH 1/3] Removed DPI rounding from PNG loading --- Tests/test_file_png.py | 21 ++++----------------- src/PIL/PngImagePlugin.py | 2 +- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index 14ad6fae162..4e7714fd4c4 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -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 diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index 07bbc52280f..9c256ca8f0a 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -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 From 0de3beaeaf11ca1670148eface36317109cf995b Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 7 May 2021 20:50:18 +1000 Subject: [PATCH 2/3] Removed DPI rounding when BMP loading --- Tests/images/hopper_roundDown.bmp | Bin 49206 -> 0 bytes Tests/test_file_bmp.py | 27 +++++++-------------------- src/PIL/BmpImagePlugin.py | 4 +--- 3 files changed, 8 insertions(+), 23 deletions(-) delete mode 100644 Tests/images/hopper_roundDown.bmp diff --git a/Tests/images/hopper_roundDown.bmp b/Tests/images/hopper_roundDown.bmp deleted file mode 100644 index 62aada05067a1a541f41b03d72feb191a3446022..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49206 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 Nz_nPQ^*_KW000}`Qt$u( diff --git a/Tests/test_file_bmp.py b/Tests/test_file_bmp.py index d5fe2a4ddc1..3374fe54e94 100644 --- a/Tests/test_file_bmp.py +++ b/Tests/test_file_bmp.py @@ -63,7 +63,7 @@ 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): @@ -71,6 +71,7 @@ def test_save_bmp_with_dpi(tmp_path): # 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"]) @@ -78,31 +79,17 @@ def test_save_bmp_with_dpi(tmp_path): # 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(): diff --git a/src/PIL/BmpImagePlugin.py b/src/PIL/BmpImagePlugin.py index 98685be0b43..821844484da 100644 --- a/src/PIL/BmpImagePlugin.py +++ b/src/PIL/BmpImagePlugin.py @@ -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( From 18e204df05b534220a1e6330bd398c9c5a358f1d Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 7 May 2021 21:23:29 +1000 Subject: [PATCH 3/3] Removed DPI rounding from JPEG loading --- Tests/images/iptc_roundDown.jpg | Bin 21019 -> 0 bytes Tests/test_file_jpeg.py | 9 --------- src/PIL/JpegImagePlugin.py | 7 +++++-- 3 files changed, 5 insertions(+), 11 deletions(-) delete mode 100644 Tests/images/iptc_roundDown.jpg diff --git a/Tests/images/iptc_roundDown.jpg b/Tests/images/iptc_roundDown.jpg deleted file mode 100644 index f98206f1826f1844f1767cbb694f830de4ed403c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21019 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 z 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 diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index ab799c13fb7..eb566e68730 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -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: diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index f449a2dc0e0..6d4bc70c5f1 100644 --- a/src/PIL/JpegImagePlugin.py +++ b/src/PIL/JpegImagePlugin.py @@ -33,6 +33,7 @@ # import array import io +import math import os import struct import subprocess @@ -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