diff --git a/.github/workflows/macos-install.sh b/.github/workflows/macos-install.sh index 25b6983b1a0..d7b54a588d3 100755 --- a/.github/workflows/macos-install.sh +++ b/.github/workflows/macos-install.sh @@ -13,7 +13,8 @@ brew install \ webp \ dav1d \ aom \ - rav1e + rav1e \ + ninja if [[ "$ImageOS" == "macos13" ]]; then brew install --ignore-dependencies libraqm else diff --git a/.github/workflows/wheels-dependencies.sh b/.github/workflows/wheels-dependencies.sh index 218b6770dcf..d0a0590991b 100755 --- a/.github/workflows/wheels-dependencies.sh +++ b/.github/workflows/wheels-dependencies.sh @@ -82,9 +82,8 @@ function install_rav1e { fi # Force libavif to treat system rav1e as if it were local - local cmake=$(get_modern_cmake) - local cmake_root=`$cmake --system-information 2>&1 | grep CMAKE_ROOT | grep -v CMAKE_ROOT:INTERNAL | sed -e s/\"//g -e 's/CMAKE_ROOT //g'` - cat < $cmake_root/Modules/Findrav1e.cmake + mkdir -p /tmp/cmake/Modules + cat < /tmp/cmake/Modules/Findrav1e.cmake add_library(rav1e::rav1e STATIC IMPORTED GLOBAL) set_target_properties(rav1e::rav1e PROPERTIES IMPORTED_LOCATION "$BUILD_PREFIX/lib/librav1e.a" @@ -118,7 +117,7 @@ function build_libavif { -DAVIF_CODEC_DAV1D=LOCAL \ -DAVIF_CODEC_SVT=LOCAL \ -DENABLE_NASM=ON \ - -DCMAKE_MACOSX_RPATH=OFF \ + -DCMAKE_MODULE_PATH=/tmp/cmake/Modules \ . \ && make install) @@ -209,11 +208,11 @@ if [[ -n "$IS_MACOS" ]]; then # remove webp and zstd to avoid inclusion on x86_64 # remove aom and libavif to fix building on arm64 # curl from brew requires zstd, use system curl - brew remove --ignore-dependencies libpng libtiff libxcb libxau libxdmcp curl cairo lcms2 zstd aom libavif + brew remove --ignore-dependencies libpng libtiff libxcb libxau libxdmcp curl cairo lcms2 zstd if [[ "$CIBW_ARCHS" == "arm64" ]]; then brew remove --ignore-dependencies jpeg-turbo else - brew remove --ignore-dependencies webp + brew remove --ignore-dependencies webp aom libavif fi brew install pkg-config diff --git a/Tests/check_wheel.py b/Tests/check_wheel.py index 4b91984f58a..ef8798b1aaa 100644 --- a/Tests/check_wheel.py +++ b/Tests/check_wheel.py @@ -6,7 +6,7 @@ def test_wheel_modules() -> None: - expected_modules = {"pil", "tkinter", "freetype2", "littlecms2", "webp"} + expected_modules = {"pil", "tkinter", "freetype2", "littlecms2", "webp", "avif"} # tkinter is not available in cibuildwheel installed CPython on Windows try: @@ -35,6 +35,7 @@ def test_wheel_features() -> None: "harfbuzz", "libjpeg_turbo", "xcb", + "avif", } if sys.platform == "win32": diff --git a/Tests/images/avif/star.avifs b/Tests/images/avif/star.avifs index bb9dfa5c33d..f2753395f8c 100644 Binary files a/Tests/images/avif/star.avifs and b/Tests/images/avif/star.avifs differ diff --git a/Tests/test_file_avif.py b/Tests/test_file_avif.py index f695cc30025..d3e4cef3f59 100644 --- a/Tests/test_file_avif.py +++ b/Tests/test_file_avif.py @@ -3,6 +3,7 @@ import gc import os import re +import warnings import xml.etree.ElementTree from contextlib import contextmanager from io import BytesIO @@ -199,7 +200,8 @@ def test_AvifDecoder_with_invalid_args(self): def test_no_resource_warning(self, tmp_path): with Image.open(TEST_AVIF_FILE) as image: temp_file = str(tmp_path / "temp.avif") - pytest.warns(None, image.save, temp_file) + with warnings.catch_warnings(): + image.save(temp_file) @pytest.mark.parametrize("major_brand", [b"avif", b"avis", b"mif1", b"msf1"]) def test_accept_ftyp_brands(self, major_brand): @@ -524,17 +526,6 @@ def test_encoder_codec_available_invalid(self): [50, (14, 50)], ], ) - def test_encoder_quality_qmin_qmax_map(self, tmp_path, quality, expected_qminmax): - qmin, qmax = expected_qminmax - with Image.open("Tests/images/avif/hopper.avif") as im: - out_quality = BytesIO() - out_qminmax = BytesIO() - im.save(out_qminmax, "AVIF", qmin=qmin, qmax=qmax) - if quality is None: - im.save(out_quality, "AVIF") - else: - im.save(out_quality, "AVIF", quality=quality) - assert len(out_quality.getvalue()) == len(out_qminmax.getvalue()) def test_encoder_quality_valueerror(self, tmp_path): with Image.open("Tests/images/avif/hopper.avif") as im: diff --git a/depends/install_libavif.sh b/depends/install_libavif.sh index 0f63afda32f..09646c4ad78 100755 --- a/depends/install_libavif.sh +++ b/depends/install_libavif.sh @@ -57,6 +57,6 @@ cmake -G Ninja -S . -B build \ -DCMAKE_MACOSX_RPATH=OFF \ "${LIBAVIF_CMAKE_FLAGS[@]}" -ninja -C build install +sudo ninja -C build install popd diff --git a/src/PIL/AvifImagePlugin.py b/src/PIL/AvifImagePlugin.py index 25bc07af39a..7ae3889ba6e 100644 --- a/src/PIL/AvifImagePlugin.py +++ b/src/PIL/AvifImagePlugin.py @@ -124,7 +124,8 @@ def _save(im, fp, filename, save_all=False): qmax = info.get("qmax", -1) quality = info.get("quality", 75) if not isinstance(quality, int) or quality < 0 or quality > 100: - raise ValueError("Invalid quality setting") + msg = "Invalid quality setting" + raise ValueError(msg) duration = info.get("duration", 0) subsampling = info.get("subsampling", "4:2:0") diff --git a/winbuild/Findrav1e.cmake b/winbuild/Findrav1e.cmake index db62bfbbd3a..ea406437229 100644 --- a/winbuild/Findrav1e.cmake +++ b/winbuild/Findrav1e.cmake @@ -1,7 +1,11 @@ file(TO_CMAKE_PATH "${AVIF_RAV1E_ROOT}" RAV1E_ROOT_PATH) add_library(rav1e::rav1e STATIC IMPORTED GLOBAL) -set_target_properties(rav1e::rav1e PROPERTIES - IMPORTED_LOCATION "${RAV1E_ROOT_PATH}/lib/rav1e.lib" - AVIF_LOCAL ON - INTERFACE_INCLUDE_DIRECTORIES "${RAV1E_ROOT_PATH}/inc/rav1e" -) +set_target_properties( + rav1e::rav1e + PROPERTIES IMPORTED_LOCATION "${RAV1E_ROOT_PATH}/lib/rav1e.lib" + AVIF_LOCAL ON + INTERFACE_INCLUDE_DIRECTORIES "${RAV1E_ROOT_PATH}/inc/rav1e" + IMPORTED_SONAME rav1e + INTERFACE_LINK_LIBRARIES ntdll.lib + userenv.lib ws2_32.lib + bcrypt.lib)