Merge branch 'main' into png_iccp

This commit is contained in:
Andrew Murray 2024-02-29 22:58:15 +11:00 committed by GitHub
commit b80b30d2fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 121 additions and 45 deletions

View File

@ -6,6 +6,7 @@ init:
# Uncomment previous line to get RDP access during the build. # Uncomment previous line to get RDP access during the build.
environment: environment:
COVERAGE_CORE: sysmon
EXECUTABLE: python.exe EXECUTABLE: python.exe
TEST_OPTIONS: TEST_OPTIONS:
DEPLOY: YES DEPLOY: YES

View File

@ -26,6 +26,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
env:
COVERAGE_CORE: sysmon
jobs: jobs:
build: build:
runs-on: windows-latest runs-on: windows-latest

View File

@ -26,6 +26,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
env:
COVERAGE_CORE: sysmon
jobs: jobs:
build: build:
runs-on: windows-latest runs-on: windows-latest

View File

@ -26,6 +26,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
env:
COVERAGE_CORE: sysmon
jobs: jobs:
build: build:
runs-on: windows-latest runs-on: windows-latest
@ -66,8 +69,16 @@ jobs:
- name: Print build system information - name: Print build system information
run: python3 .github/workflows/system-info.py run: python3 .github/workflows/system-info.py
- name: python3 -m pip install pytest pytest-cov pytest-timeout defusedxml olefile pyroma - name: Install Python dependencies
run: python3 -m pip install pytest pytest-cov pytest-timeout defusedxml olefile pyroma run: >
python3 -m pip install
coverage>=7.4.2
defusedxml
olefile
pyroma
pytest
pytest-cov
pytest-timeout
- name: Install dependencies - name: Install dependencies
id: install id: install

View File

@ -27,6 +27,7 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
env: env:
COVERAGE_CORE: sysmon
FORCE_COLOR: 1 FORCE_COLOR: 1
jobs: jobs:

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)
------------------- -------------------
- Release GIL while calling ``WebPAnimDecoderGetNext`` #7782
[evanmiller, radarhere]
- Fixed reading FLI/FLC images with a prefix chunk #7804
[twolife]
- Update wl-paste handling and return None for some errors in grabclipboard() on Linux #7745 - Update wl-paste handling and return None for some errors in grabclipboard() on Linux #7745
[nik012003, radarhere] [nik012003, 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

BIN
Tests/images/2422.flc Normal file

Binary file not shown.

View File

@ -4,7 +4,7 @@ import warnings
import pytest import pytest
from PIL import FliImagePlugin, Image from PIL import FliImagePlugin, Image, ImageFile
from .helper import assert_image_equal, assert_image_equal_tofile, is_pypy from .helper import assert_image_equal, assert_image_equal_tofile, is_pypy
@ -12,9 +12,12 @@ from .helper import assert_image_equal, assert_image_equal_tofile, is_pypy
# save as...-> hopper.fli, default options. # save as...-> hopper.fli, default options.
static_test_file = "Tests/images/hopper.fli" static_test_file = "Tests/images/hopper.fli"
# From https://samples.libav.org/fli-flc/ # From https://samples.ffmpeg.org/fli-flc/
animated_test_file = "Tests/images/a.fli" animated_test_file = "Tests/images/a.fli"
# From https://samples.ffmpeg.org/fli-flc/
animated_test_file_with_prefix_chunk = "Tests/images/2422.flc"
def test_sanity() -> None: def test_sanity() -> None:
with Image.open(static_test_file) as im: with Image.open(static_test_file) as im:
@ -32,6 +35,24 @@ def test_sanity() -> None:
assert im.is_animated assert im.is_animated
def test_prefix_chunk() -> None:
ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
with Image.open(animated_test_file_with_prefix_chunk) as im:
assert im.mode == "P"
assert im.size == (320, 200)
assert im.format == "FLI"
assert im.info["duration"] == 171
assert im.is_animated
palette = im.getpalette()
assert palette[3:6] == [255, 255, 255]
assert palette[381:384] == [204, 204, 12]
assert palette[765:] == [252, 0, 0]
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False
@pytest.mark.skipif(is_pypy(), reason="Requires CPython") @pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file() -> None: def test_unclosed_file() -> None:
def open() -> None: def open() -> None:

View File

@ -685,15 +685,18 @@ 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)),
]: ),
im = Image.new("P", (100, 100), color) )
expected = Image.new(mode, (100, 100), color) def test_p_from_rgb_rgba(self, mode: str, color: str | tuple[int, ...]) -> None:
assert_image_equal(im.convert(mode), expected) im = Image.new("P", (100, 100), color)
expected = Image.new(mode, (100, 100), color)
assert_image_equal(im.convert(mode), expected)
def test_no_resource_warning_on_save(self, tmp_path: Path) -> None: def test_no_resource_warning_on_save(self, tmp_path: Path) -> None:
# https://github.com/python-pillow/Pillow/issues/835 # https://github.com/python-pillow/Pillow/issues/835

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

@ -79,3 +79,9 @@ Portable FloatMap (PFM) images
Support has been added for reading and writing grayscale (Pf format) Support has been added for reading and writing grayscale (Pf format)
Portable FloatMap (PFM) files containing ``F`` data. Portable FloatMap (PFM) files containing ``F`` data.
Release GIL when fetching WebP frames
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Python's Global Interpreter Lock is now released when fetching WebP frames from
the libwebp decoder.

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

@ -77,6 +77,7 @@ class FliImageFile(ImageFile.ImageFile):
if i16(s, 4) == 0xF100: if i16(s, 4) == 0xF100:
# prefix chunk; ignore it # prefix chunk; ignore it
self.__offset = self.__offset + i32(s) self.__offset = self.__offset + i32(s)
self.fp.seek(self.__offset)
s = self.fp.read(16) s = self.fp.read(16)
if i16(s, 4) == 0xF1FA: if i16(s, 4) == 0xF1FA:

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

@ -448,11 +448,16 @@ PyObject *
_anim_decoder_get_next(PyObject *self) { _anim_decoder_get_next(PyObject *self) {
uint8_t *buf; uint8_t *buf;
int timestamp; int timestamp;
int ok;
PyObject *bytes; PyObject *bytes;
PyObject *ret; PyObject *ret;
ImagingSectionCookie cookie;
WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self; WebPAnimDecoderObject *decp = (WebPAnimDecoderObject *)self;
if (!WebPAnimDecoderGetNext(decp->dec, &buf, &timestamp)) { ImagingSectionEnter(&cookie);
ok = WebPAnimDecoderGetNext(decp->dec, &buf, &timestamp);
ImagingSectionLeave(&cookie);
if (!ok) {
PyErr_SetString(PyExc_OSError, "failed to read next frame"); PyErr_SetString(PyExc_OSError, "failed to read next frame");
return NULL; return NULL;
} }

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"],
}, },