mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-30 23:47:27 +03:00 
			
		
		
		
	Merge branch 'main' into types-cms2
This commit is contained in:
		
						commit
						46b0b0e57d
					
				
							
								
								
									
										15
									
								
								.github/ISSUE_TEMPLATE/ISSUE_REPORT.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/ISSUE_TEMPLATE/ISSUE_REPORT.md
									
									
									
									
										vendored
									
									
								
							|  | @ -48,6 +48,21 @@ Thank you. | |||
| * Python:  | ||||
| * Pillow:  | ||||
| 
 | ||||
| ```text | ||||
| Please paste here the output of running: | ||||
| 
 | ||||
| python3 -m PIL.report | ||||
| or | ||||
| python3 -m PIL --report | ||||
| 
 | ||||
| Or the output of the following Python code: | ||||
| 
 | ||||
| from PIL import report | ||||
| # or | ||||
| from PIL import features | ||||
| features.pilinfo(supported_formats=False) | ||||
| ``` | ||||
| 
 | ||||
| <!-- | ||||
| Please include **code** that reproduces the issue and whenever possible, an **image** that demonstrates the issue. Please upload images to GitHub, not to third-party file hosting sites. If necessary, add the image to a zip or tar archive. | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								.github/workflows/wheels-dependencies.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/wheels-dependencies.sh
									
									
									
									
										vendored
									
									
								
							|  | @ -16,7 +16,7 @@ ARCHIVE_SDIR=pillow-depends-main | |||
| 
 | ||||
| # Package versions for fresh source builds | ||||
| FREETYPE_VERSION=2.13.2 | ||||
| HARFBUZZ_VERSION=8.3.1 | ||||
| HARFBUZZ_VERSION=8.4.0 | ||||
| LIBPNG_VERSION=1.6.43 | ||||
| JPEGTURBO_VERSION=3.0.2 | ||||
| OPENJPEG_VERSION=2.5.2 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								.github/workflows/wheels.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/wheels.yml
									
									
									
									
										vendored
									
									
								
							|  | @ -5,6 +5,7 @@ on: | |||
|     paths: | ||||
|       - ".ci/requirements-cibw.txt" | ||||
|       - ".github/workflows/wheel*" | ||||
|       - "setup.py" | ||||
|       - "wheels/*" | ||||
|       - "winbuild/build_prepare.py" | ||||
|       - "winbuild/fribidi.cmake" | ||||
|  | @ -14,6 +15,7 @@ on: | |||
|     paths: | ||||
|       - ".ci/requirements-cibw.txt" | ||||
|       - ".github/workflows/wheel*" | ||||
|       - "setup.py" | ||||
|       - "wheels/*" | ||||
|       - "winbuild/build_prepare.py" | ||||
|       - "winbuild/fribidi.cmake" | ||||
|  |  | |||
|  | @ -5,6 +5,15 @@ Changelog (Pillow) | |||
| 10.3.0 (unreleased) | ||||
| ------------------- | ||||
| 
 | ||||
| - Determine MPO size from markers, not EXIF data #7884 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Improved conversion from RGB to RGBa, LA and La #7888 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Support FITS images with GZIP_1 compression #7894 | ||||
|   [radarhere] | ||||
| 
 | ||||
| - Use I;16 mode for 9-bit JPEG 2000 images #7900 | ||||
|   [scaramallion, radarhere] | ||||
| 
 | ||||
|  |  | |||
|  | @ -263,8 +263,6 @@ def hopper(mode: str | None = None, cache: dict[str, Image.Image] = {}) -> Image | |||
|     if im is None: | ||||
|         if mode == "F": | ||||
|             im = hopper("L").convert(mode) | ||||
|         elif mode[:4] == "I;16": | ||||
|             im = hopper("I").convert(mode) | ||||
|         else: | ||||
|             im = hopper().convert(mode) | ||||
|         cache[mode] = im | ||||
|  |  | |||
|  | @ -117,9 +117,10 @@ def test_unsupported_module() -> None: | |||
|         features.version_module(module) | ||||
| 
 | ||||
| 
 | ||||
| def test_pilinfo() -> None: | ||||
| @pytest.mark.parametrize("supported_formats", (True, False)) | ||||
| def test_pilinfo(supported_formats) -> None: | ||||
|     buf = io.StringIO() | ||||
|     features.pilinfo(buf) | ||||
|     features.pilinfo(buf, supported_formats=supported_formats) | ||||
|     out = buf.getvalue() | ||||
|     lines = out.splitlines() | ||||
|     assert lines[0] == "-" * 68 | ||||
|  | @ -129,9 +130,15 @@ def test_pilinfo() -> None: | |||
|     while lines[0].startswith("    "): | ||||
|         lines = lines[1:] | ||||
|     assert lines[0] == "-" * 68 | ||||
|     assert lines[1].startswith("Python modules loaded from ") | ||||
|     assert lines[2].startswith("Binary modules loaded from ") | ||||
|     assert lines[3] == "-" * 68 | ||||
|     assert lines[1].startswith("Python executable is") | ||||
|     lines = lines[2:] | ||||
|     if lines[0].startswith("Environment Python files loaded from"): | ||||
|         lines = lines[1:] | ||||
|     assert lines[0].startswith("System Python files loaded from") | ||||
|     assert lines[1] == "-" * 68 | ||||
|     assert lines[2].startswith("Python Pillow modules loaded from ") | ||||
|     assert lines[3].startswith("Binary Pillow modules loaded from ") | ||||
|     assert lines[4] == "-" * 68 | ||||
|     jpeg = ( | ||||
|         "\n" | ||||
|         + "-" * 68 | ||||
|  | @ -142,4 +149,4 @@ def test_pilinfo() -> None: | |||
|         + "-" * 68 | ||||
|         + "\n" | ||||
|     ) | ||||
|     assert jpeg in out | ||||
|     assert supported_formats == (jpeg in out) | ||||
|  |  | |||
|  | @ -825,7 +825,7 @@ class TestFileJpeg: | |||
|         with Image.open("Tests/images/no-dpi-in-exif.jpg") as im: | ||||
|             # Act / Assert | ||||
|             # "When the image resolution is unknown, 72 [dpi] is designated." | ||||
|             # https://exiv2.org/tags.html | ||||
|             # https://web.archive.org/web/20240227115053/https://exiv2.org/tags.html | ||||
|             assert im.info.get("dpi") == (72, 72) | ||||
| 
 | ||||
|     def test_invalid_exif(self) -> None: | ||||
|  |  | |||
|  | @ -33,36 +33,38 @@ from .helper import ( | |||
|     skip_unless_feature, | ||||
| ) | ||||
| 
 | ||||
| # name, pixel size | ||||
| image_modes = ( | ||||
|     ("1", 1), | ||||
|     ("L", 1), | ||||
|     ("LA", 4), | ||||
|     ("La", 4), | ||||
|     ("P", 1), | ||||
|     ("PA", 4), | ||||
|     ("F", 4), | ||||
|     ("I", 4), | ||||
|     ("I;16", 2), | ||||
|     ("I;16L", 2), | ||||
|     ("I;16B", 2), | ||||
|     ("I;16N", 2), | ||||
|     ("RGB", 4), | ||||
|     ("RGBA", 4), | ||||
|     ("RGBa", 4), | ||||
|     ("RGBX", 4), | ||||
|     ("BGR;15", 2), | ||||
|     ("BGR;16", 2), | ||||
|     ("BGR;24", 3), | ||||
|     ("CMYK", 4), | ||||
|     ("YCbCr", 4), | ||||
|     ("HSV", 4), | ||||
|     ("LAB", 4), | ||||
| ) | ||||
| 
 | ||||
| image_mode_names = [name for name, _ in image_modes] | ||||
| 
 | ||||
| 
 | ||||
| class TestImage: | ||||
|     @pytest.mark.parametrize( | ||||
|         "mode", | ||||
|         ( | ||||
|             "1", | ||||
|             "P", | ||||
|             "PA", | ||||
|             "L", | ||||
|             "LA", | ||||
|             "La", | ||||
|             "F", | ||||
|             "I", | ||||
|             "I;16", | ||||
|             "I;16L", | ||||
|             "I;16B", | ||||
|             "I;16N", | ||||
|             "RGB", | ||||
|             "RGBX", | ||||
|             "RGBA", | ||||
|             "RGBa", | ||||
|             "BGR;15", | ||||
|             "BGR;16", | ||||
|             "BGR;24", | ||||
|             "CMYK", | ||||
|             "YCbCr", | ||||
|             "LAB", | ||||
|             "HSV", | ||||
|         ), | ||||
|     ) | ||||
|     @pytest.mark.parametrize("mode", image_mode_names) | ||||
|     def test_image_modes_success(self, mode: str) -> None: | ||||
|         Image.new(mode, (1, 1)) | ||||
| 
 | ||||
|  | @ -1042,6 +1044,35 @@ class TestImage: | |||
|             assert im.fp is None | ||||
| 
 | ||||
| 
 | ||||
| class TestImageBytes: | ||||
|     @pytest.mark.parametrize("mode", image_mode_names) | ||||
|     def test_roundtrip_bytes_constructor(self, mode: str) -> None: | ||||
|         im = hopper(mode) | ||||
|         source_bytes = im.tobytes() | ||||
| 
 | ||||
|         reloaded = Image.frombytes(mode, im.size, source_bytes) | ||||
|         assert reloaded.tobytes() == source_bytes | ||||
| 
 | ||||
|     @pytest.mark.parametrize("mode", image_mode_names) | ||||
|     def test_roundtrip_bytes_method(self, mode: str) -> None: | ||||
|         im = hopper(mode) | ||||
|         source_bytes = im.tobytes() | ||||
| 
 | ||||
|         reloaded = Image.new(mode, im.size) | ||||
|         reloaded.frombytes(source_bytes) | ||||
|         assert reloaded.tobytes() == source_bytes | ||||
| 
 | ||||
|     @pytest.mark.parametrize(("mode", "pixelsize"), image_modes) | ||||
|     def test_getdata_putdata(self, mode: str, pixelsize: int) -> None: | ||||
|         im = Image.new(mode, (2, 2)) | ||||
|         source_bytes = bytes(range(im.width * im.height * pixelsize)) | ||||
|         im.frombytes(source_bytes) | ||||
| 
 | ||||
|         reloaded = Image.new(mode, im.size) | ||||
|         reloaded.putdata(im.getdata()) | ||||
|         assert_image_equal(im, reloaded) | ||||
| 
 | ||||
| 
 | ||||
| class MockEncoder(ImageFile.PyEncoder): | ||||
|     pass | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,9 +4,16 @@ import os | |||
| import subprocess | ||||
| import sys | ||||
| 
 | ||||
| import pytest | ||||
| 
 | ||||
| def test_main() -> None: | ||||
|     out = subprocess.check_output([sys.executable, "-m", "PIL"]).decode("utf-8") | ||||
| 
 | ||||
| @pytest.mark.parametrize( | ||||
|     "args, report", | ||||
|     ((["PIL"], False), (["PIL", "--report"], True), (["PIL.report"], True)), | ||||
| ) | ||||
| def test_main(args, report) -> None: | ||||
|     args = [sys.executable, "-m"] + args | ||||
|     out = subprocess.check_output(args).decode("utf-8") | ||||
|     lines = out.splitlines() | ||||
|     assert lines[0] == "-" * 68 | ||||
|     assert lines[1].startswith("Pillow ") | ||||
|  | @ -15,9 +22,15 @@ def test_main() -> None: | |||
|     while lines[0].startswith("    "): | ||||
|         lines = lines[1:] | ||||
|     assert lines[0] == "-" * 68 | ||||
|     assert lines[1].startswith("Python modules loaded from ") | ||||
|     assert lines[2].startswith("Binary modules loaded from ") | ||||
|     assert lines[3] == "-" * 68 | ||||
|     assert lines[1].startswith("Python executable is") | ||||
|     lines = lines[2:] | ||||
|     if lines[0].startswith("Environment Python files loaded from"): | ||||
|         lines = lines[1:] | ||||
|     assert lines[0].startswith("System Python files loaded from") | ||||
|     assert lines[1] == "-" * 68 | ||||
|     assert lines[2].startswith("Python Pillow modules loaded from ") | ||||
|     assert lines[3].startswith("Binary Pillow modules loaded from ") | ||||
|     assert lines[4] == "-" * 68 | ||||
|     jpeg = ( | ||||
|         os.linesep | ||||
|         + "-" * 68 | ||||
|  | @ -31,4 +44,4 @@ def test_main() -> None: | |||
|         + "-" * 68 | ||||
|         + os.linesep | ||||
|     ) | ||||
|     assert jpeg in out | ||||
|     assert report == (jpeg not in out) | ||||
|  |  | |||
|  | @ -11,41 +11,12 @@ backend_class = build_wheel.__self__.__class__ | |||
| class _CustomBuildMetaBackend(backend_class): | ||||
|     def run_setup(self, setup_script="setup.py"): | ||||
|         if self.config_settings: | ||||
|             for key, values in self.config_settings.items(): | ||||
|                 if not isinstance(values, list): | ||||
|                     values = [values] | ||||
|                 for value in values: | ||||
|                     sys.argv.append(f"--pillow-configuration={key}={value}") | ||||
| 
 | ||||
|             def config_has(key, value): | ||||
|                 settings = self.config_settings.get(key) | ||||
|                 if settings: | ||||
|                     if not isinstance(settings, list): | ||||
|                         settings = [settings] | ||||
|                     return value in settings | ||||
| 
 | ||||
|             flags = [] | ||||
|             for dependency in ( | ||||
|                 "zlib", | ||||
|                 "jpeg", | ||||
|                 "tiff", | ||||
|                 "freetype", | ||||
|                 "raqm", | ||||
|                 "lcms", | ||||
|                 "webp", | ||||
|                 "webpmux", | ||||
|                 "jpeg2000", | ||||
|                 "imagequant", | ||||
|                 "xcb", | ||||
|             ): | ||||
|                 if config_has(dependency, "enable"): | ||||
|                     flags.append("--enable-" + dependency) | ||||
|                 elif config_has(dependency, "disable"): | ||||
|                     flags.append("--disable-" + dependency) | ||||
|             for dependency in ("raqm", "fribidi"): | ||||
|                 if config_has(dependency, "vendor"): | ||||
|                     flags.append("--vendor-" + dependency) | ||||
|             if self.config_settings.get("platform-guessing") == "disable": | ||||
|                 flags.append("--disable-platform-guessing") | ||||
|             if self.config_settings.get("debug") == "true": | ||||
|                 flags.append("--debug") | ||||
|             if flags: | ||||
|                 sys.argv = sys.argv[:1] + ["build_ext"] + flags + sys.argv[1:] | ||||
|         return super().run_setup(setup_script) | ||||
| 
 | ||||
|     def build_wheel( | ||||
|  | @ -54,5 +25,15 @@ class _CustomBuildMetaBackend(backend_class): | |||
|         self.config_settings = config_settings | ||||
|         return super().build_wheel(wheel_directory, config_settings, metadata_directory) | ||||
| 
 | ||||
|     def build_editable( | ||||
|         self, wheel_directory, config_settings=None, metadata_directory=None | ||||
|     ): | ||||
|         self.config_settings = config_settings | ||||
|         return super().build_editable( | ||||
|             wheel_directory, config_settings, metadata_directory | ||||
|         ) | ||||
| 
 | ||||
| build_wheel = _CustomBuildMetaBackend().build_wheel | ||||
| 
 | ||||
| _backend = _CustomBuildMetaBackend() | ||||
| build_wheel = _backend.build_wheel | ||||
| build_editable = _backend.build_editable | ||||
|  |  | |||
|  | @ -266,9 +266,10 @@ After navigating to the Pillow directory, run:: | |||
| Build Options | ||||
| ^^^^^^^^^^^^^ | ||||
| 
 | ||||
| * Environment variable: ``MAX_CONCURRENCY=n``. Pillow can use | ||||
|   multiprocessing to build the extension. Setting ``MAX_CONCURRENCY`` | ||||
|   sets the number of CPUs to use, or can disable parallel building by | ||||
| * Config setting: ``-C parallel=n``. Can also be given | ||||
|   with environment variable: ``MAX_CONCURRENCY=n``. Pillow can use | ||||
|   multiprocessing to build the extension. Setting ``-C parallel=n`` | ||||
|   sets the number of CPUs to use to ``n``, or can disable parallel building by | ||||
|   using a setting of 1. By default, it uses 4 CPUs, or if 4 are not | ||||
|   available, as many as are present. | ||||
| 
 | ||||
|  | @ -293,14 +294,13 @@ Build Options | |||
|   used to compile the standard Pillow wheels. Compiling libraqm requires | ||||
|   a C99-compliant compiler. | ||||
| 
 | ||||
| * Build flag: ``-C platform-guessing=disable``. Skips all of the | ||||
| * Config setting: ``-C platform-guessing=disable``. Skips all of the | ||||
|   platform dependent guessing of include and library directories for | ||||
|   automated build systems that configure the proper paths in the | ||||
|   environment variables (e.g. Buildroot). | ||||
| 
 | ||||
| * Build flag: ``-C debug=true``. Adds a debugging flag to the include and | ||||
|   library search process to dump all paths searched for and found to | ||||
|   stdout. | ||||
| * Config setting: ``-C debug=true``. Adds a debugging flag to the include and | ||||
|   library search process to dump all paths searched for and found to stdout. | ||||
| 
 | ||||
| 
 | ||||
| Sample usage:: | ||||
|  |  | |||
							
								
								
									
										26
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								setup.py
									
									
									
									
									
								
							|  | @ -27,6 +27,9 @@ def get_version(): | |||
|     return locals()["__version__"] | ||||
| 
 | ||||
| 
 | ||||
| configuration = {} | ||||
| 
 | ||||
| 
 | ||||
| PILLOW_VERSION = get_version() | ||||
| FREETYPE_ROOT = None | ||||
| HARFBUZZ_ROOT = None | ||||
|  | @ -333,15 +336,24 @@ class pil_build_ext(build_ext): | |||
|         + [("add-imaging-libs=", None, "Add libs to _imaging build")] | ||||
|     ) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def check_configuration(option, value): | ||||
|         return True if value in configuration.get(option, []) else None | ||||
| 
 | ||||
|     def initialize_options(self): | ||||
|         self.disable_platform_guessing = None | ||||
|         self.disable_platform_guessing = self.check_configuration( | ||||
|             "platform-guessing", "disable" | ||||
|         ) | ||||
|         self.add_imaging_libs = "" | ||||
|         build_ext.initialize_options(self) | ||||
|         for x in self.feature: | ||||
|             setattr(self, f"disable_{x}", None) | ||||
|             setattr(self, f"enable_{x}", None) | ||||
|             setattr(self, f"disable_{x}", self.check_configuration(x, "disable")) | ||||
|             setattr(self, f"enable_{x}", self.check_configuration(x, "enable")) | ||||
|         for x in ("raqm", "fribidi"): | ||||
|             setattr(self, f"vendor_{x}", None) | ||||
|             setattr(self, f"vendor_{x}", self.check_configuration(x, "vendor")) | ||||
|         if self.check_configuration("debug", "true"): | ||||
|             self.debug = True | ||||
|         self.parallel = configuration.get("parallel", [None])[-1] | ||||
| 
 | ||||
|     def finalize_options(self): | ||||
|         build_ext.finalize_options(self) | ||||
|  | @ -987,6 +999,12 @@ ext_modules = [ | |||
|     Extension("PIL._imagingmorph", ["src/_imagingmorph.c"]), | ||||
| ] | ||||
| 
 | ||||
| 
 | ||||
| # parse configuration from _custom_build/backend.py | ||||
| while sys.argv[-1].startswith("--pillow-configuration="): | ||||
|     _, key, value = sys.argv.pop().split("=", 2) | ||||
|     configuration.setdefault(key, []).append(value) | ||||
| 
 | ||||
| try: | ||||
|     setup( | ||||
|         cmdclass={"build_ext": pil_build_ext}, | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ You can get the subsampling of a JPEG with the | |||
| :func:`.JpegImagePlugin.get_sampling` function. | ||||
| 
 | ||||
| In JPEG compressed data a JPEG marker is used instead of an EXIF tag. | ||||
| (ref.: https://exiv2.org/tags.html) | ||||
| (ref.: https://web.archive.org/web/20240227115053/https://exiv2.org/tags.html) | ||||
| 
 | ||||
| 
 | ||||
| Quantization tables | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| from __future__ import annotations | ||||
| 
 | ||||
| import sys | ||||
| 
 | ||||
| from .features import pilinfo | ||||
| 
 | ||||
| pilinfo() | ||||
| pilinfo(supported_formats="--report" not in sys.argv) | ||||
|  |  | |||
|  | @ -230,6 +230,9 @@ def pilinfo(out=None, supported_formats=True): | |||
|     """ | ||||
|     Prints information about this installation of Pillow. | ||||
|     This function can be called with ``python3 -m PIL``. | ||||
|     It can also be called with ``python3 -m PIL.report`` or ``python3 -m PIL --report`` | ||||
|     to have "supported_formats" set to ``False``, omitting the list of all supported | ||||
|     image file formats. | ||||
| 
 | ||||
|     :param out: | ||||
|         The output stream to print to. Defaults to ``sys.stdout`` if ``None``. | ||||
|  | @ -249,12 +252,17 @@ def pilinfo(out=None, supported_formats=True): | |||
|     for py_version in py_version[1:]: | ||||
|         print(f"       {py_version.strip()}", file=out) | ||||
|     print("-" * 68, file=out) | ||||
|     print(f"Python executable is {sys.executable or 'unknown'}", file=out) | ||||
|     if sys.prefix != sys.base_prefix: | ||||
|         print(f"Environment Python files loaded from {sys.prefix}", file=out) | ||||
|     print(f"System Python files loaded from {sys.base_prefix}", file=out) | ||||
|     print("-" * 68, file=out) | ||||
|     print( | ||||
|         f"Python modules loaded from {os.path.dirname(Image.__file__)}", | ||||
|         f"Python Pillow modules loaded from {os.path.dirname(Image.__file__)}", | ||||
|         file=out, | ||||
|     ) | ||||
|     print( | ||||
|         f"Binary modules loaded from {os.path.dirname(Image.core.__file__)}", | ||||
|         f"Binary Pillow modules loaded from {os.path.dirname(Image.core.__file__)}", | ||||
|         file=out, | ||||
|     ) | ||||
|     print("-" * 68, file=out) | ||||
|  |  | |||
							
								
								
									
										5
									
								
								src/PIL/report.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/PIL/report.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| from __future__ import annotations | ||||
| 
 | ||||
| from .features import pilinfo | ||||
| 
 | ||||
| pilinfo(supported_formats=False) | ||||
|  | @ -1578,7 +1578,17 @@ if (PySequence_Check(op)) { \ | |||
|                 int bigendian = 0; | ||||
|                 if (image->type == IMAGING_TYPE_SPECIAL) { | ||||
|                     // I;16*
 | ||||
|                     bigendian = strcmp(image->mode, "I;16B") == 0; | ||||
|                     if (strcmp(image->mode, "I;16N") == 0) { | ||||
| #ifdef WORDS_BIGENDIAN | ||||
|                         bigendian = 1; | ||||
| #else | ||||
|                         bigendian = 0; | ||||
| #endif | ||||
|                     } else if (strcmp(image->mode, "I;16B") == 0) { | ||||
|                         bigendian = 1; | ||||
|                     } else { | ||||
|                         bigendian = 0; | ||||
|                     } | ||||
|                 } | ||||
|                 for (i = x = y = 0; i < n; i++) { | ||||
|                     set_value_to_item(seq, i); | ||||
|  |  | |||
|  | @ -250,6 +250,26 @@ rgb2i(UINT8 *out_, const UINT8 *in, int xsize) { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| rgb2i16l(UINT8 *out_, const UINT8 *in, int xsize) { | ||||
|     int x; | ||||
|     for (x = 0; x < xsize; x++, in += 4) { | ||||
|         UINT8 v = CLIP16(L24(in) >> 16); | ||||
|         *out_++ = v; | ||||
|         *out_++ = v >> 8; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| rgb2i16b(UINT8 *out_, const UINT8 *in, int xsize) { | ||||
|     int x; | ||||
|     for (x = 0; x < xsize; x++, in += 4) { | ||||
|         UINT8 v = CLIP16(L24(in) >> 16); | ||||
|         *out_++ = v >> 8; | ||||
|         *out_++ = v; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| rgb2f(UINT8 *out_, const UINT8 *in, int xsize) { | ||||
|     int x; | ||||
|  | @ -944,6 +964,14 @@ static struct { | |||
|     {"RGB", "LA", rgb2la}, | ||||
|     {"RGB", "La", rgb2la}, | ||||
|     {"RGB", "I", rgb2i}, | ||||
|     {"RGB", "I;16", rgb2i16l}, | ||||
|     {"RGB", "I;16L", rgb2i16l}, | ||||
|     {"RGB", "I;16B", rgb2i16b}, | ||||
| #ifdef WORDS_BIGENDIAN | ||||
|     {"RGB", "I;16N", rgb2i16b}, | ||||
| #else | ||||
|     {"RGB", "I;16N", rgb2i16l}, | ||||
| #endif | ||||
|     {"RGB", "F", rgb2f}, | ||||
|     {"RGB", "BGR;15", rgb2bgr15}, | ||||
|     {"RGB", "BGR;16", rgb2bgr16}, | ||||
|  |  | |||
|  | @ -87,11 +87,18 @@ are set by running ``winbuild\build\build_env.cmd`` and install Pillow with pip: | |||
|     winbuild\build\build_env.cmd | ||||
|     python.exe -m pip install -v -C raqm=vendor -C fribidi=vendor . | ||||
| 
 | ||||
| To build a wheel instead, run:: | ||||
| You can also install Pillow in `editable mode`_:: | ||||
| 
 | ||||
|     winbuild\build\build_env.cmd | ||||
|     python.exe -m pip install -v -C raqm=vendor -C fribidi=vendor -e . | ||||
| 
 | ||||
| To build a binary wheel instead, run:: | ||||
| 
 | ||||
|     winbuild\build\build_env.cmd | ||||
|     python.exe -m pip wheel -v -C raqm=vendor -C fribidi=vendor . | ||||
| 
 | ||||
| .. _editable mode: https://setuptools.pypa.io/en/stable/userguide/development_mode.html | ||||
| 
 | ||||
| Testing Pillow | ||||
| -------------- | ||||
| 
 | ||||
|  |  | |||
|  | @ -113,7 +113,7 @@ V = { | |||
|     "BROTLI": "1.1.0", | ||||
|     "FREETYPE": "2.13.2", | ||||
|     "FRIBIDI": "1.0.13", | ||||
|     "HARFBUZZ": "8.3.1", | ||||
|     "HARFBUZZ": "8.4.0", | ||||
|     "JPEGTURBO": "3.0.2", | ||||
|     "LCMS2": "2.16", | ||||
|     "LIBPNG": "1.6.43", | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user