Merge branch 'main' into main

This commit is contained in:
Andrew Murray 2024-03-01 22:33:09 +11:00 committed by GitHub
commit 7268920b06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 100 additions and 45 deletions

View File

@ -67,10 +67,10 @@ jobs:
mingw-w64-x86_64-python3-cffi \ mingw-w64-x86_64-python3-cffi \
mingw-w64-x86_64-python3-numpy \ mingw-w64-x86_64-python3-numpy \
mingw-w64-x86_64-python3-olefile \ mingw-w64-x86_64-python3-olefile \
mingw-w64-x86_64-python3-pip \
mingw-w64-x86_64-python3-setuptools \ mingw-w64-x86_64-python3-setuptools \
mingw-w64-x86_64-python-pyqt6 mingw-w64-x86_64-python-pyqt6
python3 -m ensurepip
python3 -m pip install pyroma pytest pytest-cov pytest-timeout python3 -m pip install pyroma pytest pytest-cov pytest-timeout
pushd depends && ./install_extra_test_images.sh && popd pushd depends && ./install_extra_test_images.sh && popd

View File

@ -19,7 +19,7 @@ FREETYPE_VERSION=2.13.2
HARFBUZZ_VERSION=8.3.0 HARFBUZZ_VERSION=8.3.0
LIBPNG_VERSION=1.6.40 LIBPNG_VERSION=1.6.40
JPEGTURBO_VERSION=3.0.1 JPEGTURBO_VERSION=3.0.1
OPENJPEG_VERSION=2.5.0 OPENJPEG_VERSION=2.5.2
XZ_VERSION=5.4.5 XZ_VERSION=5.4.5
TIFF_VERSION=4.6.0 TIFF_VERSION=4.6.0
LCMS2_VERSION=2.16 LCMS2_VERSION=2.16
@ -40,7 +40,7 @@ BROTLI_VERSION=1.1.0
if [[ -n "$IS_MACOS" ]] && [[ "$CIBW_ARCHS" == "x86_64" ]]; then if [[ -n "$IS_MACOS" ]] && [[ "$CIBW_ARCHS" == "x86_64" ]]; then
function build_openjpeg { function build_openjpeg {
local out_dir=$(fetch_unpack https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz openjpeg-2.5.0.tar.gz) local out_dir=$(fetch_unpack https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz openjpeg-${OPENJPEG_VERSION}.tar.gz)
(cd $out_dir \ (cd $out_dir \
&& cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \ && cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib . \
&& make install) && make install)
@ -93,6 +93,9 @@ function build {
done done
fi fi
build_openjpeg build_openjpeg
if [ -f /usr/local/lib64/libopenjp2.so ]; then
cp /usr/local/lib64/libopenjp2.so /usr/local/lib
fi
ORIGINAL_CFLAGS=$CFLAGS ORIGINAL_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -O3 -DNDEBUG" CFLAGS="$CFLAGS -O3 -DNDEBUG"

View File

@ -5,6 +5,12 @@ Changelog (Pillow)
10.3.0 (unreleased) 10.3.0 (unreleased)
------------------- -------------------
- Handle truncated chunks at the end of PNG images #7709
[lajiyuan, radarhere]
- Match mask size to pasted image size in GifImagePlugin #7779
[radarhere]
- Release GIL while calling ``WebPAnimDecoderGetNext`` #7782 - Release GIL while calling ``WebPAnimDecoderGetNext`` #7782
[evanmiller, radarhere] [evanmiller, radarhere]

View File

@ -82,9 +82,6 @@ As of 2019, Pillow development is
<a href="https://gitter.im/python-pillow/Pillow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img <a href="https://gitter.im/python-pillow/Pillow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img
alt="Join the chat at https://gitter.im/python-pillow/Pillow" alt="Join the chat at https://gitter.im/python-pillow/Pillow"
src="https://badges.gitter.im/python-pillow/Pillow.svg"></a> src="https://badges.gitter.im/python-pillow/Pillow.svg"></a>
<a href="https://twitter.com/PythonPillow"><img
alt="Follow on https://twitter.com/PythonPillow"
src="https://img.shields.io/badge/tweet-on%20Twitter-00aced.svg"></a>
<a href="https://fosstodon.org/@pillow"><img <a href="https://fosstodon.org/@pillow"><img
alt="Follow on https://fosstodon.org/@pillow" alt="Follow on https://fosstodon.org/@pillow"
src="https://img.shields.io/badge/publish-on%20Mastodon-595aff.svg" src="https://img.shields.io/badge/publish-on%20Mastodon-595aff.svg"

View File

@ -86,7 +86,7 @@ Released as needed privately to individual vendors for critical security-related
## Publicize Release ## Publicize Release
* [ ] Announce release availability via [Twitter](https://twitter.com/pythonpillow) and [Mastodon](https://fosstodon.org/@pillow) e.g. https://twitter.com/PythonPillow/status/1013789184354603010 * [ ] Announce release availability via [Mastodon](https://fosstodon.org/@pillow) e.g. https://fosstodon.org/@pillow/110639450470725321
## Documentation ## Documentation

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1113,6 +1113,21 @@ def test_append_images(tmp_path: Path) -> None:
assert reread.n_frames == 10 assert reread.n_frames == 10
def test_append_different_size_image(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = Image.new("RGB", (100, 100))
bigger_im = Image.new("RGB", (200, 200), "#f00")
im.save(out, save_all=True, append_images=[bigger_im])
with Image.open(out) as reread:
assert reread.size == (100, 100)
reread.seek(1)
assert reread.size == (100, 100)
def test_transparent_optimize(tmp_path: Path) -> None: def test_transparent_optimize(tmp_path: Path) -> None:
# From issue #2195, if the transparent color is incorrectly optimized out, GIF loses # From issue #2195, if the transparent color is incorrectly optimized out, GIF loses
# transparency. # transparency.

View File

@ -783,6 +783,18 @@ class TestFilePng:
with Image.open(mystdout) as reloaded: with Image.open(mystdout) as reloaded:
assert_image_equal_tofile(reloaded, TEST_PNG_FILE) assert_image_equal_tofile(reloaded, TEST_PNG_FILE)
def test_truncated_end_chunk(self) -> None:
with Image.open("Tests/images/truncated_end_chunk.png") as im:
with pytest.raises(OSError):
im.load()
ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
with Image.open("Tests/images/truncated_end_chunk.png") as im:
assert_image_equal_tofile(im, "Tests/images/hopper.png")
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False
@pytest.mark.skipif(is_win32(), reason="Requires Unix or macOS") @pytest.mark.skipif(is_win32(), reason="Requires Unix or macOS")
@skip_unless_feature("zlib") @skip_unless_feature("zlib")

View File

@ -685,12 +685,15 @@ class TestImage:
_make_new(im, blank_p, ImagePalette.ImagePalette()) _make_new(im, blank_p, ImagePalette.ImagePalette())
_make_new(im, blank_pa, ImagePalette.ImagePalette()) _make_new(im, blank_pa, ImagePalette.ImagePalette())
def test_p_from_rgb_rgba(self) -> None: @pytest.mark.parametrize(
for mode, color in [ "mode, color",
(
("RGB", "#DDEEFF"), ("RGB", "#DDEEFF"),
("RGB", (221, 238, 255)), ("RGB", (221, 238, 255)),
("RGBA", (221, 238, 255, 255)), ("RGBA", (221, 238, 255, 255)),
]: ),
)
def test_p_from_rgb_rgba(self, mode: str, color: str | tuple[int, ...]) -> None:
im = Image.new("P", (100, 100), color) im = Image.new("P", (100, 100), color)
expected = Image.new(mode, (100, 100), color) expected = Image.new(mode, (100, 100), color)
assert_image_equal(im.convert(mode), expected) assert_image_equal(im.convert(mode), expected)

View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# install openjpeg # install openjpeg
archive=openjpeg-2.5.0 archive=openjpeg-2.5.2
./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/main/$archive.tar.gz ./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/main/$archive.tar.gz

View File

@ -504,3 +504,27 @@ PIL.OleFileIO
the upstream :pypi:`olefile` Python package, and replaced with an :py:exc:`ImportError` in 5.0.0 the upstream :pypi:`olefile` Python package, and replaced with an :py:exc:`ImportError` in 5.0.0
(2018-01). The deprecated file has now been removed from Pillow. If needed, install from (2018-01). The deprecated file has now been removed from Pillow. If needed, install from
PyPI (eg. ``python3 -m pip install olefile``). PyPI (eg. ``python3 -m pip install olefile``).
import _imaging
~~~~~~~~~~~~~~~
.. versionremoved:: 2.1.0
Pillow >= 2.1.0 no longer supports ``import _imaging``.
Please use ``from PIL.Image import core as _imaging`` instead.
Pillow and PIL
~~~~~~~~~~~~~~
.. versionremoved:: 1.0.0
Pillow and PIL cannot co-exist in the same environment.
Before installing Pillow, please uninstall PIL.
import Image
~~~~~~~~~~~~
.. versionremoved:: 1.0.0
Pillow >= 1.0 no longer supports ``import Image``.
Please use ``from PIL import Image`` instead.

View File

@ -73,10 +73,6 @@ Pillow for enterprise is available via the Tidelift Subscription. `Learn more <h
:target: https://gitter.im/python-pillow/Pillow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge :target: https://gitter.im/python-pillow/Pillow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
:alt: Join the chat at https://gitter.im/python-pillow/Pillow :alt: Join the chat at https://gitter.im/python-pillow/Pillow
.. image:: https://img.shields.io/badge/tweet-on%20Twitter-00aced.svg
:target: https://twitter.com/PythonPillow
:alt: Follow on https://twitter.com/PythonPillow
.. image:: https://img.shields.io/badge/publish-on%20Mastodon-595aff.svg .. image:: https://img.shields.io/badge/publish-on%20Mastodon-595aff.svg
:target: https://fosstodon.org/@pillow :target: https://fosstodon.org/@pillow
:alt: Follow on https://fosstodon.org/@pillow :alt: Follow on https://fosstodon.org/@pillow

View File

@ -9,15 +9,6 @@ Installation
}); });
</script> </script>
Warnings
--------
.. warning:: Pillow and PIL cannot co-exist in the same environment. Before installing Pillow, please uninstall PIL.
.. warning:: Pillow >= 1.0 no longer supports ``import Image``. Please use ``from PIL import Image`` instead.
.. warning:: Pillow >= 2.1.0 no longer supports ``import _imaging``. Please use ``from PIL.Image import core as _imaging`` instead.
Python Support Python Support
-------------- --------------
@ -186,7 +177,7 @@ Many of Pillow's features require external libraries:
* **openjpeg** provides JPEG 2000 functionality. * **openjpeg** provides JPEG 2000 functionality.
* Pillow has been tested with openjpeg **2.0.0**, **2.1.0**, **2.3.1**, * Pillow has been tested with openjpeg **2.0.0**, **2.1.0**, **2.3.1**,
**2.4.0** and **2.5.0**. **2.4.0**, **2.5.0** and **2.5.2**.
* Pillow does **not** support the earlier **1.5** series which ships * Pillow does **not** support the earlier **1.5** series which ships
with Debian Jessie. with Debian Jessie.

View File

@ -14,6 +14,8 @@ only work on L and RGB images.
.. autofunction:: colorize .. autofunction:: colorize
.. autofunction:: crop .. autofunction:: crop
.. autofunction:: scale .. autofunction:: scale
.. autoclass:: SupportsGetMesh
:show-inheritance:
.. autofunction:: deform .. autofunction:: deform
.. autofunction:: equalize .. autofunction:: equalize
.. autofunction:: expand .. autofunction:: expand

View File

@ -80,7 +80,6 @@ Homepage = "https://python-pillow.org"
Mastodon = "https://fosstodon.org/@pillow" Mastodon = "https://fosstodon.org/@pillow"
"Release notes" = "https://pillow.readthedocs.io/en/stable/releasenotes/index.html" "Release notes" = "https://pillow.readthedocs.io/en/stable/releasenotes/index.html"
Source = "https://github.com/python-pillow/Pillow" Source = "https://github.com/python-pillow/Pillow"
Twitter = "https://twitter.com/PythonPillow"
[tool.setuptools] [tool.setuptools]
packages = ["PIL"] packages = ["PIL"]

View File

@ -649,9 +649,7 @@ def _write_multiple_frames(im, fp, palette):
if "transparency" in encoderinfo: if "transparency" in encoderinfo:
# When the delta is zero, fill the image with transparency # When the delta is zero, fill the image with transparency
diff_frame = im_frame.copy() diff_frame = im_frame.copy()
fill = Image.new( fill = Image.new("P", delta.size, encoderinfo["transparency"])
"P", diff_frame.size, encoderinfo["transparency"]
)
if delta.mode == "RGBA": if delta.mode == "RGBA":
r, g, b, a = delta.split() r, g, b, a = delta.split()
mask = ImageMath.eval( mask = ImageMath.eval(

View File

@ -411,7 +411,15 @@ def scale(
return image.resize(size, resample) return image.resize(size, resample)
class _SupportsGetMesh(Protocol): class SupportsGetMesh(Protocol):
"""
An object that supports the ``getmesh`` method, taking an image as an
argument, and returning a list of tuples. Each tuple contains two tuples,
the source box as a tuple of 4 integers, and a tuple of 8 integers for the
final quadrilateral, in order of top left, bottom left, bottom right, top
right.
"""
def getmesh( def getmesh(
self, image: Image.Image self, image: Image.Image
) -> list[ ) -> list[
@ -421,7 +429,7 @@ class _SupportsGetMesh(Protocol):
def deform( def deform(
image: Image.Image, image: Image.Image,
deformer: _SupportsGetMesh, deformer: SupportsGetMesh,
resample: int = Image.Resampling.BILINEAR, resample: int = Image.Resampling.BILINEAR,
) -> Image.Image: ) -> Image.Image:
""" """

View File

@ -981,7 +981,13 @@ class PngImageFile(ImageFile.ImageFile):
except EOFError: except EOFError:
if cid == b"fdAT": if cid == b"fdAT":
length -= 4 length -= 4
try:
ImageFile._safe_read(self.fp, length) ImageFile._safe_read(self.fp, length)
except OSError as e:
if ImageFile.LOAD_TRUNCATED_IMAGES:
break
else:
raise e
except AttributeError: except AttributeError:
logger.debug("%r %s %s (unknown)", cid, pos, length) logger.debug("%r %s %s (unknown)", cid, pos, length)
s = ImageFile._safe_read(self.fp, length) s = ImageFile._safe_read(self.fp, length)

View File

@ -308,21 +308,16 @@ DEPS = {
"libs": [r"Lib\MS\*.lib"], "libs": [r"Lib\MS\*.lib"],
}, },
"openjpeg": { "openjpeg": {
"url": "https://github.com/uclouvain/openjpeg/archive/v2.5.0.tar.gz", "url": "https://github.com/uclouvain/openjpeg/archive/v2.5.2.tar.gz",
"filename": "openjpeg-2.5.0.tar.gz", "filename": "openjpeg-2.5.2.tar.gz",
"dir": "openjpeg-2.5.0", "dir": "openjpeg-2.5.2",
"license": "LICENSE", "license": "LICENSE",
"patch": {
r"src\lib\openjp2\ht_dec.c": {
"#ifdef OPJ_COMPILER_MSVC\n return (OPJ_UINT32)__popcnt(val);": "#if defined(OPJ_COMPILER_MSVC) && (defined(_M_IX86) || defined(_M_AMD64))\n return (OPJ_UINT32)__popcnt(val);", # noqa: E501
}
},
"build": [ "build": [
*cmds_cmake( *cmds_cmake(
"openjp2", "-DBUILD_CODEC:BOOL=OFF", "-DBUILD_SHARED_LIBS:BOOL=OFF" "openjp2", "-DBUILD_CODEC:BOOL=OFF", "-DBUILD_SHARED_LIBS:BOOL=OFF"
), ),
cmd_mkdir(r"{inc_dir}\openjpeg-2.5.0"), cmd_mkdir(r"{inc_dir}\openjpeg-2.5.2"),
cmd_copy(r"src\lib\openjp2\*.h", r"{inc_dir}\openjpeg-2.5.0"), cmd_copy(r"src\lib\openjp2\*.h", r"{inc_dir}\openjpeg-2.5.2"),
], ],
"libs": [r"bin\*.lib"], "libs": [r"bin\*.lib"],
}, },