Compare commits

...

12 Commits
main ... 5.4.x

Author SHA1 Message Date
Hugo
f38f01bbe3 5.4.1 version bump 2019-01-06 14:12:16 +02:00
Hugo van Kemenade
8189bb24fe Apply suggestions from code review
Co-Authored-By: radarhere <3112309+radarhere@users.noreply.github.com>
2019-01-06 13:19:09 +02:00
Andrew Murray
876e7b36a1 Added release notes for #3540 [ci skip] 2019-01-06 13:19:05 +02:00
Hugo
35c7a554ce 5.5.0 changes irrelevant here 2019-01-06 13:13:43 +02:00
Hugo van Kemenade
1ce66a22b8 Update CHANGES.rst
[CI skip]
2019-01-06 13:12:54 +02:00
Hugo van Kemenade
bafb7e8587 Update CHANGES.rst 2019-01-06 13:12:29 +02:00
Andrew Murray
eabc600690 Updated release notes [ci skip] 2019-01-06 13:09:41 +02:00
Hugo
24636d8a36 Add 5.4.1 release notes 2019-01-06 13:09:37 +02:00
Andrew Murray
194f599f27 Only close __fp if not fp 2019-01-06 12:54:58 +02:00
Andrew Murray
f073be52dc Handle IDAT chunks after image end 2019-01-05 20:00:52 +02:00
Pedro Lacerda
3fdd7002a9 Fix build for Termux
`_find_library_dirs_ldconfig` can return an empty list when `ldconfig` is missing, then `setup.py` can continue guessing library directories.

fixes #3526
2019-01-05 19:33:51 +02:00
Andrew Murray
2ad96b038c Detect whether mimetype is image/png or image/apng 2019-01-05 19:27:16 +02:00
20 changed files with 93 additions and 16 deletions

View File

@ -2,6 +2,21 @@
Changelog (Pillow)
==================
5.4.1 (2019-01-06)
------------------
- File closing: Only close __fp if not fp #3540
[radarhere]
- Fix build for Termux #3529
[pslacerda]
- PNG: Detect MIME types #3525
[radarhere]
- PNG: Handle IDAT chunks after image end #3532
[radarhere]
5.4.0 (2019-01-01)
------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

View File

@ -86,6 +86,7 @@ class TestFilePng(PillowTestCase):
self.assertEqual(im.mode, "RGB")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "PNG")
self.assertEqual(im.get_format_mimetype(), 'image/png')
hopper("1").save(test_file)
Image.open(test_file)
@ -585,10 +586,16 @@ class TestFilePng(PillowTestCase):
self.assertIsInstance(im.text, dict)
ImageFile.LOAD_TRUNCATED_IMAGES = False
# Raises an EOFError in load_end
im = Image.open("Tests/images/hopper_idat_after_image_end.png")
self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})
@unittest.skipUnless(HAVE_WEBP and _webp.HAVE_WEBPANIM,
"WebP support not installed with animation")
def test_apng(self):
im = Image.open("Tests/images/iss634.apng")
self.assertEqual(im.get_format_mimetype(), 'image/apng')
expected = Image.open("Tests/images/iss634.webp")
self.assert_image_similar(im, expected, 0.23)

View File

@ -220,6 +220,10 @@ class TestFileTiff(PillowTestCase):
self.assertEqual(
im.getextrema(), (-3.140936851501465, 3.140684127807617))
def test_unknown_pixel_mode(self):
self.assertRaises(
IOError, Image.open, 'Tests/images/hopper_unknown_pixel_mode.tif')
def test_n_frames(self):
for path, n_frames in [
['Tests/images/multipage-lastframe.tif', 1],

View File

@ -0,0 +1,36 @@
5.4.1
-----
This release fixes regressions in 5.4.0.
Installation on Termux
^^^^^^^^^^^^^^^^^^^^^^
A change to the way Pillow detects libraries during installed prevented
installation on Termux, which does not have ``/sbin/ldconfig``. This is now
fixed.
PNG: Handle IDAT chunks after image end
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Some PNG images have multiple IDAT chunks. In some cases, Pillow will stop
reading image data before the IDAT chunks finish. A regression caused an
``EOFError`` exception when previously there was none. This is now fixed, and
file reading continues in case there are subsequent text chunks.
PNG: MIME type
^^^^^^^^^^^^^^
The addition of limited APNG support to the PNG plugin also overwrote the MIME
type for PNG files, causing "image/apng" to be returned as the MIME type of
both APNG and PNG files. This has been fixed so the MIME type of PNG files is
"image/png".
File closing
^^^^^^^^^^^^
A regression caused an unsupported image file to report a
``ValueError: seek of closed file`` exception instead of an ``OSError``. This
has been fixed by ensuring that image plugins only close their internal ``__fp``
if they are not the same as ``ImageFile``'s ``fp``, allowing each to manage their own
file pointers.

View File

@ -6,6 +6,7 @@ Release Notes
.. toctree::
:maxdepth: 2
5.4.1
5.4.0
5.3.0
5.2.0

View File

@ -111,7 +111,7 @@ def _find_library_dirs_ldconfig():
stdout=subprocess.PIPE,
env=env)
except OSError: # E.g. command not found
return None
return []
[data, _] = p.communicate()
if isinstance(data, bytes):
data = data.decode()

View File

@ -83,7 +83,8 @@ class DcxImageFile(PcxImageFile):
def _close__fp(self):
try:
self.__fp.close()
if self.__fp != self.fp:
self.__fp.close()
except AttributeError:
pass
finally:

View File

@ -159,7 +159,8 @@ class FliImageFile(ImageFile.ImageFile):
def _close__fp(self):
try:
self.__fp.close()
if self.__fp != self.fp:
self.__fp.close()
except AttributeError:
pass
finally:

View File

@ -304,7 +304,8 @@ class GifImageFile(ImageFile.ImageFile):
def _close__fp(self):
try:
self.__fp.close()
if self.__fp != self.fp:
self.__fp.close()
except AttributeError:
pass
finally:

View File

@ -292,7 +292,8 @@ class ImImageFile(ImageFile.ImageFile):
def _close__fp(self):
try:
self.__fp.close()
if self.__fp != self.fp:
self.__fp.close()
except AttributeError:
pass
finally:

View File

@ -594,10 +594,10 @@ class Image(object):
:ref:`file-handling` for more information.
"""
try:
self.fp.close()
self.fp = None
if hasattr(self, "_close__fp"):
self._close__fp()
self.fp.close()
self.fp = None
except Exception as msg:
logger.debug("Error closing: %s", msg)
@ -611,12 +611,12 @@ class Image(object):
if sys.version_info.major >= 3:
def __del__(self):
if hasattr(self, "_close__fp"):
self._close__fp()
if (hasattr(self, 'fp') and hasattr(self, '_exclusive_fp')
and self.fp and self._exclusive_fp):
self.fp.close()
self.fp = None
if hasattr(self, "_close__fp"):
self._close__fp()
def _copy(self):
self.load()

View File

@ -79,6 +79,8 @@ class ImageFile(Image.Image):
self._min_frame = 0
self.custom_mimetype = None
self.tile = None
self.readonly = 1 # until we know better
@ -120,7 +122,7 @@ class ImageFile(Image.Image):
def get_format_mimetype(self):
if self.format is None:
return
return Image.MIME.get(self.format.upper())
return self.custom_mimetype or Image.MIME.get(self.format.upper())
def verify(self):
"Check file integrity"

View File

@ -99,7 +99,8 @@ class MicImageFile(TiffImagePlugin.TiffImageFile):
def _close__fp(self):
try:
self.__fp.close()
if self.__fp != self.fp:
self.__fp.close()
except AttributeError:
pass
finally:

View File

@ -86,7 +86,8 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
def _close__fp(self):
try:
self.__fp.close()
if self.__fp != self.fp:
self.__fp.close()
except AttributeError:
pass
finally:

View File

@ -296,6 +296,7 @@ class PngStream(ChunkStream):
self.im_mode = None
self.im_tile = None
self.im_palette = None
self.im_custom_mimetype = None
self.text_memory = 0
@ -529,6 +530,7 @@ class PngStream(ChunkStream):
# APNG chunks
def chunk_acTL(self, pos, length):
s = ImageFile._safe_read(self.fp, length)
self.im_custom_mimetype = 'image/apng'
return s
def chunk_fcTL(self, pos, length):
@ -594,6 +596,7 @@ class PngImageFile(ImageFile.ImageFile):
self.info = self.png.im_info
self._text = None
self.tile = self.png.im_tile
self.custom_mimetype = self.png.im_custom_mimetype
if self.png.im_palette:
rawmode, data = self.png.im_palette
@ -677,6 +680,8 @@ class PngImageFile(ImageFile.ImageFile):
self.png.call(cid, pos, length)
except UnicodeDecodeError:
break
except EOFError:
ImageFile._safe_read(self.fp, length)
self._text = self.png.im_text
self.png.close()
self.png = None
@ -908,4 +913,3 @@ Image.register_save(PngImageFile.format, _save)
Image.register_extensions(PngImageFile.format, [".png", ".apng"])
Image.register_mime(PngImageFile.format, "image/png")
Image.register_mime(PngImageFile.format, "image/apng")

View File

@ -195,7 +195,8 @@ class SpiderImageFile(ImageFile.ImageFile):
def _close__fp(self):
try:
self.__fp.close()
if self.__fp != self.fp:
self.__fp.close()
except AttributeError:
pass
finally:

View File

@ -1361,7 +1361,8 @@ class TiffImageFile(ImageFile.ImageFile):
def _close__fp(self):
try:
self.__fp.close()
if self.__fp != self.fp:
self.__fp.close()
except AttributeError:
pass
finally:

View File

@ -1,2 +1,2 @@
# Master version for Pillow
__version__ = '5.4.0'
__version__ = '5.4.1'