mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +03:00 
			
		
		
		
	Merge pull request #619 from eliempje/master
Bugfix: EPS thumbnail failed
This commit is contained in:
		
						commit
						3f18e0adfe
					
				| 
						 | 
					@ -11,6 +11,7 @@
 | 
				
			||||||
# 1996-08-23 fl   Handle files from Macintosh (0.3)
 | 
					# 1996-08-23 fl   Handle files from Macintosh (0.3)
 | 
				
			||||||
# 2001-02-17 fl   Use 're' instead of 'regex' (Python 2.1) (0.4)
 | 
					# 2001-02-17 fl   Use 're' instead of 'regex' (Python 2.1) (0.4)
 | 
				
			||||||
# 2003-09-07 fl   Check gs.close status (from Federico Di Gregorio) (0.5)
 | 
					# 2003-09-07 fl   Check gs.close status (from Federico Di Gregorio) (0.5)
 | 
				
			||||||
 | 
					# 2014-05-07 e    Handling of EPS with binary preview and fixed resolution resizing
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Copyright (c) 1997-2003 by Secret Labs AB.
 | 
					# Copyright (c) 1997-2003 by Secret Labs AB.
 | 
				
			||||||
# Copyright (c) 1995-2003 by Fredrik Lundh
 | 
					# Copyright (c) 1995-2003 by Fredrik Lundh
 | 
				
			||||||
| 
						 | 
					@ -77,8 +78,9 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
				
			||||||
    orig_size = size
 | 
					    orig_size = size
 | 
				
			||||||
    orig_bbox = bbox
 | 
					    orig_bbox = bbox
 | 
				
			||||||
    size = (size[0] * scale, size[1] * scale)
 | 
					    size = (size[0] * scale, size[1] * scale)
 | 
				
			||||||
    bbox = [bbox[0], bbox[1], bbox[2] * scale, bbox[3] * scale]
 | 
					    # resolution is dependend on bbox and size
 | 
				
			||||||
    #print("Ghostscript", scale, size, orig_size, bbox, orig_bbox)
 | 
					    res = ( float((72.0 * size[0]) / (bbox[2]-bbox[0])), float((72.0 * size[1]) / (bbox[3]-bbox[1])) )
 | 
				
			||||||
 | 
					    #print("Ghostscript", scale, size, orig_size, bbox, orig_bbox, res)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    import tempfile, os, subprocess
 | 
					    import tempfile, os, subprocess
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,20 +89,29 @@ def Ghostscript(tile, size, fp, scale=1):
 | 
				
			||||||
    in_fd, infile = tempfile.mkstemp()
 | 
					    in_fd, infile = tempfile.mkstemp()
 | 
				
			||||||
    os.close(in_fd)
 | 
					    os.close(in_fd)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    # ignore length and offset!
 | 
				
			||||||
 | 
					    # ghostscript can read it   
 | 
				
			||||||
 | 
					    # copy whole file to read in ghostscript
 | 
				
			||||||
    with open(infile, 'wb') as f:
 | 
					    with open(infile, 'wb') as f:
 | 
				
			||||||
        fp.seek(offset)
 | 
					        # fetch length of fp
 | 
				
			||||||
        while length >0:
 | 
					        fp.seek(0, 2)
 | 
				
			||||||
            s = fp.read(100*1024)
 | 
					        fsize = fp.tell()
 | 
				
			||||||
 | 
					        # ensure start position
 | 
				
			||||||
 | 
					        # go back
 | 
				
			||||||
 | 
					        fp.seek(0)
 | 
				
			||||||
 | 
					        lengthfile = fsize
 | 
				
			||||||
 | 
					        while lengthfile > 0:
 | 
				
			||||||
 | 
					            s = fp.read(min(lengthfile, 100*1024))
 | 
				
			||||||
            if not s:
 | 
					            if not s:
 | 
				
			||||||
                break
 | 
					                break
 | 
				
			||||||
            length = length - len(s)
 | 
					            lengthfile = lengthfile - len(s)
 | 
				
			||||||
            f.write(s)
 | 
					            f.write(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Build ghostscript command
 | 
					    # Build ghostscript command
 | 
				
			||||||
    command = ["gs",
 | 
					    command = ["gs",
 | 
				
			||||||
               "-q",                        # quiet mode
 | 
					               "-q",                        # quiet mode
 | 
				
			||||||
               "-g%dx%d" % size,            # set output geometry (pixels)
 | 
					               "-g%dx%d" % size,            # set output geometry (pixels)
 | 
				
			||||||
               "-r%d" % (72*scale),         # set input DPI (dots per inch)
 | 
					               "-r%fx%f" % res,             # set input DPI (dots per inch)
 | 
				
			||||||
               "-dNOPAUSE -dSAFER",         # don't pause between pages, safe mode
 | 
					               "-dNOPAUSE -dSAFER",         # don't pause between pages, safe mode
 | 
				
			||||||
               "-sDEVICE=ppmraw",           # ppm driver
 | 
					               "-sDEVICE=ppmraw",           # ppm driver
 | 
				
			||||||
               "-sOutputFile=%s" % outfile, # output file
 | 
					               "-sOutputFile=%s" % outfile, # output file
 | 
				
			||||||
| 
						 | 
					@ -145,6 +156,8 @@ class PSFile:
 | 
				
			||||||
        self.fp.seek(offset, whence)
 | 
					        self.fp.seek(offset, whence)
 | 
				
			||||||
    def read(self, count):
 | 
					    def read(self, count):
 | 
				
			||||||
        return self.fp.read(count).decode('latin-1')
 | 
					        return self.fp.read(count).decode('latin-1')
 | 
				
			||||||
 | 
					    def readbinary(self, count):
 | 
				
			||||||
 | 
					        return self.fp.read(count)
 | 
				
			||||||
    def tell(self):
 | 
					    def tell(self):
 | 
				
			||||||
        pos = self.fp.tell()
 | 
					        pos = self.fp.tell()
 | 
				
			||||||
        if self.char:
 | 
					        if self.char:
 | 
				
			||||||
| 
						 | 
					@ -182,24 +195,32 @@ class EpsImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _open(self):
 | 
					    def _open(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # FIXME: should check the first 512 bytes to see if this
 | 
					 | 
				
			||||||
        # really is necessary (platform-dependent, though...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fp = PSFile(self.fp)
 | 
					        fp = PSFile(self.fp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # HEAD
 | 
					        # FIX for: Some EPS file not handled correctly / issue #302 
 | 
				
			||||||
        s = fp.read(512)
 | 
					        # EPS can contain binary data
 | 
				
			||||||
 | 
					        # or start directly with latin coding
 | 
				
			||||||
 | 
					        # read header in both ways to handle both
 | 
				
			||||||
 | 
					        # file types
 | 
				
			||||||
 | 
					        # more info see http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # for HEAD without binary preview
 | 
				
			||||||
 | 
					        s = fp.read(4)
 | 
				
			||||||
 | 
					        # for HEAD with binary preview
 | 
				
			||||||
 | 
					        fp.seek(0)
 | 
				
			||||||
 | 
					        sb = fp.readbinary(160)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if s[:4] == "%!PS":
 | 
					        if s[:4] == "%!PS":
 | 
				
			||||||
            offset = 0
 | 
					 | 
				
			||||||
            fp.seek(0, 2)
 | 
					            fp.seek(0, 2)
 | 
				
			||||||
            length = fp.tell()
 | 
					            length = fp.tell()
 | 
				
			||||||
        elif i32(s) == 0xC6D3D0C5:
 | 
					            offset = 0
 | 
				
			||||||
            offset = i32(s[4:])
 | 
					        elif i32(sb[0:4]) == 0xC6D3D0C5:
 | 
				
			||||||
            length = i32(s[8:])
 | 
					            offset = i32(sb[4:8])
 | 
				
			||||||
            fp.seek(offset)
 | 
					            length = i32(sb[8:12])
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            raise SyntaxError("not an EPS file")
 | 
					            raise SyntaxError("not an EPS file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # go to offset - start of "%!PS" 
 | 
				
			||||||
        fp.seek(offset)
 | 
					        fp.seek(offset)
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        box = None
 | 
					        box = None
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								Tests/images/binary_preview_map.eps
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/images/binary_preview_map.eps
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -1,25 +1,27 @@
 | 
				
			||||||
from tester import *
 | 
					from tester import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, EpsImagePlugin
 | 
					from PIL import Image, EpsImagePlugin
 | 
				
			||||||
import sys
 | 
					 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if not EpsImagePlugin.has_ghostscript():
 | 
					if not EpsImagePlugin.has_ghostscript():
 | 
				
			||||||
    skip()
 | 
					    skip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Our two EPS test files (they are identical except for their bounding boxes)
 | 
					# Our two EPS test files (they are identical except for their bounding boxes)
 | 
				
			||||||
file1 = "Tests/images/zero_bb.eps"
 | 
					file1 = "Tests/images/zero_bb.eps"
 | 
				
			||||||
file2 = "Tests/images/non_zero_bb.eps"
 | 
					file2 = "Tests/images/non_zero_bb.eps"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Due to palletization, we'll need to convert these to RGB after load
 | 
					# Due to palletization, we'll need to convert these to RGB after load
 | 
				
			||||||
file1_compare = "Tests/images/zero_bb.png"
 | 
					file1_compare = "Tests/images/zero_bb.png"
 | 
				
			||||||
file1_compare_scale2 = "Tests/images/zero_bb_scale2.png"
 | 
					file1_compare_scale2 = "Tests/images/zero_bb_scale2.png"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
file2_compare = "Tests/images/non_zero_bb.png"
 | 
					file2_compare = "Tests/images/non_zero_bb.png"
 | 
				
			||||||
file2_compare_scale2 = "Tests/images/non_zero_bb_scale2.png"
 | 
					file2_compare_scale2 = "Tests/images/non_zero_bb_scale2.png"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# EPS test files with binary preview
 | 
				
			||||||
 | 
					file3 = "Tests/images/binary_preview_map.eps"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity():
 | 
				
			||||||
    #Regular scale
 | 
					    # Regular scale
 | 
				
			||||||
    image1 = Image.open(file1)
 | 
					    image1 = Image.open(file1)
 | 
				
			||||||
    image1.load()
 | 
					    image1.load()
 | 
				
			||||||
    assert_equal(image1.mode, "RGB")
 | 
					    assert_equal(image1.mode, "RGB")
 | 
				
			||||||
| 
						 | 
					@ -32,7 +34,7 @@ def test_sanity():
 | 
				
			||||||
    assert_equal(image2.size, (360, 252))
 | 
					    assert_equal(image2.size, (360, 252))
 | 
				
			||||||
    assert_equal(image2.format, "EPS")
 | 
					    assert_equal(image2.format, "EPS")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #Double scale
 | 
					    # Double scale
 | 
				
			||||||
    image1_scale2 = Image.open(file1)
 | 
					    image1_scale2 = Image.open(file1)
 | 
				
			||||||
    image1_scale2.load(scale=2)
 | 
					    image1_scale2.load(scale=2)
 | 
				
			||||||
    assert_equal(image1_scale2.mode, "RGB")
 | 
					    assert_equal(image1_scale2.mode, "RGB")
 | 
				
			||||||
| 
						 | 
					@ -45,54 +47,96 @@ def test_sanity():
 | 
				
			||||||
    assert_equal(image2_scale2.size, (720, 504))
 | 
					    assert_equal(image2_scale2.size, (720, 504))
 | 
				
			||||||
    assert_equal(image2_scale2.format, "EPS")
 | 
					    assert_equal(image2_scale2.format, "EPS")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_file_object():
 | 
					def test_file_object():
 | 
				
			||||||
    #issue 479
 | 
					    # issue 479
 | 
				
			||||||
    image1 = Image.open(file1)
 | 
					    image1 = Image.open(file1)
 | 
				
			||||||
    with open(tempfile('temp_file.eps'), 'wb') as fh:
 | 
					    with open(tempfile('temp_file.eps'), 'wb') as fh:
 | 
				
			||||||
        image1.save(fh, 'EPS')
 | 
					        image1.save(fh, 'EPS')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_iobase_object():
 | 
					def test_iobase_object():
 | 
				
			||||||
    #issue 479
 | 
					    # issue 479
 | 
				
			||||||
    image1 = Image.open(file1)
 | 
					    image1 = Image.open(file1)
 | 
				
			||||||
    with io.open(tempfile('temp_iobase.eps'), 'wb') as fh:
 | 
					    with io.open(tempfile('temp_iobase.eps'), 'wb') as fh:
 | 
				
			||||||
        image1.save(fh, 'EPS')
 | 
					        image1.save(fh, 'EPS')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_render_scale1():
 | 
					def test_render_scale1():
 | 
				
			||||||
    #We need png support for these render test
 | 
					    # We need png support for these render test
 | 
				
			||||||
    codecs = dir(Image.core)
 | 
					    codecs = dir(Image.core)
 | 
				
			||||||
    if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
 | 
					    if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
 | 
				
			||||||
        skip("zip/deflate support not available")
 | 
					        skip("zip/deflate support not available")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #Zero bounding box
 | 
					    # Zero bounding box
 | 
				
			||||||
    image1_scale1 = Image.open(file1)
 | 
					    image1_scale1 = Image.open(file1)
 | 
				
			||||||
    image1_scale1.load()
 | 
					    image1_scale1.load()
 | 
				
			||||||
    image1_scale1_compare = Image.open(file1_compare).convert("RGB")
 | 
					    image1_scale1_compare = Image.open(file1_compare).convert("RGB")
 | 
				
			||||||
    image1_scale1_compare.load()
 | 
					    image1_scale1_compare.load()
 | 
				
			||||||
    assert_image_similar(image1_scale1, image1_scale1_compare, 5)
 | 
					    assert_image_similar(image1_scale1, image1_scale1_compare, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #Non-Zero bounding box
 | 
					    # Non-Zero bounding box
 | 
				
			||||||
    image2_scale1 = Image.open(file2)
 | 
					    image2_scale1 = Image.open(file2)
 | 
				
			||||||
    image2_scale1.load()
 | 
					    image2_scale1.load()
 | 
				
			||||||
    image2_scale1_compare = Image.open(file2_compare).convert("RGB")
 | 
					    image2_scale1_compare = Image.open(file2_compare).convert("RGB")
 | 
				
			||||||
    image2_scale1_compare.load()
 | 
					    image2_scale1_compare.load()
 | 
				
			||||||
    assert_image_similar(image2_scale1, image2_scale1_compare, 10)
 | 
					    assert_image_similar(image2_scale1, image2_scale1_compare, 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_render_scale2():
 | 
					def test_render_scale2():
 | 
				
			||||||
    #We need png support for these render test
 | 
					    # We need png support for these render test
 | 
				
			||||||
    codecs = dir(Image.core)
 | 
					    codecs = dir(Image.core)
 | 
				
			||||||
    if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
 | 
					    if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
 | 
				
			||||||
        skip("zip/deflate support not available")
 | 
					        skip("zip/deflate support not available")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #Zero bounding box
 | 
					    # Zero bounding box
 | 
				
			||||||
    image1_scale2 = Image.open(file1)
 | 
					    image1_scale2 = Image.open(file1)
 | 
				
			||||||
    image1_scale2.load(scale=2)
 | 
					    image1_scale2.load(scale=2)
 | 
				
			||||||
    image1_scale2_compare = Image.open(file1_compare_scale2).convert("RGB")
 | 
					    image1_scale2_compare = Image.open(file1_compare_scale2).convert("RGB")
 | 
				
			||||||
    image1_scale2_compare.load()
 | 
					    image1_scale2_compare.load()
 | 
				
			||||||
    assert_image_similar(image1_scale2, image1_scale2_compare, 5)
 | 
					    assert_image_similar(image1_scale2, image1_scale2_compare, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #Non-Zero bounding box
 | 
					    # Non-Zero bounding box
 | 
				
			||||||
    image2_scale2 = Image.open(file2)
 | 
					    image2_scale2 = Image.open(file2)
 | 
				
			||||||
    image2_scale2.load(scale=2)
 | 
					    image2_scale2.load(scale=2)
 | 
				
			||||||
    image2_scale2_compare = Image.open(file2_compare_scale2).convert("RGB")
 | 
					    image2_scale2_compare = Image.open(file2_compare_scale2).convert("RGB")
 | 
				
			||||||
    image2_scale2_compare.load()
 | 
					    image2_scale2_compare.load()
 | 
				
			||||||
    assert_image_similar(image2_scale2, image2_scale2_compare, 10)
 | 
					    assert_image_similar(image2_scale2, image2_scale2_compare, 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_resize():
 | 
				
			||||||
 | 
					    # Arrange
 | 
				
			||||||
 | 
					    image1 = Image.open(file1)
 | 
				
			||||||
 | 
					    image2 = Image.open(file2)
 | 
				
			||||||
 | 
					    new_size = (100, 100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Act
 | 
				
			||||||
 | 
					    image1 = image1.resize(new_size)
 | 
				
			||||||
 | 
					    image2 = image2.resize(new_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Assert
 | 
				
			||||||
 | 
					    assert_equal(image1.size, new_size)
 | 
				
			||||||
 | 
					    assert_equal(image2.size, new_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_thumbnail():
 | 
				
			||||||
 | 
					    # Issue #619
 | 
				
			||||||
 | 
					    # Arrange
 | 
				
			||||||
 | 
					    image1 = Image.open(file1)
 | 
				
			||||||
 | 
					    image2 = Image.open(file2)
 | 
				
			||||||
 | 
					    new_size = (100, 100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Act
 | 
				
			||||||
 | 
					    image1.thumbnail(new_size)
 | 
				
			||||||
 | 
					    image2.thumbnail(new_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Assert
 | 
				
			||||||
 | 
					    assert_equal(max(image1.size), max(new_size))
 | 
				
			||||||
 | 
					    assert_equal(max(image2.size), max(new_size))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_read_binary_preview():
 | 
				
			||||||
 | 
					    # Issue 302
 | 
				
			||||||
 | 
					    # open image with binary preview
 | 
				
			||||||
 | 
					    image1 = Image.open(file3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# End of file
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user