From 92acfca46f033798e722b5f377974c5b184f2e38 Mon Sep 17 00:00:00 2001 From: Hugo Date: Tue, 14 Mar 2017 11:26:11 +0200 Subject: [PATCH 1/2] Test getting DPI from EXIF --- Tests/images/photoshop-200dpi.jpg | Bin 0 -> 10953 bytes Tests/test_file_jpeg.py | 12 ++++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 Tests/images/photoshop-200dpi.jpg diff --git a/Tests/images/photoshop-200dpi.jpg b/Tests/images/photoshop-200dpi.jpg new file mode 100644 index 0000000000000000000000000000000000000000..72455a147ad2b21c9b6c8b1e2dc8f85d20ea5617 GIT binary patch literal 10953 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 z z*+<*(Q#Z9CKC#((9;>MF7Ai$9Jxf)&(|Y52P8 zDk3NX><9RWL*V~v2+Xxw8h$mv`%m6R1?PgXpvmSQrT7S5cb%69NqgZ%hyeAe?chiN z?J2osJ4U++{I$>^A|&m-;fUr`5;2el_zXS;Rs2(B;Tr|J3hu|ProsxhpFj>Hs z(ee`IVz^9Oy@t(IpT`+w8$ zia_3ev@VifVd}3k(2s)x$J7*r>0_e1xi#0>c@41N zf_NSr2KZ}!?`wYhxhmr8cRKLHAfQF;po*vAja_O=Ai*1Y)zlD}>Xjt~2dyemU`QG< z^D1cDN3HI_8(>j(9I!uaJBB8}6&e_D9s4)*XtKQ$b1+J_&}ym=I?rBy&sarN?BwM~*>jgOY93s42|>aV)XeRscBb3*#dT9P z^I#UYGsQM)^(km=qiUw%4X14_v~FeK)9z;Hxo^DmF1$r|T633oH@~eX_DJx5oTk?_ zSeVjZvnwy=6LKhaq!IE)rr6C>6xefIcDk_6_in4@EsnG=8tT~pulD9=58xN}+YXcV zob4sV-h4t;%UeLwSm^+A5wLdivLQ8w*xOm))%|0 literal 0 HcmV?d00001 diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index f90a29162..f543119f6 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -167,14 +167,14 @@ class TestFileJpeg(PillowTestCase): def test_progressive_large_buffer_highest_quality(self): f = self.tempfile('temp.jpg') - im = self.gen_random_image((255,255)) + im = self.gen_random_image((255, 255)) # this requires more bytes than pixels in the image im.save(f, format="JPEG", progressive=True, quality=100) def test_progressive_cmyk_buffer(self): # Issue 2272, quality 90 cmyk image is tripping the large buffer bug. f = BytesIO() - im = self.gen_random_image((256,256), 'CMYK') + im = self.gen_random_image((256, 256), 'CMYK') im.save(f, format='JPEG', progressive=True, quality=94) def test_large_exif(self): @@ -500,6 +500,14 @@ class TestFileJpeg(PillowTestCase): reloaded.load() self.assertEqual(im.info['dpi'], reloaded.info['dpi']) + def test_dpi_from_exif(self): + # Arrange + # This Photoshop CC 2017 image has DPI in EXIF not metadata + im = Image.open("Tests/images/photoshop-200dpi.jpg") + + # Act / Assert + self.assertEqual(im.info.get("dpi"), 200) + if __name__ == '__main__': unittest.main() From 07a96209597c5e8dfe785c757d7051ce67a980fb Mon Sep 17 00:00:00 2001 From: Hugo Date: Tue, 14 Mar 2017 11:49:10 +0200 Subject: [PATCH 2/2] If DPI isn't in JPEG header, fetch from EXIF --- PIL/JpegImagePlugin.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/PIL/JpegImagePlugin.py b/PIL/JpegImagePlugin.py index 7a29d8bff..ae420551b 100644 --- a/PIL/JpegImagePlugin.py +++ b/PIL/JpegImagePlugin.py @@ -117,6 +117,11 @@ def APP(self, marker): # plus constant header size self.info["mpoffset"] = self.fp.tell() - n + 4 + # If DPI isn't in JPEG header, fetch from EXIF + if "dpi" not in self.info and "exif" in self.info: + x_resolution = self._getexif()[0x011A] + self.info["dpi"] = x_resolution[0] / x_resolution[1] + def COM(self, marker): #