From e632e43ff273f66a51cf06c3a5ec79d8a75cb027 Mon Sep 17 00:00:00 2001 From: Frankie Dintino Date: Wed, 14 Aug 2024 00:45:53 -0400 Subject: [PATCH] fixup4 --- Tests/check_avif_leaks.py | 2 + Tests/test_file_avif.py | 3 +- src/PIL/AvifImagePlugin.py | 2 + src/_avif.c | 99 ++++++++++++++++++++++---------------- winbuild/build_prepare.py | 63 ++++++++++++++---------- 5 files changed, 102 insertions(+), 67 deletions(-) diff --git a/Tests/check_avif_leaks.py b/Tests/check_avif_leaks.py index 57818efcbee..de6f370d971 100644 --- a/Tests/check_avif_leaks.py +++ b/Tests/check_avif_leaks.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from io import BytesIO import pytest diff --git a/Tests/test_file_avif.py b/Tests/test_file_avif.py index d30b2fdf6a8..f695cc30025 100644 --- a/Tests/test_file_avif.py +++ b/Tests/test_file_avif.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import gc import os import re @@ -5,7 +7,6 @@ from contextlib import contextmanager from io import BytesIO from struct import unpack -from unittest import mock import pytest diff --git a/src/PIL/AvifImagePlugin.py b/src/PIL/AvifImagePlugin.py index c792f8570c7..25bc07af39a 100644 --- a/src/PIL/AvifImagePlugin.py +++ b/src/PIL/AvifImagePlugin.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from io import BytesIO from . import ExifTags, Image, ImageFile diff --git a/src/_avif.c b/src/_avif.c index 74573171d98..5365d38b660 100644 --- a/src/_avif.c +++ b/src/_avif.c @@ -25,8 +25,7 @@ typedef struct { // Encoder type typedef struct { - PyObject_HEAD - avifEncoder *encoder; + PyObject_HEAD avifEncoder *encoder; avifImage *image; PyObject *icc_bytes; PyObject *exif_bytes; @@ -38,8 +37,7 @@ static PyTypeObject AvifEncoder_Type; // Decoder type typedef struct { - PyObject_HEAD - avifDecoder *decoder; + PyObject_HEAD avifDecoder *decoder; PyObject *data; char *mode; } AvifDecoderObject; @@ -89,7 +87,8 @@ init_max_threads(void) { PyErr_Clear(); } PyErr_WarnEx( - PyExc_RuntimeWarning, "could not get cpu count: using max_threads=1", 1); + PyExc_RuntimeWarning, "could not get cpu count: using max_threads=1", 1 + ); goto done; } @@ -146,9 +145,9 @@ exif_orientation_to_irot_imir(avifImage *image, int orientation) { image->transformFlags = otherFlags; image->irot.angle = 0; // ignored #if AVIF_VERSION_MAJOR >= 1 - image->imir.axis = 0; // ignored + image->imir.axis = 0; // ignored #else - image->imir.mode = 0; // ignored + image->imir.mode = 0; // ignored #endif return; case 2: // The 0th row is at the visual top of the image, and the 0th column is @@ -237,9 +236,9 @@ exif_orientation_to_irot_imir(avifImage *image, int orientation) { image->transformFlags = otherFlags; image->irot.angle = 0; // ignored #if AVIF_VERSION_MAJOR >= 1 - image->imir.axis = 0; // ignored + image->imir.axis = 0; // ignored #else - image->imir.mode = 0; // ignored + image->imir.mode = 0; // ignored #endif } @@ -348,7 +347,8 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { &exif_bytes, &exif_orientation, &xmp_bytes, - &advanced)) { + &advanced + )) { return NULL; } @@ -497,7 +497,8 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { avifImageSetProfileICC( image, (uint8_t *)PyBytes_AS_STRING(icc_bytes), - PyBytes_GET_SIZE(icc_bytes)); + PyBytes_GET_SIZE(icc_bytes) + ); } else { image->colorPrimaries = AVIF_COLOR_PRIMARIES_BT709; image->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_SRGB; @@ -509,7 +510,8 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { avifImageSetMetadataExif( image, (uint8_t *)PyBytes_AS_STRING(exif_bytes), - PyBytes_GET_SIZE(exif_bytes)); + PyBytes_GET_SIZE(exif_bytes) + ); } if (PyBytes_GET_SIZE(xmp_bytes)) { self->xmp_bytes = xmp_bytes; @@ -517,7 +519,8 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { avifImageSetMetadataXMP( image, (uint8_t *)PyBytes_AS_STRING(xmp_bytes), - PyBytes_GET_SIZE(xmp_bytes)); + PyBytes_GET_SIZE(xmp_bytes) + ); } exif_orientation_to_irot_imir(image, exif_orientation); @@ -573,7 +576,8 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) { &width, &height, &mode, - &is_single_frame)) { + &is_single_frame + )) { return NULL; } @@ -586,7 +590,8 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) { image->width, image->height, width, - height); + height + ); return NULL; } @@ -632,7 +637,8 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) { rgb.rowBytes, rgb.height, rgb.rowBytes * rgb.height, - size); + size + ); ret = NULL; goto end; } @@ -640,15 +646,15 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) { // rgb.pixels is safe for writes memcpy(rgb.pixels, rgb_bytes, size); - Py_BEGIN_ALLOW_THREADS - result = avifImageRGBToYUV(frame, &rgb); + Py_BEGIN_ALLOW_THREADS result = avifImageRGBToYUV(frame, &rgb); Py_END_ALLOW_THREADS - if (result != AVIF_RESULT_OK) { + if (result != AVIF_RESULT_OK) { PyErr_Format( exc_type_for_avif_result(result), "Conversion to YUV failed: %s", - avifResultToString(result)); + avifResultToString(result) + ); ret = NULL; goto end; } @@ -658,15 +664,16 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) { addImageFlags |= AVIF_ADD_IMAGE_FLAG_SINGLE; } - Py_BEGIN_ALLOW_THREADS - result = avifEncoderAddImage(encoder, frame, duration, addImageFlags); + Py_BEGIN_ALLOW_THREADS result = + avifEncoderAddImage(encoder, frame, duration, addImageFlags); Py_END_ALLOW_THREADS - if (result != AVIF_RESULT_OK) { + if (result != AVIF_RESULT_OK) { PyErr_Format( exc_type_for_avif_result(result), "Failed to encode image: %s", - avifResultToString(result)); + avifResultToString(result) + ); ret = NULL; goto end; } @@ -693,15 +700,15 @@ _encoder_finish(AvifEncoderObject *self) { avifResult result; PyObject *ret = NULL; - Py_BEGIN_ALLOW_THREADS - result = avifEncoderFinish(encoder, &raw); + Py_BEGIN_ALLOW_THREADS result = avifEncoderFinish(encoder, &raw); Py_END_ALLOW_THREADS - if (result != AVIF_RESULT_OK) { + if (result != AVIF_RESULT_OK) { PyErr_Format( exc_type_for_avif_result(result), "Failed to finish encoding: %s", - avifResultToString(result)); + avifResultToString(result) + ); avifRWDataFree(&raw); return NULL; } @@ -727,7 +734,9 @@ AvifDecoderNew(PyObject *self_, PyObject *args) { avifResult result; - if (!PyArg_ParseTuple(args, "Sssi", &avif_bytes, &codec_str, &upsampling_str, &max_threads)) { + if (!PyArg_ParseTuple( + args, "Sssi", &avif_bytes, &codec_str, &upsampling_str, &max_threads + )) { return NULL; } @@ -757,7 +766,8 @@ AvifDecoderNew(PyObject *self_, PyObject *args) { const char *codec_name = avifCodecName(codec, AVIF_CODEC_FLAG_CAN_DECODE); if (codec_name == NULL) { PyErr_Format( - PyExc_ValueError, "AV1 Codec cannot decode: %s", codec_str); + PyExc_ValueError, "AV1 Codec cannot decode: %s", codec_str + ); return NULL; } } @@ -796,7 +806,8 @@ AvifDecoderNew(PyObject *self_, PyObject *args) { avifDecoderSetIOMemory( self->decoder, (uint8_t *)PyBytes_AS_STRING(self->data), - PyBytes_GET_SIZE(self->data)); + PyBytes_GET_SIZE(self->data) + ); result = avifDecoderParse(self->decoder); @@ -804,7 +815,8 @@ AvifDecoderNew(PyObject *self_, PyObject *args) { PyErr_Format( exc_type_for_avif_result(result), "Failed to decode image: %s", - avifResultToString(result)); + avifResultToString(result) + ); avifDecoderDestroy(self->decoder); self->decoder = NULL; Py_DECREF(self); @@ -860,7 +872,8 @@ _decoder_get_info(AvifDecoderObject *self) { self->mode, NULL == icc ? Py_None : icc, NULL == exif ? Py_None : exif, - NULL == xmp ? Py_None : xmp); + NULL == xmp ? Py_None : xmp + ); Py_XDECREF(xmp); Py_XDECREF(exif); @@ -894,7 +907,8 @@ _decoder_get_frame(AvifDecoderObject *self, PyObject *args) { exc_type_for_avif_result(result), "Failed to decode frame %u: %s", decoder->imageIndex + 1, - avifResultToString(result)); + avifResultToString(result) + ); return NULL; } @@ -921,15 +935,15 @@ _decoder_get_frame(AvifDecoderObject *self, PyObject *args) { avifRGBImageAllocatePixels(&rgb); - Py_BEGIN_ALLOW_THREADS - result = avifImageYUVToRGB(image, &rgb); + Py_BEGIN_ALLOW_THREADS result = avifImageYUVToRGB(image, &rgb); Py_END_ALLOW_THREADS - if (result != AVIF_RESULT_OK) { + if (result != AVIF_RESULT_OK) { PyErr_Format( exc_type_for_avif_result(result), "Conversion from YUV failed: %s", - avifResultToString(result)); + avifResultToString(result) + ); avifRGBImageFreePixels(&rgb); return NULL; } @@ -944,7 +958,8 @@ _decoder_get_frame(AvifDecoderObject *self, PyObject *args) { bytes, decoder->timescale, decoder->imageTiming.ptsInTimescales, - decoder->imageTiming.durationInTimescales); + decoder->imageTiming.durationInTimescales + ); Py_DECREF(bytes); @@ -1011,7 +1026,8 @@ static PyMethodDef avifMethods[] = { {"AvifCodecVersions", AvifCodecVersions, METH_NOARGS}, {"decoder_codec_available", _decoder_codec_available, METH_VARARGS}, {"encoder_codec_available", _encoder_codec_available, METH_VARARGS}, - {NULL, NULL}}; + {NULL, NULL} +}; static int setup_module(PyObject *m) { @@ -1033,7 +1049,8 @@ setup_module(PyObject *m) { Py_DECREF(v); v = Py_BuildValue( - "(iii)", AVIF_VERSION_MAJOR, AVIF_VERSION_MINOR, AVIF_VERSION_PATCH); + "(iii)", AVIF_VERSION_MAJOR, AVIF_VERSION_MINOR, AVIF_VERSION_PATCH + ); if (PyDict_SetItemString(d, "VERSION", v) < 0) { Py_DECREF(v); diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index eb646556e99..bbe401405b8 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -122,6 +122,8 @@ def cmd_msbuild( "TIFF": "4.6.0", "XZ": "5.4.5", "ZLIB": "1.3.1", + "LIBAVIF": "1.1.1", + "RAV1E": "0.7.1", } V["LIBPNG_DOTLESS"] = V["LIBPNG"].replace(".", "") V["LIBPNG_XY"] = "".join(V["LIBPNG"].split(".")[:2]) @@ -400,12 +402,12 @@ def cmd_msbuild( }, "rav1e": { "url": ( - "https://github.com/xiph/rav1e/releases/download/v0.6.6/" - "rav1e-0.6.6-windows-msvc-generic.zip" + f"https://github.com/xiph/rav1e/releases/download/v{V['RAV1E']}/" + f"rav1e-{V['RAV1E']}-windows-msvc-generic.zip" ), - "filename": "rav1e-0.6.6-windows-msvc-generic.zip", + "filename": f"rav1e-{V['RAV1E']}-windows-msvc-generic.zip", "dir": "rav1e-windows-msvc-sdk", - "license": [], + "license": "LICENSE", "build": [ cmd_xcopy("include", "{inc_dir}"), ], @@ -413,31 +415,41 @@ def cmd_msbuild( "libs": [r"lib\*.*"], }, "libavif": { - "url": ( - "https://github.com/AOMediaCodec/libavif/archive/" - "f9625fc16e29535a0c822108841d30f1b41ce562.zip" - ), - "filename": "libavif-f9625fc16e29535a0c822108841d30f1b41ce562.zip", - "dir": "libavif-f9625fc16e29535a0c822108841d30f1b41ce562", + "url": f"https://github.com/AOMediaCodec/libavif/archive/v{V['LIBAVIF']}.zip", + "filename": f"libavif-{V['LIBAVIF']}.zip", + "dir": f"libavif-{V['LIBAVIF']}", "license": "LICENSE", "build": [ - cmd_cd("ext"), - cmd_rmdir("dav1d"), - 'cmd.exe /c "dav1d.cmd"', - cmd_rmdir("libyuv"), - 'cmd.exe /c "libyuv.cmd"', - cmd_cd(".."), - *cmds_cmake( - "avif", - "-DBUILD_SHARED_LIBS=OFF", - "-DAVIF_LOCAL_LIBYUV=ON", - "-DAVIF_CODEC_RAV1E=ON", - "-DAVIF_CODEC_DAV1D=ON", - "-DAVIF_LOCAL_DAV1D=ON", + cmd_mkdir("build.pillow"), + cmd_cd("build.pillow"), + " ".join( + [ + "{cmake}", + "-DCMAKE_BUILD_TYPE=Release", + "-DCMAKE_VERBOSE_MAKEFILE=ON", + "-DCMAKE_RULE_MESSAGES:BOOL=OFF", # for NMake + "-DCMAKE_C_COMPILER=cl.exe", # for Ninja + "-DCMAKE_CXX_COMPILER=cl.exe", # for Ninja + "-DCMAKE_C_FLAGS=-nologo", + "-DCMAKE_CXX_FLAGS=-nologo", + "-DBUILD_SHARED_LIBS=OFF", + "-DAVIF_CODEC_AOM=LOCAL", + "-DAVIF_LIBYUV=LOCAL", + "-DAVIF_LIBSHARPYUV=LOCAL", + "-DAVIF_CODEC_RAV1E=SYSTEM", + "-DAVIF_RAV1E_ROOT={build_dir}", + "-DCMAKE_MODULE_PATH={winbuild_dir_cmake}", + "-DAVIF_CODEC_DAV1D=LOCAL", + "-DAVIF_CODEC_SVT=LOCAL", + '-G "Ninja"', + "..", + ] ), + "ninja -v", + cmd_cd(".."), cmd_xcopy("include", "{inc_dir}"), ], - "libs": [r"avif.lib"], + "libs": [r"build.pillow\avif.lib"], }, } @@ -786,7 +798,7 @@ def main() -> None: disabled += ["libimagequant"] if args.no_fribidi: disabled += ["fribidi"] - if args.no_avif or args.architecture != "x64": + if args.no_avif or args.architecture == "ARM64": disabled += ["rav1e", "libavif"] prefs = { @@ -794,6 +806,7 @@ def main() -> None: **arch_prefs, # Pillow paths "winbuild_dir": winbuild_dir, + "winbuild_dir_cmake": winbuild_dir.replace("\\", "/"), # Build paths "bin_dir": bin_dir, "build_dir": args.build_dir,