mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 16:07:30 +03:00 
			
		
		
		
	Merge pull request #5476 from radarhere/dpi_rounding
This commit is contained in:
		
						commit
						a72ae6823c
					
				
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 48 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 20 KiB | 
|  | @ -63,7 +63,7 @@ def test_dpi(): | ||||||
| 
 | 
 | ||||||
|     output.seek(0) |     output.seek(0) | ||||||
|     with Image.open(output) as reloaded: |     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): | def test_save_bmp_with_dpi(tmp_path): | ||||||
|  | @ -71,6 +71,7 @@ def test_save_bmp_with_dpi(tmp_path): | ||||||
|     # Arrange |     # Arrange | ||||||
|     outfile = str(tmp_path / "temp.jpg") |     outfile = str(tmp_path / "temp.jpg") | ||||||
|     with Image.open("Tests/images/hopper.bmp") as im: |     with Image.open("Tests/images/hopper.bmp") as im: | ||||||
|  |         assert im.info["dpi"] == (95.98654816726399, 95.98654816726399) | ||||||
| 
 | 
 | ||||||
|         # Act |         # Act | ||||||
|         im.save(outfile, "JPEG", dpi=im.info["dpi"]) |         im.save(outfile, "JPEG", dpi=im.info["dpi"]) | ||||||
|  | @ -78,31 +79,17 @@ def test_save_bmp_with_dpi(tmp_path): | ||||||
|         # Assert |         # Assert | ||||||
|         with Image.open(outfile) as reloaded: |         with Image.open(outfile) as reloaded: | ||||||
|             reloaded.load() |             reloaded.load() | ||||||
|             assert im.info["dpi"] == reloaded.info["dpi"] |             assert reloaded.info["dpi"] == (96, 96) | ||||||
|             assert im.size == reloaded.size |             assert reloaded.size == im.size | ||||||
|             assert reloaded.format == "JPEG" |             assert reloaded.format == "JPEG" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_load_dpi_rounding(): | def test_save_float_dpi(tmp_path): | ||||||
|     # 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): |  | ||||||
|     outfile = str(tmp_path / "temp.bmp") |     outfile = str(tmp_path / "temp.bmp") | ||||||
|     with Image.open("Tests/images/hopper.bmp") as im: |     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: |         with Image.open(outfile) as reloaded: | ||||||
|             assert reloaded.info["dpi"] == (72, 72) |             assert reloaded.info["dpi"] == (72.21216100543306, 72.21216100543306) | ||||||
| 
 |  | ||||||
|         im.save(outfile, dpi=(72.8, 72.8)) |  | ||||||
|     with Image.open(outfile) as reloaded: |  | ||||||
|         assert reloaded.info["dpi"] == (73, 73) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_load_dib(): | def test_load_dib(): | ||||||
|  |  | ||||||
|  | @ -656,15 +656,6 @@ class TestFileJpeg: | ||||||
|                 reloaded.load() |                 reloaded.load() | ||||||
|                 assert im.info["dpi"] == reloaded.info["dpi"] |                 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): |     def test_save_dpi_rounding(self, tmp_path): | ||||||
|         outfile = str(tmp_path / "temp.jpg") |         outfile = str(tmp_path / "temp.jpg") | ||||||
|         with Image.open("Tests/images/hopper.jpg") as im: |         with Image.open("Tests/images/hopper.jpg") as im: | ||||||
|  |  | ||||||
|  | @ -386,25 +386,12 @@ class TestFilePng: | ||||||
|         # Check dpi roundtripping |         # Check dpi roundtripping | ||||||
| 
 | 
 | ||||||
|         with Image.open(TEST_PNG_FILE) as im: |         with Image.open(TEST_PNG_FILE) as im: | ||||||
|             im = roundtrip(im, dpi=(100, 100)) |             im = roundtrip(im, dpi=(100.33, 100.33)) | ||||||
|         assert im.info["dpi"] == (100, 100) |         assert im.info["dpi"] == (100.33, 100.33) | ||||||
| 
 | 
 | ||||||
|     def test_load_dpi_rounding(self): |     def test_load_float_dpi(self): | ||||||
|         # Round up |  | ||||||
|         with Image.open(TEST_PNG_FILE) as im: |         with Image.open(TEST_PNG_FILE) as im: | ||||||
|             assert im.info["dpi"] == (96, 96) |             assert im.info["dpi"] == (95.9866, 95.9866) | ||||||
| 
 |  | ||||||
|         # 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) |  | ||||||
| 
 | 
 | ||||||
|     def test_roundtrip_text(self): |     def test_roundtrip_text(self): | ||||||
|         # Check text roundtripping |         # Check text roundtripping | ||||||
|  |  | ||||||
|  | @ -115,9 +115,7 @@ class BmpImageFile(ImageFile.ImageFile): | ||||||
|             ) |             ) | ||||||
|             file_info["colors"] = i32(header_data, 28) |             file_info["colors"] = i32(header_data, 28) | ||||||
|             file_info["palette_padding"] = 4 |             file_info["palette_padding"] = 4 | ||||||
|             self.info["dpi"] = tuple( |             self.info["dpi"] = tuple(x / 39.3701 for x in file_info["pixels_per_meter"]) | ||||||
|                 int(x / 39.3701 + 0.5) for x in file_info["pixels_per_meter"] |  | ||||||
|             ) |  | ||||||
|             if file_info["compression"] == self.BITFIELDS: |             if file_info["compression"] == self.BITFIELDS: | ||||||
|                 if len(header_data) >= 52: |                 if len(header_data) >= 52: | ||||||
|                     for idx, mask in enumerate( |                     for idx, mask in enumerate( | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ | ||||||
| # | # | ||||||
| import array | import array | ||||||
| import io | import io | ||||||
|  | import math | ||||||
| import os | import os | ||||||
| import struct | import struct | ||||||
| import subprocess | import subprocess | ||||||
|  | @ -162,15 +163,17 @@ def APP(self, marker): | ||||||
|                 dpi = float(x_resolution[0]) / x_resolution[1] |                 dpi = float(x_resolution[0]) / x_resolution[1] | ||||||
|             except TypeError: |             except TypeError: | ||||||
|                 dpi = x_resolution |                 dpi = x_resolution | ||||||
|  |             if math.isnan(dpi): | ||||||
|  |                 raise ValueError | ||||||
|             if resolution_unit == 3:  # cm |             if resolution_unit == 3:  # cm | ||||||
|                 # 1 dpcm = 2.54 dpi |                 # 1 dpcm = 2.54 dpi | ||||||
|                 dpi *= 2.54 |                 dpi *= 2.54 | ||||||
|             self.info["dpi"] = int(dpi + 0.5), int(dpi + 0.5) |             self.info["dpi"] = dpi, dpi | ||||||
|         except (KeyError, SyntaxError, ValueError, ZeroDivisionError): |         except (KeyError, SyntaxError, ValueError, ZeroDivisionError): | ||||||
|             # SyntaxError for invalid/unreadable EXIF |             # SyntaxError for invalid/unreadable EXIF | ||||||
|             # KeyError for dpi not included |             # KeyError for dpi not included | ||||||
|             # ZeroDivisionError for invalid dpi rational value |             # 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 |             self.info["dpi"] = 72, 72 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -500,7 +500,7 @@ class PngStream(ChunkStream): | ||||||
|         px, py = i32(s, 0), i32(s, 4) |         px, py = i32(s, 0), i32(s, 4) | ||||||
|         unit = s[8] |         unit = s[8] | ||||||
|         if unit == 1:  # meter |         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 |             self.im_info["dpi"] = dpi | ||||||
|         elif unit == 0: |         elif unit == 0: | ||||||
|             self.im_info["aspect"] = px, py |             self.im_info["aspect"] = px, py | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user