From 5513587bfa1a066d888277d54c17c1f70b4d00fa Mon Sep 17 00:00:00 2001 From: Frankie Dintino Date: Wed, 14 Aug 2024 01:07:51 -0400 Subject: [PATCH] fixup5 --- .github/workflows/macos-install.sh | 3 ++- .github/workflows/test-windows.yml | 4 ++++ .github/workflows/wheels-dependencies.sh | 11 ++++----- Tests/check_wheel.py | 3 ++- Tests/images/avif/star.avifs | Bin 29724 -> 29724 bytes Tests/test_file_avif.py | 28 +++-------------------- depends/install_libavif.sh | 2 +- src/PIL/AvifImagePlugin.py | 10 +++++++- winbuild/Findrav1e.cmake | 12 ++++++---- winbuild/build_prepare.py | 16 ++++++++++++- 10 files changed, 48 insertions(+), 41 deletions(-) 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/test-windows.yml b/.github/workflows/test-windows.yml index de59f025692..c79386c27f0 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -143,6 +143,10 @@ jobs: if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_rav1e.cmd" + - name: Build dependencies / meson + if: steps.build-cache.outputs.cache-hit != 'true' + run: "& winbuild\\build\\install_meson.cmd" + - name: Build dependencies / libavif if: steps.build-cache.outputs.cache-hit != 'true' run: "& winbuild\\build\\build_dep_libavif.cmd" 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 bb9dfa5c33d2489acc17e4bc8f87d242fd354777..f2753395f8c3c131267eb4d1846ca9a21a6a47a3 100644 GIT binary patch delta 16 XcmbR9f^p6Z#tqDjj4Yd37$u4UHKYXx delta 16 XcmbR9f^p6Z#tqDjj0~Gu7$u4UHH-xV diff --git a/Tests/test_file_avif.py b/Tests/test_file_avif.py index f695cc30025..f5c9a18f551 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 @@ -19,7 +20,6 @@ assert_image_similar_tofile, hopper, skip_unless_feature, - skip_unless_feature_version, ) try: @@ -199,7 +199,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): @@ -513,29 +514,6 @@ def test_encoder_codec_available_cannot_decode(self): def test_encoder_codec_available_invalid(self): assert _avif.encoder_codec_available("foo") is False - @skip_unless_feature_version("avif", "1.0.0") - @pytest.mark.parametrize( - "quality,expected_qminmax", - [ - [0, (63, 63)], - [100, (0, 0)], - [90, (0, 10)], - [None, (0, 25)], # default - [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: test_file = str(tmp_path / "temp.avif") 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..06edf230620 100644 --- a/src/PIL/AvifImagePlugin.py +++ b/src/PIL/AvifImagePlugin.py @@ -54,6 +54,13 @@ def load_seek(self, pos: int) -> None: pass def _open(self): + if not SUPPORTED: + msg = ( + "image file could not be identified because AVIF " + "support not installed" + ) + raise SyntaxError(msg) + self._decoder = _avif.AvifDecoder( self.fp.read(), DECODE_CODEC_CHOICE, CHROMA_UPSAMPLING, DEFAULT_MAX_THREADS ) @@ -124,7 +131,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..06e907111ff 100644 --- a/winbuild/Findrav1e.cmake +++ b/winbuild/Findrav1e.cmake @@ -1,7 +1,9 @@ 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) +target_link_libraries(rav1e::rav1e ntdll.lib userenv.lib ws2_32.lib bcrypt.lib) diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index bbe401405b8..385ddf51c06 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -122,6 +122,7 @@ def cmd_msbuild( "TIFF": "4.6.0", "XZ": "5.4.5", "ZLIB": "1.3.1", + "MESON": "1.5.1", "LIBAVIF": "1.1.1", "RAV1E": "0.7.1", } @@ -674,12 +675,15 @@ def build_dep(name: str, prefs: dict[str, str], verbose: bool) -> str: def build_dep_all(disabled: list[str], prefs: dict[str, str], verbose: bool) -> None: lines = [r'call "{build_dir}\build_env.cmd"'] gha_groups = "GITHUB_ACTIONS" in os.environ + scripts = ["install_meson.cmd"] for dep_name in DEPS: print() if dep_name in disabled: print(f"Skipping disabled dependency {dep_name}") continue - script = build_dep(dep_name, prefs, verbose) + scripts.append(build_dep(dep_name, prefs, verbose)) + + for script in scripts: if gha_groups: lines.append(f"@echo ::group::Running {script}") lines.append(rf'cmd.exe /c "{{build_dir}}\{script}"') @@ -828,6 +832,16 @@ def main() -> None: print() write_script(".gitignore", ["*"], prefs, args.verbose) + write_script( + "install_meson.cmd", + [ + r'call "{build_dir}\build_env.cmd"', + "@echo " + ("=" * 70), + f"@echo ==== {'Building meson':<60} ====", + "@echo " + ("=" * 70), + f"python -mpip install meson=={V['MESON']}", + ], + ) build_env(prefs, args.verbose) build_dep_all(disabled, prefs, args.verbose)