mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	Merge pull request #2240 from uploadcare/draft-min-scale
Use minimal scale for jpeg drafts
This commit is contained in:
		
						commit
						620d082457
					
				| 
						 | 
					@ -341,6 +341,10 @@ class JpegImageFile(ImageFile.ImageFile):
 | 
				
			||||||
        if len(self.tile) != 1:
 | 
					        if len(self.tile) != 1:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Protect from second call
 | 
				
			||||||
 | 
					        if self.decoderconfig:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        d, e, o, a = self.tile[0]
 | 
					        d, e, o, a = self.tile[0]
 | 
				
			||||||
        scale = 0
 | 
					        scale = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -349,7 +353,7 @@ class JpegImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            a = mode, ""
 | 
					            a = mode, ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if size:
 | 
					        if size:
 | 
				
			||||||
            scale = max(self.size[0] // size[0], self.size[1] // size[1])
 | 
					            scale = min(self.size[0] // size[0], self.size[1] // size[1])
 | 
				
			||||||
            for s in [8, 4, 2, 1]:
 | 
					            for s in [8, 4, 2, 1]:
 | 
				
			||||||
                if scale >= s:
 | 
					                if scale >= s:
 | 
				
			||||||
                    break
 | 
					                    break
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,36 +2,73 @@ from helper import unittest, PillowTestCase, fromstring, tostring
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CODECS = dir(Image.core)
 | 
					 | 
				
			||||||
FILENAME = "Tests/images/hopper.jpg"
 | 
					 | 
				
			||||||
DATA = tostring(Image.open(FILENAME).resize((512, 512)), "JPEG")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def draft(mode, size):
 | 
					 | 
				
			||||||
    im = fromstring(DATA)
 | 
					 | 
				
			||||||
    im.draft(mode, size)
 | 
					 | 
				
			||||||
    return im
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestImageDraft(PillowTestCase):
 | 
					class TestImageDraft(PillowTestCase):
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        if "jpeg_encoder" not in CODECS or "jpeg_decoder" not in CODECS:
 | 
					        codecs = dir(Image.core)
 | 
				
			||||||
 | 
					        if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
 | 
				
			||||||
            self.skipTest("jpeg support not available")
 | 
					            self.skipTest("jpeg support not available")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def draft_roundtrip(self, in_mode, in_size, req_mode, req_size):
 | 
				
			||||||
 | 
					        im = Image.new(in_mode, in_size)
 | 
				
			||||||
 | 
					        data = tostring(im, 'JPEG')
 | 
				
			||||||
 | 
					        im = fromstring(data)
 | 
				
			||||||
 | 
					        im.draft(req_mode, req_size)
 | 
				
			||||||
 | 
					        return im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_size(self):
 | 
					    def test_size(self):
 | 
				
			||||||
        self.assertEqual(draft("RGB", (512, 512)).size, (512, 512))
 | 
					        for in_size, req_size, out_size in [
 | 
				
			||||||
        self.assertEqual(draft("RGB", (256, 256)).size, (256, 256))
 | 
					            ((435, 361), (2048, 2048), (435, 361)),  # bigger
 | 
				
			||||||
        self.assertEqual(draft("RGB", (128, 128)).size, (128, 128))
 | 
					            ((435, 361), (435, 361), (435, 361)),  # same
 | 
				
			||||||
        self.assertEqual(draft("RGB", (64, 64)).size, (64, 64))
 | 
					            ((128, 128), (64, 64), (64, 64)),
 | 
				
			||||||
        self.assertEqual(draft("RGB", (32, 32)).size, (64, 64))
 | 
					            ((128, 128), (32, 32), (32, 32)),
 | 
				
			||||||
 | 
					            ((128, 128), (16, 16), (16, 16)),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # large requested width
 | 
				
			||||||
 | 
					            ((435, 361), (218, 128), (435, 361)),  # almost 2x
 | 
				
			||||||
 | 
					            ((435, 361), (217, 128), (218, 181)),  # more than 2x
 | 
				
			||||||
 | 
					            ((435, 361), (109, 64), (218, 181)),  # almost 4x
 | 
				
			||||||
 | 
					            ((435, 361), (108, 64), (109, 91)),  # more than 4x
 | 
				
			||||||
 | 
					            ((435, 361), (55, 32), (109, 91)),  # almost 8x
 | 
				
			||||||
 | 
					            ((435, 361), (54, 32), (55, 46)),  # more than 8x
 | 
				
			||||||
 | 
					            ((435, 361), (27, 16), (55, 46)),  # more than 16x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # and vice versa
 | 
				
			||||||
 | 
					            ((435, 361), (128, 181), (435, 361)),  # almost 2x
 | 
				
			||||||
 | 
					            ((435, 361), (128, 180), (218, 181)),  # more than 2x
 | 
				
			||||||
 | 
					            ((435, 361), (64, 91), (218, 181)),  # almost 4x
 | 
				
			||||||
 | 
					            ((435, 361), (64, 90), (109, 91)),  # more than 4x
 | 
				
			||||||
 | 
					            ((435, 361), (32, 46), (109, 91)),  # almost 8x
 | 
				
			||||||
 | 
					            ((435, 361), (32, 45), (55, 46)),  # more than 8x
 | 
				
			||||||
 | 
					            ((435, 361), (16, 22), (55, 46)),  # more than 16x
 | 
				
			||||||
 | 
					        ]:
 | 
				
			||||||
 | 
					            im = self.draft_roundtrip('L', in_size, None, req_size)
 | 
				
			||||||
 | 
					            im.load()
 | 
				
			||||||
 | 
					            self.assertEqual(im.size, out_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_mode(self):
 | 
					    def test_mode(self):
 | 
				
			||||||
        self.assertEqual(draft("1", (512, 512)).mode, "RGB")
 | 
					        for in_mode, req_mode, out_mode in [
 | 
				
			||||||
        self.assertEqual(draft("L", (512, 512)).mode, "L")
 | 
					            ("RGB", "1", "RGB"),
 | 
				
			||||||
        self.assertEqual(draft("RGB", (512, 512)).mode, "RGB")
 | 
					            ("RGB", "L", "L"),
 | 
				
			||||||
        self.assertEqual(draft("YCbCr", (512, 512)).mode, "YCbCr")
 | 
					            ("RGB", "RGB", "RGB"),
 | 
				
			||||||
 | 
					            ("RGB", "YCbCr", "YCbCr"),
 | 
				
			||||||
 | 
					            ("L", "1", "L"),
 | 
				
			||||||
 | 
					            ("L", "L", "L"),
 | 
				
			||||||
 | 
					            ("L", "RGB", "L"),
 | 
				
			||||||
 | 
					            ("L", "YCbCr", "L"),
 | 
				
			||||||
 | 
					            ("CMYK", "1", "CMYK"),
 | 
				
			||||||
 | 
					            ("CMYK", "L", "CMYK"),
 | 
				
			||||||
 | 
					            ("CMYK", "RGB", "CMYK"),
 | 
				
			||||||
 | 
					            ("CMYK", "YCbCr", "CMYK"),
 | 
				
			||||||
 | 
					        ]:
 | 
				
			||||||
 | 
					            im = self.draft_roundtrip(in_mode, (64, 64), req_mode, None)
 | 
				
			||||||
 | 
					            im.load()
 | 
				
			||||||
 | 
					            self.assertEqual(im.mode, out_mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_several_drafts(self):
 | 
				
			||||||
 | 
					        im = self.draft_roundtrip('L', (128, 128), None, (64, 64))
 | 
				
			||||||
 | 
					        im.draft(None, (64, 64))
 | 
				
			||||||
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    unittest.main()
 | 
					    unittest.main()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user