mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-30 23:47:27 +03:00 
			
		
		
		
	Improved error handling
This commit is contained in:
		
							parent
							
								
									3730bf214b
								
							
						
					
					
						commit
						c40bcbfc87
					
				|  | @ -23,8 +23,7 @@ if [[ $(uname) != CYGWIN* ]]; then | |||
|     sudo apt-get -qq install libfreetype6-dev liblcms2-dev python3-tk\ | ||||
|                              ghostscript libjpeg-turbo-progs libopenjp2-7-dev\ | ||||
|                              cmake meson imagemagick libharfbuzz-dev libfribidi-dev\ | ||||
|                              sway wl-clipboard libopenblas-dev\ | ||||
|                              ninja-build build-essential nasm | ||||
|                              sway wl-clipboard libopenblas-dev nasm | ||||
| fi | ||||
| 
 | ||||
| python3 -m pip install --upgrade pip | ||||
|  |  | |||
							
								
								
									
										15
									
								
								.github/workflows/wheels-dependencies.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/workflows/wheels-dependencies.sh
									
									
									
									
										vendored
									
									
								
							|  | @ -114,7 +114,7 @@ function install_rav1e { | |||
| 
 | ||||
|     curl -sLo - \ | ||||
|         https://github.com/xiph/rav1e/releases/download/v$RAV1E_VERSION/librav1e-$RAV1E_VERSION-$suffix.tar.gz \ | ||||
|         | tar -C $BUILD_PREFIX --exclude LICENSE --exclude LICENSE --exclude '*.so' --exclude '*.dylib' -zxf - | ||||
|         | tar -C $BUILD_PREFIX --exclude LICENSE --exclude '*.so' --exclude '*.dylib' -zxf - | ||||
| 
 | ||||
|     if [ -z "$IS_MACOS" ]; then | ||||
|         sed -i 's/-lgcc_s/-lgcc_eh/g' "${BUILD_PREFIX}/lib/pkgconfig/rav1e.pc" | ||||
|  | @ -133,6 +133,7 @@ EOF | |||
| } | ||||
| 
 | ||||
| function build_libavif { | ||||
|     if [ -e libavif-stamp ]; then return; fi | ||||
|     install_rav1e | ||||
|     python3 -m pip install meson ninja | ||||
| 
 | ||||
|  | @ -140,13 +141,11 @@ function build_libavif { | |||
|         build_simple nasm 2.16.03 https://www.nasm.us/pub/nasm/releasebuilds/2.16.03/ | ||||
|     fi | ||||
| 
 | ||||
|     local cmake=$(get_modern_cmake) | ||||
|     local out_dir=$(fetch_unpack https://github.com/AOMediaCodec/libavif/archive/refs/tags/v$LIBAVIF_VERSION.tar.gz libavif-$LIBAVIF_VERSION.tar.gz) | ||||
| 
 | ||||
|     (cd $out_dir \ | ||||
|         && $cmake \ | ||||
|         && cmake \ | ||||
|             -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX \ | ||||
|             -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib \ | ||||
|             -DCMAKE_INSTALL_LIBDIR=$BUILD_PREFIX/lib \ | ||||
|             -DCMAKE_BUILD_TYPE=Release \ | ||||
|             -DBUILD_SHARED_LIBS=OFF \ | ||||
|             -DAVIF_LIBSHARPYUV=LOCAL \ | ||||
|  | @ -159,11 +158,7 @@ function build_libavif { | |||
|             -DCMAKE_MODULE_PATH=/tmp/cmake/Modules \ | ||||
|             . \ | ||||
|         && make install) | ||||
| 
 | ||||
|     if [[ "$MB_ML_LIBC" == "manylinux" ]]; then | ||||
|         cp /usr/local/lib64/libavif.a /usr/local/lib | ||||
|         cp /usr/local/lib64/pkgconfig/libavif.pc /usr/local/lib/pkgconfig | ||||
|     fi | ||||
|     touch libavif-stamp | ||||
| } | ||||
| 
 | ||||
| function build { | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ def test_wheel_modules() -> None: | |||
|     except ImportError: | ||||
|         expected_modules.remove("tkinter") | ||||
| 
 | ||||
|     # libavif is not available on windows for x86 and ARM64 architectures | ||||
|     # libavif is not available on Windows for x86 and ARM64 architectures | ||||
|     if sys.platform == "win32": | ||||
|         if platform.machine() == "ARM64" or struct.calcsize("P") == 4: | ||||
|             expected_modules.remove("avif") | ||||
|  |  | |||
|  | @ -127,8 +127,6 @@ class TestUnsupportedAvif: | |||
| @skip_unless_feature("avif") | ||||
| class TestFileAvif: | ||||
|     def test_version(self) -> None: | ||||
|         _avif.AvifCodecVersions() | ||||
| 
 | ||||
|         version = features.version_module("avif") | ||||
|         assert version is not None | ||||
|         assert re.search(r"\d+\.\d+\.\d+$", version) | ||||
|  |  | |||
|  | @ -1370,17 +1370,16 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options: | |||
|     YUV range, either "full" or "limited". Defaults to "full" | ||||
| 
 | ||||
| **codec** | ||||
|     AV1 codec to use for encoding. Possible values are "aom", "rav1e", and | ||||
|     "svt", depending on what codecs were compiled with libavif. Defaults to | ||||
|     "auto", which will choose the first available codec in the order of the | ||||
|     preceding list. | ||||
|     AV1 codec to use for encoding. Specific values are "aom", "rav1e", and | ||||
|     "svt", presuming the chosen codec is available. Defaults to "auto", which | ||||
|     will choose the first available codec in the order of the preceding list. | ||||
| 
 | ||||
| **tile_rows** / **tile_cols** | ||||
|     For tile encoding, the (log 2) number of tile rows and columns to use. | ||||
|     Valid values are 0-6, default 0. | ||||
| 
 | ||||
| **alpha_premultiplied** | ||||
|     Encode the image with premultiplied alpha, defaults ``False`` | ||||
|     Encode the image with premultiplied alpha. Defaults to ``False`` | ||||
| 
 | ||||
| **icc_profile** | ||||
|     The ICC Profile to include in the saved file. | ||||
|  |  | |||
|  | @ -164,9 +164,11 @@ Many of Pillow's features require external libraries: | |||
|     The easiest way to install external libraries is via `Homebrew | ||||
|     <https://brew.sh/>`_. After you install Homebrew, run:: | ||||
| 
 | ||||
|         brew install libjpeg libraqm libtiff little-cms2 openjpeg webp | ||||
|         brew install libavif libjpeg libraqm libtiff little-cms2 openjpeg webp | ||||
| 
 | ||||
|     To install libavif on macOS use Homebrew to install its build dependencies:: | ||||
|     If you would like to use libavif with more codecs than just aom, then | ||||
|     instead of installing libavif through Homebrew directly, you can use | ||||
|     Homebrew to install libavif's build dependencies:: | ||||
| 
 | ||||
|         brew install aom dav1d rav1e | ||||
| 
 | ||||
|  | @ -224,8 +226,7 @@ Many of Pillow's features require external libraries: | |||
| 
 | ||||
|         sudo pkg install jpeg-turbo tiff webp lcms2 freetype2 openjpeg harfbuzz fribidi libxcb libavif | ||||
| 
 | ||||
|     See ``depends/install_raqm_cmake.sh`` to install libraqm and | ||||
|     ``depends/install_libavif.sh`` to install libavif. | ||||
|     See ``depends/install_raqm_cmake.sh`` to install libraqm. | ||||
| 
 | ||||
| .. tab:: Android | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,17 +24,11 @@ _VALID_AVIF_MODES = {"RGB", "RGBA"} | |||
| def _accept(prefix: bytes) -> bool | str: | ||||
|     if prefix[4:8] != b"ftyp": | ||||
|         return False | ||||
|     coding_brands = (b"avif", b"avis") | ||||
|     container_brands = (b"mif1", b"msf1") | ||||
|     major_brand = prefix[8:12] | ||||
|     if major_brand in coding_brands: | ||||
|         if not SUPPORTED: | ||||
|             return ( | ||||
|                 "image file could not be identified because AVIF " | ||||
|                 "support not installed" | ||||
|             ) | ||||
|         return True | ||||
|     if major_brand in container_brands: | ||||
|     if major_brand in ( | ||||
|         # coding brands | ||||
|         b"avif", | ||||
|         b"avis", | ||||
|         # We accept files with AVIF container brands; we can't yet know if | ||||
|         # the ftyp box has the correct compatible brands, but if it doesn't | ||||
|         # then the plugin will raise a SyntaxError which Pillow will catch | ||||
|  | @ -42,6 +36,14 @@ def _accept(prefix: bytes) -> bool | str: | |||
|         # | ||||
|         # Also, because this file might not actually be an AVIF file, we | ||||
|         # don't raise an error if AVIF support isn't properly compiled. | ||||
|         b"mif1", | ||||
|         b"msf1", | ||||
|     ): | ||||
|         if not SUPPORTED: | ||||
|             return ( | ||||
|                 "image file could not be identified because AVIF " | ||||
|                 "support not installed" | ||||
|             ) | ||||
|         return True | ||||
|     return False | ||||
| 
 | ||||
|  | @ -72,6 +74,11 @@ class AvifImageFile(ImageFile.ImageFile): | |||
|             ) | ||||
|             raise SyntaxError(msg) | ||||
| 
 | ||||
|         if DECODE_CODEC_CHOICE != "auto" and not _avif.decoder_codec_available( | ||||
|             DECODE_CODEC_CHOICE | ||||
|         ): | ||||
|             msg = "Invalid opening codec" | ||||
|             raise ValueError(msg) | ||||
|         self._decoder = _avif.AvifDecoder( | ||||
|             self.fp.read(), | ||||
|             DECODE_CODEC_CHOICE, | ||||
|  | @ -104,10 +111,8 @@ class AvifImageFile(ImageFile.ImageFile): | |||
|             data, timescale, tsp_in_ts, dur_in_ts = self._decoder.get_frame( | ||||
|                 self.__frame | ||||
|             ) | ||||
|             timestamp = round(1000 * (tsp_in_ts / timescale)) | ||||
|             duration = round(1000 * (dur_in_ts / timescale)) | ||||
|             self.info["timestamp"] = timestamp | ||||
|             self.info["duration"] = duration | ||||
|             self.info["timestamp"] = round(1000 * (tsp_in_ts / timescale)) | ||||
|             self.info["duration"] = round(1000 * (dur_in_ts / timescale)) | ||||
|             self.__loaded = self.__frame | ||||
| 
 | ||||
|             # Set tile | ||||
|  | @ -153,6 +158,9 @@ def _save( | |||
|     speed = info.get("speed", 6) | ||||
|     max_threads = info.get("max_threads", _get_default_max_threads()) | ||||
|     codec = info.get("codec", "auto") | ||||
|     if codec != "auto" and not _avif.encoder_codec_available(codec): | ||||
|         msg = "Invalid saving codec" | ||||
|         raise ValueError(msg) | ||||
|     range_ = info.get("range", "full") | ||||
|     tile_rows_log2 = info.get("tile_rows", 0) | ||||
|     tile_cols_log2 = info.get("tile_cols", 0) | ||||
|  | @ -199,7 +207,7 @@ def _save( | |||
|             ) | ||||
|             raise ValueError(msg) | ||||
|         advanced = tuple( | ||||
|             [(str(k).encode("utf-8"), str(v).encode("utf-8")) for k, v in advanced] | ||||
|             (str(k).encode("utf-8"), str(v).encode("utf-8")) for k, v in advanced | ||||
|         ) | ||||
| 
 | ||||
|     # Setup the AVIF encoder | ||||
|  |  | |||
							
								
								
									
										147
									
								
								src/_avif.c
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								src/_avif.c
									
									
									
									
									
								
							|  | @ -218,30 +218,43 @@ _encoder_codec_available(PyObject *self, PyObject *args) { | |||
|     return PyBool_FromLong(is_available); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| static int | ||||
| _add_codec_specific_options(avifEncoder *encoder, PyObject *opts) { | ||||
|     Py_ssize_t i, size; | ||||
|     PyObject *keyval, *py_key, *py_val; | ||||
|     char *key, *val; | ||||
|     if (!PyTuple_Check(opts)) { | ||||
|         return; | ||||
|         PyErr_SetString(PyExc_ValueError, "Invalid advanced codec options"); | ||||
|         return 1; | ||||
|     } | ||||
|     size = PyTuple_GET_SIZE(opts); | ||||
| 
 | ||||
|     for (i = 0; i < size; i++) { | ||||
|         keyval = PyTuple_GetItem(opts, i); | ||||
|         if (!PyTuple_Check(keyval) || PyTuple_GET_SIZE(keyval) != 2) { | ||||
|             return; | ||||
|             PyErr_SetString(PyExc_ValueError, "Invalid advanced codec options"); | ||||
|             return 1; | ||||
|         } | ||||
|         py_key = PyTuple_GetItem(keyval, 0); | ||||
|         py_val = PyTuple_GetItem(keyval, 1); | ||||
|         if (!PyBytes_Check(py_key) || !PyBytes_Check(py_val)) { | ||||
|             return; | ||||
|             PyErr_SetString(PyExc_ValueError, "Invalid advanced codec options"); | ||||
|             return 1; | ||||
|         } | ||||
|         key = PyBytes_AsString(py_key); | ||||
|         val = PyBytes_AsString(py_val); | ||||
|         avifEncoderSetCodecSpecificOption(encoder, key, val); | ||||
| 
 | ||||
|         avifResult result = avifEncoderSetCodecSpecificOption(encoder, key, val); | ||||
|         if (result != AVIF_RESULT_OK) { | ||||
|             PyErr_Format( | ||||
|                 exc_type_for_avif_result(result), | ||||
|                 "Setting advanced codec options failed: %s", | ||||
|                 avifResultToString(result) | ||||
|             ); | ||||
|             return 1; | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| // Encoder functions
 | ||||
|  | @ -336,17 +349,6 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { | |||
|         enc_options.codec = AVIF_CODEC_CHOICE_AUTO; | ||||
|     } else { | ||||
|         enc_options.codec = avifCodecChoiceFromName(codec); | ||||
|         if (enc_options.codec == AVIF_CODEC_CHOICE_AUTO) { | ||||
|             PyErr_Format(PyExc_ValueError, "Invalid codec: %s", codec); | ||||
|             return NULL; | ||||
|         } else { | ||||
|             const char *codec_name = | ||||
|                 avifCodecName(enc_options.codec, AVIF_CODEC_FLAG_CAN_ENCODE); | ||||
|             if (codec_name == NULL) { | ||||
|                 PyErr_Format(PyExc_ValueError, "AV1 Codec cannot encode: %s", codec); | ||||
|                 return NULL; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (strcmp(range, "full") == 0) { | ||||
|  | @ -410,9 +412,18 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { | |||
|         encoder->autoTiling = enc_options.autotiling; | ||||
| #endif | ||||
| 
 | ||||
|         if (advanced != Py_None) { | ||||
| #if AVIF_VERSION >= 80200 | ||||
|         _add_codec_specific_options(encoder, advanced); | ||||
|             if (_add_codec_specific_options(encoder, advanced)) { | ||||
|                 return NULL; | ||||
|             } | ||||
| #else | ||||
|             PyErr_SetString( | ||||
|                 PyExc_ValueError, "Advanced codec options require libavif >= 0.8.2" | ||||
|             ); | ||||
|             return NULL; | ||||
| #endif | ||||
|         } | ||||
| 
 | ||||
|         self->encoder = encoder; | ||||
| 
 | ||||
|  | @ -430,14 +441,24 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { | |||
|         image->alphaPremultiplied = enc_options.alpha_premultiplied; | ||||
| #endif | ||||
| 
 | ||||
|         avifResult result; | ||||
|         if (PyBytes_GET_SIZE(icc_bytes)) { | ||||
|             self->icc_bytes = icc_bytes; | ||||
|             Py_INCREF(icc_bytes); | ||||
|             avifImageSetProfileICC( | ||||
| 
 | ||||
|             result = avifImageSetProfileICC( | ||||
|                 image, | ||||
|                 (uint8_t *)PyBytes_AS_STRING(icc_bytes), | ||||
|                 PyBytes_GET_SIZE(icc_bytes) | ||||
|             ); | ||||
|             if (result != AVIF_RESULT_OK) { | ||||
|                 PyErr_Format( | ||||
|                     exc_type_for_avif_result(result), | ||||
|                     "Setting ICC profile failed: %s", | ||||
|                     avifResultToString(result) | ||||
|                 ); | ||||
|                 return NULL; | ||||
|             } | ||||
|         } else { | ||||
|             image->colorPrimaries = AVIF_COLOR_PRIMARIES_BT709; | ||||
|             image->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_SRGB; | ||||
|  | @ -446,20 +467,38 @@ AvifEncoderNew(PyObject *self_, PyObject *args) { | |||
|         if (PyBytes_GET_SIZE(exif_bytes)) { | ||||
|             self->exif_bytes = exif_bytes; | ||||
|             Py_INCREF(exif_bytes); | ||||
|             avifImageSetMetadataExif( | ||||
| 
 | ||||
|             result = avifImageSetMetadataExif( | ||||
|                 image, | ||||
|                 (uint8_t *)PyBytes_AS_STRING(exif_bytes), | ||||
|                 PyBytes_GET_SIZE(exif_bytes) | ||||
|             ); | ||||
|             if (result != AVIF_RESULT_OK) { | ||||
|                 PyErr_Format( | ||||
|                     exc_type_for_avif_result(result), | ||||
|                     "Setting EXIF data failed: %s", | ||||
|                     avifResultToString(result) | ||||
|                 ); | ||||
|                 return NULL; | ||||
|             } | ||||
|         } | ||||
|         if (PyBytes_GET_SIZE(xmp_bytes)) { | ||||
|             self->xmp_bytes = xmp_bytes; | ||||
|             Py_INCREF(xmp_bytes); | ||||
|             avifImageSetMetadataXMP( | ||||
| 
 | ||||
|             result = avifImageSetMetadataXMP( | ||||
|                 image, | ||||
|                 (uint8_t *)PyBytes_AS_STRING(xmp_bytes), | ||||
|                 PyBytes_GET_SIZE(xmp_bytes) | ||||
|             ); | ||||
|             if (result != AVIF_RESULT_OK) { | ||||
|                 PyErr_Format( | ||||
|                     exc_type_for_avif_result(result), | ||||
|                     "Setting XMP data failed: %s", | ||||
|                     avifResultToString(result) | ||||
|                 ); | ||||
|                 return NULL; | ||||
|             } | ||||
|         } | ||||
|         exif_orientation_to_irot_imir(image, exif_orientation); | ||||
| 
 | ||||
|  | @ -498,7 +537,6 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) { | |||
|     PyObject *ret = Py_None; | ||||
| 
 | ||||
|     int is_first_frame; | ||||
|     int channels; | ||||
|     avifRGBImage rgb; | ||||
|     avifResult result; | ||||
| 
 | ||||
|  | @ -561,13 +599,19 @@ _encoder_add(AvifEncoderObject *self, PyObject *args) { | |||
| 
 | ||||
|     if (strcmp(mode, "RGBA") == 0) { | ||||
|         rgb.format = AVIF_RGB_FORMAT_RGBA; | ||||
|         channels = 4; | ||||
|     } else { | ||||
|         rgb.format = AVIF_RGB_FORMAT_RGB; | ||||
|         channels = 3; | ||||
|     } | ||||
| 
 | ||||
|     avifRGBImageAllocatePixels(&rgb); | ||||
|     result = avifRGBImageAllocatePixels(&rgb); | ||||
|     if (result != AVIF_RESULT_OK) { | ||||
|         PyErr_Format( | ||||
|             exc_type_for_avif_result(result), | ||||
|             "Pixel allocation failed: %s", | ||||
|             avifResultToString(result) | ||||
|         ); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     if (rgb.rowBytes * rgb.height != size) { | ||||
|         PyErr_Format( | ||||
|  | @ -679,18 +723,6 @@ AvifDecoderNew(PyObject *self_, PyObject *args) { | |||
|         codec = AVIF_CODEC_CHOICE_AUTO; | ||||
|     } else { | ||||
|         codec = avifCodecChoiceFromName(codec_str); | ||||
|         if (codec == AVIF_CODEC_CHOICE_AUTO) { | ||||
|             PyErr_Format(PyExc_ValueError, "Invalid codec: %s", codec_str); | ||||
|             return NULL; | ||||
|         } else { | ||||
|             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 | ||||
|                 ); | ||||
|                 return NULL; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     self = PyObject_New(AvifDecoderObject, &AvifDecoder_Type); | ||||
|  | @ -717,14 +749,24 @@ AvifDecoderNew(PyObject *self_, PyObject *args) { | |||
| #endif | ||||
|     self->decoder->codecChoice = codec; | ||||
| 
 | ||||
|     avifDecoderSetIOMemory( | ||||
|     result = avifDecoderSetIOMemory( | ||||
|         self->decoder, | ||||
|         (uint8_t *)PyBytes_AS_STRING(self->data), | ||||
|         PyBytes_GET_SIZE(self->data) | ||||
|     ); | ||||
|     if (result != AVIF_RESULT_OK) { | ||||
|         PyErr_Format( | ||||
|             exc_type_for_avif_result(result), | ||||
|             "Setting IO memory failed: %s", | ||||
|             avifResultToString(result) | ||||
|         ); | ||||
|         avifDecoderDestroy(self->decoder); | ||||
|         self->decoder = NULL; | ||||
|         Py_DECREF(self); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     result = avifDecoderParse(self->decoder); | ||||
| 
 | ||||
|     if (result != AVIF_RESULT_OK) { | ||||
|         PyErr_Format( | ||||
|             exc_type_for_avif_result(result), | ||||
|  | @ -815,7 +857,6 @@ _decoder_get_frame(AvifDecoderObject *self, PyObject *args) { | |||
|     } | ||||
| 
 | ||||
|     result = avifDecoderNthImage(decoder, frame_index); | ||||
| 
 | ||||
|     if (result != AVIF_RESULT_OK) { | ||||
|         PyErr_Format( | ||||
|             exc_type_for_avif_result(result), | ||||
|  | @ -847,7 +888,15 @@ _decoder_get_frame(AvifDecoderObject *self, PyObject *args) { | |||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     avifRGBImageAllocatePixels(&rgb); | ||||
|     result = avifRGBImageAllocatePixels(&rgb); | ||||
|     if (result != AVIF_RESULT_OK) { | ||||
|         PyErr_Format( | ||||
|             exc_type_for_avif_result(result), | ||||
|             "Pixel allocation failed: %s", | ||||
|             avifResultToString(result) | ||||
|         ); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     Py_BEGIN_ALLOW_THREADS result = avifImageYUVToRGB(image, &rgb); | ||||
|     Py_END_ALLOW_THREADS | ||||
|  | @ -893,10 +942,7 @@ static struct PyMethodDef _encoder_methods[] = { | |||
| 
 | ||||
| // AvifDecoder type definition
 | ||||
| static PyTypeObject AvifEncoder_Type = { | ||||
|     // clang-format off
 | ||||
|     PyVarObject_HEAD_INIT(NULL, 0) | ||||
|     .tp_name = "AvifEncoder", | ||||
|     // clang-format on
 | ||||
|     PyVarObject_HEAD_INIT(NULL, 0).tp_name = "AvifEncoder", | ||||
|     .tp_basicsize = sizeof(AvifEncoderObject), | ||||
|     .tp_dealloc = (destructor)_encoder_dealloc, | ||||
|     .tp_flags = Py_TPFLAGS_DEFAULT, | ||||
|  | @ -912,10 +958,7 @@ static struct PyMethodDef _decoder_methods[] = { | |||
| 
 | ||||
| // AvifDecoder type definition
 | ||||
| static PyTypeObject AvifDecoder_Type = { | ||||
|     // clang-format off
 | ||||
|     PyVarObject_HEAD_INIT(NULL, 0) | ||||
|     .tp_name = "AvifDecoder", | ||||
|     // clang-format on
 | ||||
|     PyVarObject_HEAD_INIT(NULL, 0).tp_name = "AvifDecoder", | ||||
|     .tp_basicsize = sizeof(AvifDecoderObject), | ||||
|     .tp_itemsize = 0, | ||||
|     .tp_dealloc = (destructor)_decoder_dealloc, | ||||
|  | @ -923,13 +966,6 @@ static PyTypeObject AvifDecoder_Type = { | |||
|     .tp_methods = _decoder_methods, | ||||
| }; | ||||
| 
 | ||||
| PyObject * | ||||
| AvifCodecVersions() { | ||||
|     char codecVersions[256]; | ||||
|     avifCodecVersions(codecVersions); | ||||
|     return PyUnicode_FromString(codecVersions); | ||||
| } | ||||
| 
 | ||||
| /* -------------------------------------------------------------------- */ | ||||
| /* Module Setup                                                         */ | ||||
| /* -------------------------------------------------------------------- */ | ||||
|  | @ -937,7 +973,6 @@ AvifCodecVersions() { | |||
| static PyMethodDef avifMethods[] = { | ||||
|     {"AvifDecoder", AvifDecoderNew, METH_VARARGS}, | ||||
|     {"AvifEncoder", AvifEncoderNew, METH_VARARGS}, | ||||
|     {"AvifCodecVersions", AvifCodecVersions, METH_NOARGS}, | ||||
|     {"decoder_codec_available", _decoder_codec_available, METH_VARARGS}, | ||||
|     {"encoder_codec_available", _encoder_codec_available, METH_VARARGS}, | ||||
|     {NULL, NULL} | ||||
|  |  | |||
|  | @ -122,7 +122,7 @@ V = { | |||
|     "TIFF": "4.6.0", | ||||
|     "XZ": "5.6.3", | ||||
|     "ZLIB": "1.3.1", | ||||
|     "MESON": "1.5.2", | ||||
|     "MESON": "1.6.0", | ||||
|     "LIBAVIF": "1.1.1", | ||||
|     "RAV1E": "0.7.1", | ||||
| } | ||||
|  | @ -673,21 +673,24 @@ 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 | ||||
| 
 | ||||
|         scripts = [] | ||||
|         if dep_name == "libavif": | ||||
|             scripts.append("install_meson.cmd") | ||||
|         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}"') | ||||
|         lines.append("if errorlevel 1 echo Build failed! && exit /B 1") | ||||
|         if gha_groups: | ||||
|             lines.append("@echo ::endgroup::") | ||||
|         for script in scripts: | ||||
|             if gha_groups: | ||||
|                 lines.append(f"@echo ::group::Running {script}") | ||||
|             lines.append(rf'cmd.exe /c "{{build_dir}}\{script}"') | ||||
|             lines.append("if errorlevel 1 echo Build failed! && exit /B 1") | ||||
|             if gha_groups: | ||||
|                 lines.append("@echo ::endgroup::") | ||||
|     print() | ||||
|     lines.append("@echo All Pillow dependencies built successfully!") | ||||
|     write_script("build_dep_all.cmd", lines, prefs, verbose) | ||||
|  | @ -830,18 +833,19 @@ 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"{sys.executable} -m pip install meson=={V['MESON']}", | ||||
|         ], | ||||
|         prefs, | ||||
|         args.verbose, | ||||
|     ) | ||||
|     if "libavif" not in disabled: | ||||
|         write_script( | ||||
|             "install_meson.cmd", | ||||
|             [ | ||||
|                 r'call "{build_dir}\build_env.cmd"', | ||||
|                 "@echo " + ("=" * 70), | ||||
|                 f"@echo ==== {'Building meson':<60} ====", | ||||
|                 "@echo " + ("=" * 70), | ||||
|                 f"{sys.executable} -m pip install meson=={V['MESON']}", | ||||
|             ], | ||||
|             prefs, | ||||
|             args.verbose, | ||||
|         ) | ||||
|     build_env(prefs, args.verbose) | ||||
|     build_dep_all(disabled, prefs, args.verbose) | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user