diff --git a/.ci/requirements-cibw.txt b/.ci/requirements-cibw.txt index 45c2af975..7e257b75c 100644 --- a/.ci/requirements-cibw.txt +++ b/.ci/requirements-cibw.txt @@ -1 +1 @@ -cibuildwheel==2.17.0 +cibuildwheel==2.18.1 diff --git a/.clang-format b/.clang-format index be32e6d1a..3199e330b 100644 --- a/.clang-format +++ b/.clang-format @@ -9,6 +9,7 @@ BinPackParameters: false BreakBeforeBraces: Attach ColumnLimit: 88 DerivePointerAlignment: false +IndentGotoLabels: false IndentWidth: 4 Language: Cpp PointerAlignment: Right diff --git a/.github/workflows/wheels-test.sh b/.github/workflows/wheels-test.sh index 3fbf3be69..a3376ac92 100755 --- a/.github/workflows/wheels-test.sh +++ b/.github/workflows/wheels-test.sh @@ -12,7 +12,7 @@ elif [ "${AUDITWHEEL_POLICY::9}" == "musllinux" ]; then else yum install -y fribidi fi -if [ "${AUDITWHEEL_POLICY::9}" != "musllinux" ]; then +if [ "${AUDITWHEEL_POLICY::9}" != "musllinux" ] && !([[ "$OSTYPE" == "darwin"* ]] && [[ $(python3 --version) == *"3.13."* ]]); then python3 -m pip install numpy fi diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index b2fbd3140..3d6099c1c 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -46,6 +46,7 @@ jobs: - cp310 - cp311 - cp312 + - cp313 spec: - manylinux2014 - manylinux_2_28 @@ -80,6 +81,7 @@ jobs: CIBW_ARCHS: "aarch64" # Likewise, select only one Python version per job to speed this up. CIBW_BUILD: "${{ matrix.python-version }}-${{ matrix.spec == 'musllinux' && 'musllinux' || 'manylinux' }}*" + CIBW_PRERELEASE_PYTHONS: True # Extra options for manylinux. CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.spec }} CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: ${{ matrix.spec }} @@ -133,6 +135,7 @@ jobs: CIBW_BUILD: ${{ matrix.build }} CIBW_MANYLINUX_PYPY_X86_64_IMAGE: ${{ matrix.manylinux }} CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux }} + CIBW_PRERELEASE_PYTHONS: True CIBW_SKIP: pp38-* CIBW_TEST_SKIP: cp38-macosx_arm64 MACOSX_DEPLOYMENT_TARGET: ${{ matrix.macosx_deployment_target }} @@ -204,6 +207,7 @@ jobs: CIBW_ARCHS: ${{ matrix.cibw_arch }} CIBW_BEFORE_ALL: "{package}\\winbuild\\build\\build_dep_all.cmd" CIBW_CACHE_PATH: "C:\\cibw" + CIBW_PRERELEASE_PYTHONS: True CIBW_SKIP: pp38-* CIBW_TEST_SKIP: "*-win_arm64" CIBW_TEST_COMMAND: 'docker run --rm diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 51625eb4c..e848eb670 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,12 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.4 + rev: v0.4.3 hooks: - id: ruff args: [--exit-non-zero-on-fix] - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.3.0 + rev: 24.4.2 hooks: - id: black @@ -23,13 +23,20 @@ repos: - id: remove-tabs exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$) + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v18.1.4 + hooks: + - id: clang-format + types: [c] + exclude: ^src/thirdparty/ + - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: - id: rst-backticks - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-executables-have-shebangs - id: check-shebang-scripts-are-executable @@ -43,7 +50,7 @@ repos: exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/ - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.28.1 + rev: 0.28.2 hooks: - id: check-github-workflows - id: check-readthedocs @@ -55,7 +62,7 @@ repos: - id: sphinx-lint - repo: https://github.com/tox-dev/pyproject-fmt - rev: 1.7.0 + rev: 1.8.0 hooks: - id: pyproject-fmt diff --git a/CHANGES.rst b/CHANGES.rst index c5df1f8f7..dc4016d76 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,15 @@ Changelog (Pillow) 10.4.0 (unreleased) ------------------- +- Added ImageDraw circle() #8085 + [void4, hugovk, radarhere] + +- Add mypy target to Makefile #8077 + [Yay295] + +- Added more modes to Image.MODES #7984 + [radarhere] + - Deprecate BGR;15, BGR;16 and BGR;24 modes #7978 [radarhere, hugovk] diff --git a/Makefile b/Makefile index 1f9b4a370..94f7565d8 100644 --- a/Makefile +++ b/Makefile @@ -118,3 +118,8 @@ lint-fix: python3 -m black . python3 -c "import ruff" > /dev/null 2>&1 || python3 -m pip install ruff python3 -m ruff --fix . + +.PHONY: mypy +mypy: + python3 -c "import tox" > /dev/null 2>&1 || python3 -m pip install tox + python3 -m tox -e mypy diff --git a/Tests/helper.py b/Tests/helper.py index 1297c1c43..fe337c09f 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -29,33 +29,6 @@ elif "GITHUB_ACTIONS" in os.environ: uploader = "github_actions" -modes = ( - "1", - "L", - "LA", - "La", - "P", - "PA", - "F", - "I", - "I;16", - "I;16L", - "I;16B", - "I;16N", - "RGB", - "RGBA", - "RGBa", - "RGBX", - "BGR;15", - "BGR;16", - "BGR;24", - "CMYK", - "YCbCr", - "HSV", - "LAB", -) - - def upload(a: Image.Image, b: Image.Image) -> str | None: if uploader == "show": # local img.show for errors. @@ -201,12 +174,13 @@ def skip_unless_feature(feature: str) -> pytest.MarkDecorator: def skip_unless_feature_version( feature: str, required: str, reason: str | None = None ) -> pytest.MarkDecorator: - if not features.check(feature): + version = features.version(feature) + if version is None: return pytest.mark.skip(f"{feature} not available") if reason is None: reason = f"{feature} is older than {required}" version_required = parse_version(required) - version_available = parse_version(features.version(feature)) + version_available = parse_version(version) return pytest.mark.skipif(version_available < version_required, reason=reason) @@ -216,12 +190,13 @@ def mark_if_feature_version( version_blacklist: str, reason: str | None = None, ) -> pytest.MarkDecorator: - if not features.check(feature): + version = features.version(feature) + if version is None: return pytest.mark.pil_noop_mark() if reason is None: reason = f"{feature} is {version_blacklist}" version_required = parse_version(version_blacklist) - version_available = parse_version(features.version(feature)) + version_available = parse_version(version) if ( version_available.major == version_required.major and version_available.minor == version_required.minor @@ -247,16 +222,11 @@ class PillowLeakTestCase: from resource import RUSAGE_SELF, getrusage mem = getrusage(RUSAGE_SELF).ru_maxrss - if sys.platform == "darwin": - # man 2 getrusage: - # ru_maxrss - # This is the maximum resident set size utilized (in bytes). - return mem / 1024 # Kb - # linux - # man 2 getrusage - # ru_maxrss (since Linux 2.6.32) - # This is the maximum resident set size used (in kilobytes). - return mem # Kb + # man 2 getrusage: + # ru_maxrss + # This is the maximum resident set size utilized + # in bytes on macOS, in kilobytes on Linux + return mem / 1024 if sys.platform == "darwin" else mem def _test_leak(self, core: Callable[[], None]) -> None: start_mem = self._get_mem_usage() diff --git a/Tests/oss-fuzz/test_fuzzers.py b/Tests/oss-fuzz/test_fuzzers.py index 58d0213e8..90eb8713a 100644 --- a/Tests/oss-fuzz/test_fuzzers.py +++ b/Tests/oss-fuzz/test_fuzzers.py @@ -12,8 +12,9 @@ from Tests.helper import skip_unless_feature if sys.platform.startswith("win32"): pytest.skip("Fuzzer is linux only", allow_module_level=True) -if features.check("libjpeg_turbo"): - version = packaging.version.parse(features.version("libjpeg_turbo")) +libjpeg_turbo_version = features.version("libjpeg_turbo") +if libjpeg_turbo_version is not None: + version = packaging.version.parse(libjpeg_turbo_version) if version.major == 2 and version.minor == 0: pytestmark = pytest.mark.valgrind_known_error( reason="Known failing with libjpeg_turbo 2.0" diff --git a/Tests/test_features.py b/Tests/test_features.py index 2d402ca91..59fb49809 100644 --- a/Tests/test_features.py +++ b/Tests/test_features.py @@ -30,7 +30,7 @@ def test_version() -> None: # Check the correctness of the convenience function # and the format of version numbers - def test(name: str, function: Callable[[str], bool]) -> None: + def test(name: str, function: Callable[[str], str | None]) -> None: version = features.version(name) if not features.check(name): assert version is None @@ -67,12 +67,16 @@ def test_webp_anim() -> None: @skip_unless_feature("libjpeg_turbo") def test_libjpeg_turbo_version() -> None: - assert re.search(r"\d+\.\d+\.\d+$", features.version("libjpeg_turbo")) + version = features.version("libjpeg_turbo") + assert version is not None + assert re.search(r"\d+\.\d+\.\d+$", version) @skip_unless_feature("libimagequant") def test_libimagequant_version() -> None: - assert re.search(r"\d+\.\d+\.\d+$", features.version("libimagequant")) + version = features.version("libimagequant") + assert version is not None + assert re.search(r"\d+\.\d+\.\d+$", version) @pytest.mark.parametrize("feature", features.modules) diff --git a/Tests/test_file_eps.py b/Tests/test_file_eps.py index d01884f96..1c21aa8ca 100644 --- a/Tests/test_file_eps.py +++ b/Tests/test_file_eps.py @@ -336,9 +336,7 @@ def test_readline_psfile(tmp_path: Path) -> None: strings = ["something", "else", "baz", "bif"] def _test_readline(t: EpsImagePlugin.PSFile, ending: str) -> None: - ending = "Failure with line ending: %s" % ( - "".join("%s" % ord(s) for s in ending) - ) + ending = f"Failure with line ending: {''.join(str(ord(s)) for s in ending)}" assert t.readline().strip("\r\n") == "something", ending assert t.readline().strip("\r\n") == "else", ending assert t.readline().strip("\r\n") == "baz", ending diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 5d2157651..f24faecaa 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -70,7 +70,9 @@ class TestFileJpeg: def test_sanity(self) -> None: # internal version number - assert re.search(r"\d+\.\d+$", features.version_codec("jpg")) + version = features.version_codec("jpg") + assert version is not None + assert re.search(r"\d+\.\d+$", version) with Image.open(TEST_FILE) as im: im.load() diff --git a/Tests/test_file_jpeg2k.py b/Tests/test_file_jpeg2k.py index a7cae563a..5a208739f 100644 --- a/Tests/test_file_jpeg2k.py +++ b/Tests/test_file_jpeg2k.py @@ -48,7 +48,9 @@ def roundtrip(im: Image.Image, **options: Any) -> Image.Image: def test_sanity() -> None: # Internal version number - assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("jpg_2000")) + version = features.version_codec("jpg_2000") + assert version is not None + assert re.search(r"\d+\.\d+\.\d+$", version) with Image.open("Tests/images/test-card-lossless.jp2") as im: px = im.load() diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 11883ad24..6c13999a5 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -52,7 +52,9 @@ class LibTiffTestCase: class TestFileLibTiff(LibTiffTestCase): def test_version(self) -> None: - assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("libtiff")) + version = features.version_codec("libtiff") + assert version is not None + assert re.search(r"\d+\.\d+\.\d+$", version) def test_g4_tiff(self, tmp_path: Path) -> None: """Test the ordinary file path load path""" diff --git a/Tests/test_file_mpeg.py b/Tests/test_file_mpeg.py new file mode 100644 index 000000000..468aef8a9 --- /dev/null +++ b/Tests/test_file_mpeg.py @@ -0,0 +1,39 @@ +from __future__ import annotations + +from io import BytesIO + +import pytest + +from PIL import Image, MpegImagePlugin + + +def test_identify() -> None: + # Arrange + b = BytesIO(b"\x00\x00\x01\xb3\x01\x00\x01") + + # Act + with Image.open(b) as im: + # Assert + assert im.format == "MPEG" + + assert im.mode == "RGB" + assert im.size == (16, 1) + + +def test_invalid_file() -> None: + # Arrange + invalid_file = "Tests/images/flower.jpg" + + # Act / Assert + with pytest.raises(SyntaxError): + MpegImagePlugin.MpegImageFile(invalid_file) + + +def test_load() -> None: + # Arrange + b = BytesIO(b"\x00\x00\x01\xb3\x01\x00\x01") + + with Image.open(b) as im: + # Act / Assert: cannot load + with pytest.raises(OSError): + im.load() diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index 19462dcb5..c7c9f6fab 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -85,9 +85,9 @@ class TestFilePng: def test_sanity(self, tmp_path: Path) -> None: # internal version number - assert re.search( - r"\d+(\.\d+){1,3}(\.zlib\-ng)?$", features.version_codec("zlib") - ) + version = features.version_codec("zlib") + assert version is not None + assert re.search(r"\d+(\.\d+){1,3}(\.zlib\-ng)?$", version) test_file = str(tmp_path / "temp.png") diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py index 249846da4..e2de84c71 100644 --- a/Tests/test_file_webp.py +++ b/Tests/test_file_webp.py @@ -49,7 +49,9 @@ class TestFileWebp: def test_version(self) -> None: _webp.WebPDecoderVersion() _webp.WebPDecoderBuggyAlpha() - assert re.search(r"\d+\.\d+\.\d+$", features.version_module("webp")) + version = features.version_module("webp") + assert version is not None + assert re.search(r"\d+\.\d+\.\d+$", version) def test_read_rgb(self) -> None: """ diff --git a/Tests/test_file_webp_animated.py b/Tests/test_file_webp_animated.py index 6a9337fa5..ba931f864 100644 --- a/Tests/test_file_webp_animated.py +++ b/Tests/test_file_webp_animated.py @@ -52,8 +52,9 @@ def test_write_animation_L(tmp_path: Path) -> None: assert_image_similar(im, orig.convert("RGBA"), 32.9) if is_big_endian(): - webp = parse_version(features.version_module("webp")) - if webp < parse_version("1.2.2"): + version = features.version_module("webp") + assert version is not None + if parse_version(version) < parse_version("1.2.2"): pytest.skip("Fails with libwebp earlier than 1.2.2") orig.seek(orig.n_frames - 1) im.seek(im.n_frames - 1) @@ -78,8 +79,9 @@ def test_write_animation_RGB(tmp_path: Path) -> None: # Compare second frame to original if is_big_endian(): - webp = parse_version(features.version_module("webp")) - if webp < parse_version("1.2.2"): + version = features.version_module("webp") + assert version is not None + if parse_version(version) < parse_version("1.2.2"): pytest.skip("Fails with libwebp earlier than 1.2.2") im.seek(1) im.load() diff --git a/Tests/test_image.py b/Tests/test_image.py index e1490d6a0..742d0dfe4 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -31,7 +31,6 @@ from .helper import ( is_big_endian, is_win32, mark_if_feature_version, - modes, skip_unless_feature, ) @@ -46,7 +45,7 @@ def helper_image_new(mode: str, size: tuple[int, int]) -> Image.Image: class TestImage: - @pytest.mark.parametrize("mode", modes) + @pytest.mark.parametrize("mode", Image.MODES + ["BGR;15", "BGR;16", "BGR;24"]) def test_image_modes_success(self, mode: str) -> None: helper_image_new(mode, (1, 1)) @@ -1027,7 +1026,7 @@ class TestImage: class TestImageBytes: - @pytest.mark.parametrize("mode", modes) + @pytest.mark.parametrize("mode", Image.MODES + ["BGR;15", "BGR;16", "BGR;24"]) def test_roundtrip_bytes_constructor(self, mode: str) -> None: im = hopper(mode) source_bytes = im.tobytes() @@ -1039,7 +1038,7 @@ class TestImageBytes: reloaded = Image.frombytes(mode, im.size, source_bytes) assert reloaded.tobytes() == source_bytes - @pytest.mark.parametrize("mode", modes) + @pytest.mark.parametrize("mode", Image.MODES + ["BGR;15", "BGR;16", "BGR;24"]) def test_roundtrip_bytes_method(self, mode: str) -> None: im = hopper(mode) source_bytes = im.tobytes() @@ -1048,7 +1047,7 @@ class TestImageBytes: reloaded.frombytes(source_bytes) assert reloaded.tobytes() == source_bytes - @pytest.mark.parametrize("mode", modes) + @pytest.mark.parametrize("mode", Image.MODES + ["BGR;15", "BGR;16", "BGR;24"]) def test_getdata_putdata(self, mode: str) -> None: if is_big_endian() and mode == "BGR;15": pytest.xfail("Known failure of BGR;15 on big-endian") diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index 02c75073a..9d6006679 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -10,7 +10,7 @@ import pytest from PIL import Image -from .helper import assert_image_equal, hopper, is_win32, modes +from .helper import assert_image_equal, hopper, is_win32 # CFFI imports pycparser which doesn't support PYTHONOPTIMIZE=2 # https://github.com/eliben/pycparser/pull/198#issuecomment-317001670 @@ -205,12 +205,13 @@ class TestImageGetPixel(AccessTest): with pytest.raises(error): im.getpixel((-1, -1)) - @pytest.mark.parametrize("mode", modes) + @pytest.mark.parametrize("mode", Image.MODES) def test_basic(self, mode: str) -> None: - if mode.startswith("BGR;"): - with pytest.warns(DeprecationWarning): - self.check(mode) - else: + self.check(mode) + + @pytest.mark.parametrize("mode", ("BGR;15", "BGR;16", "BGR;24")) + def test_deprecated(self, mode: str) -> None: + with pytest.warns(DeprecationWarning): self.check(mode) def test_list(self) -> None: @@ -409,13 +410,14 @@ class TestEmbeddable: from setuptools.command import build_ext with open("embed_pil.c", "w", encoding="utf-8") as fh: + home = sys.prefix.replace("\\", "\\\\") fh.write( - """ + f""" #include "Python.h" int main(int argc, char* argv[]) -{ - char *home = "%s"; +{{ + char *home = "{home}"; wchar_t *whome = Py_DecodeLocale(home, NULL); Py_SetPythonHome(whome); @@ -430,9 +432,8 @@ int main(int argc, char* argv[]) PyMem_RawFree(whome); return 0; -} +}} """ - % sys.prefix.replace("\\", "\\\\") ) compiler = getattr(build_ext, "new_compiler")() diff --git a/Tests/test_image_quantize.py b/Tests/test_image_quantize.py index e1aa6252b..2daaf5c3c 100644 --- a/Tests/test_image_quantize.py +++ b/Tests/test_image_quantize.py @@ -24,8 +24,9 @@ def test_sanity() -> None: def test_libimagequant_quantize() -> None: image = hopper() if is_ppc64le(): - libimagequant = parse_version(features.version_feature("libimagequant")) - if libimagequant < parse_version("4"): + version = features.version_feature("libimagequant") + assert version is not None + if parse_version(version) < parse_version("4"): pytest.skip("Fails with libimagequant earlier than 4.0.0 on ppc64le") converted = image.quantize(100, Image.Quantize.LIBIMAGEQUANT) assert converted.mode == "P" diff --git a/Tests/test_image_reduce.py b/Tests/test_image_reduce.py index fcf671daa..f6609a1a0 100644 --- a/Tests/test_image_reduce.py +++ b/Tests/test_image_reduce.py @@ -102,7 +102,7 @@ def test_unsupported_modes(mode: str) -> None: def get_image(mode: str) -> Image.Image: mode_info = ImageMode.getmode(mode) if mode_info.basetype == "L": - bands = [gradients_image] + bands: list[Image.Image] = [gradients_image] for _ in mode_info.bands[1:]: # rotate previous image band = bands[-1].transpose(Image.Transpose.ROTATE_90) diff --git a/Tests/test_imagecms.py b/Tests/test_imagecms.py index bf629fa79..8d2029c21 100644 --- a/Tests/test_imagecms.py +++ b/Tests/test_imagecms.py @@ -60,10 +60,13 @@ def test_sanity() -> None: assert list(map(type, v)) == [str, str, str, str] # internal version number - assert re.search(r"\d+\.\d+(\.\d+)?$", features.version_module("littlecms2")) + version = features.version_module("littlecms2") + assert version is not None + assert re.search(r"\d+\.\d+(\.\d+)?$", version) skip_missing() i = ImageCms.profileToProfile(hopper(), SRGB, SRGB) + assert i is not None assert_image(i, "RGB", (128, 128)) i = hopper() @@ -72,23 +75,27 @@ def test_sanity() -> None: t = ImageCms.buildTransform(SRGB, SRGB, "RGB", "RGB") i = ImageCms.applyTransform(hopper(), t) + assert i is not None assert_image(i, "RGB", (128, 128)) with hopper() as i: t = ImageCms.buildTransform(SRGB, SRGB, "RGB", "RGB") ImageCms.applyTransform(hopper(), t, inPlace=True) + assert i is not None assert_image(i, "RGB", (128, 128)) p = ImageCms.createProfile("sRGB") o = ImageCms.getOpenProfile(SRGB) t = ImageCms.buildTransformFromOpenProfiles(p, o, "RGB", "RGB") i = ImageCms.applyTransform(hopper(), t) + assert i is not None assert_image(i, "RGB", (128, 128)) t = ImageCms.buildProofTransform(SRGB, SRGB, SRGB, "RGB", "RGB") assert t.inputMode == "RGB" assert t.outputMode == "RGB" i = ImageCms.applyTransform(hopper(), t) + assert i is not None assert_image(i, "RGB", (128, 128)) # test PointTransform convenience API @@ -260,7 +267,7 @@ def test_simple_lab() -> None: t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB") i_lab = ImageCms.applyTransform(i, t) - + assert i_lab is not None assert i_lab.mode == "LAB" k = i_lab.getpixel((0, 0)) @@ -284,6 +291,7 @@ def test_lab_color() -> None: # Need to add a type mapping for some PIL type to TYPE_Lab_8 in findLCMSType, and # have that mapping work back to a PIL mode (likely RGB). i = ImageCms.applyTransform(hopper(), t) + assert i is not None assert_image(i, "LAB", (128, 128)) # i.save('temp.lab.tif') # visually verified vs PS. @@ -298,6 +306,7 @@ def test_lab_srgb() -> None: with Image.open("Tests/images/hopper.Lab.tif") as img: img_srgb = ImageCms.applyTransform(img, t) + assert img_srgb is not None # img_srgb.save('temp.srgb.tif') # visually verified vs ps. @@ -317,11 +326,11 @@ def test_lab_roundtrip() -> None: t2 = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB") i = ImageCms.applyTransform(hopper(), t) - + assert i is not None assert i.info["icc_profile"] == ImageCmsProfile(pLab).tobytes() out = ImageCms.applyTransform(i, t2) - + assert out is not None assert_image_similar(hopper(), out, 2) @@ -657,7 +666,7 @@ def test_auxiliary_channels_isolated() -> None: reference_image = ImageCms.applyTransform( source_image.convert(src_format[2]), reference_transform ) - + assert reference_image is not None assert_image_equal(test_image.convert(dst_format[2]), reference_image) diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 0a699e2ab..69d09e03d 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -2,6 +2,7 @@ from __future__ import annotations import contextlib import os.path +from typing import Sequence import pytest @@ -265,6 +266,21 @@ def test_chord_too_fat() -> None: assert_image_equal_tofile(im, "Tests/images/imagedraw_chord_too_fat.png") +@pytest.mark.parametrize("mode", ("RGB", "L")) +@pytest.mark.parametrize("xy", ((W / 2, H / 2), [W / 2, H / 2])) +def test_circle(mode: str, xy: Sequence[float]) -> None: + # Arrange + im = Image.new(mode, (W, H)) + draw = ImageDraw.Draw(im) + expected = f"Tests/images/imagedraw_ellipse_{mode}.png" + + # Act + draw.circle(xy, 25, fill="green", outline="blue") + + # Assert + assert_image_similar_tofile(im, expected, 1) + + @pytest.mark.parametrize("mode", ("RGB", "L")) @pytest.mark.parametrize("bbox", BBOX) def test_ellipse(mode: str, bbox: Coords) -> None: diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py index ddcae80d6..c9dba2943 100644 --- a/Tests/test_imagefile.py +++ b/Tests/test_imagefile.py @@ -202,6 +202,8 @@ class TestImageFile: class MockPyDecoder(ImageFile.PyDecoder): + last: MockPyDecoder + def __init__(self, mode: str, *args: Any) -> None: MockPyDecoder.last = self @@ -213,6 +215,8 @@ class MockPyDecoder(ImageFile.PyDecoder): class MockPyEncoder(ImageFile.PyEncoder): + last: MockPyEncoder | None + def __init__(self, mode: str, *args: Any) -> None: MockPyEncoder.last = self @@ -315,6 +319,7 @@ class TestPyEncoder(CodecsTest): im, fp, [("MOCK", (xoff, yoff, xoff + xsize, yoff + ysize), 0, "RGB")] ) + assert MockPyEncoder.last assert MockPyEncoder.last.state.xoff == xoff assert MockPyEncoder.last.state.yoff == yoff assert MockPyEncoder.last.state.xsize == xsize @@ -329,6 +334,7 @@ class TestPyEncoder(CodecsTest): fp = BytesIO() ImageFile._save(im, fp, [("MOCK", None, 0, "RGB")]) + assert MockPyEncoder.last assert MockPyEncoder.last.state.xoff == 0 assert MockPyEncoder.last.state.yoff == 0 assert MockPyEncoder.last.state.xsize == 200 diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 05b5d4716..4398f8a30 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -34,7 +34,9 @@ pytestmark = skip_unless_feature("freetype2") def test_sanity() -> None: - assert re.search(r"\d+\.\d+\.\d+$", features.version_module("freetype2")) + version = features.version_module("freetype2") + assert version is not None + assert re.search(r"\d+\.\d+\.\d+$", version) @pytest.fixture( @@ -547,11 +549,10 @@ def test_find_font( def loadable_font( filepath: str, size: int, index: int, encoding: str, *args: Any ): + _freeTypeFont = getattr(ImageFont, "_FreeTypeFont") if filepath == path_to_fake: - return ImageFont._FreeTypeFont( - FONT_PATH, size, index, encoding, *args - ) - return ImageFont._FreeTypeFont(filepath, size, index, encoding, *args) + return _freeTypeFont(FONT_PATH, size, index, encoding, *args) + return _freeTypeFont(filepath, size, index, encoding, *args) m.setattr(ImageFont, "FreeTypeFont", loadable_font) font = ImageFont.truetype(fontname) @@ -630,7 +631,9 @@ def test_complex_font_settings() -> None: def test_variation_get(font: ImageFont.FreeTypeFont) -> None: - freetype = parse_version(features.version_module("freetype2")) + version = features.version_module("freetype2") + assert version is not None + freetype = parse_version(version) if freetype < parse_version("2.9.1"): with pytest.raises(NotImplementedError): font.get_variation_names() @@ -700,7 +703,9 @@ def _check_text(font: ImageFont.FreeTypeFont, path: str, epsilon: float) -> None def test_variation_set_by_name(font: ImageFont.FreeTypeFont) -> None: - freetype = parse_version(features.version_module("freetype2")) + version = features.version_module("freetype2") + assert version is not None + freetype = parse_version(version) if freetype < parse_version("2.9.1"): with pytest.raises(NotImplementedError): font.set_variation_by_name("Bold") @@ -725,7 +730,9 @@ def test_variation_set_by_name(font: ImageFont.FreeTypeFont) -> None: def test_variation_set_by_axes(font: ImageFont.FreeTypeFont) -> None: - freetype = parse_version(features.version_module("freetype2")) + version = features.version_module("freetype2") + assert version is not None + freetype = parse_version(version) if freetype < parse_version("2.9.1"): with pytest.raises(NotImplementedError): font.set_variation_by_axes([100]) diff --git a/Tests/test_imageops_usm.py b/Tests/test_imageops_usm.py index c15907a55..104c620de 100644 --- a/Tests/test_imageops_usm.py +++ b/Tests/test_imageops_usm.py @@ -4,11 +4,11 @@ from typing import Generator import pytest -from PIL import Image, ImageFilter +from PIL import Image, ImageFile, ImageFilter @pytest.fixture -def test_images() -> Generator[dict[str, Image.Image], None, None]: +def test_images() -> Generator[dict[str, ImageFile.ImageFile], None, None]: ims = { "im": Image.open("Tests/images/hopper.ppm"), "snakes": Image.open("Tests/images/color_snakes.png"), @@ -20,7 +20,7 @@ def test_images() -> Generator[dict[str, Image.Image], None, None]: im.close() -def test_filter_api(test_images: dict[str, Image.Image]) -> None: +def test_filter_api(test_images: dict[str, ImageFile.ImageFile]) -> None: im = test_images["im"] test_filter = ImageFilter.GaussianBlur(2.0) @@ -34,7 +34,7 @@ def test_filter_api(test_images: dict[str, Image.Image]) -> None: assert i.size == (128, 128) -def test_usm_formats(test_images: dict[str, Image.Image]) -> None: +def test_usm_formats(test_images: dict[str, ImageFile.ImageFile]) -> None: im = test_images["im"] usm = ImageFilter.UnsharpMask @@ -52,7 +52,7 @@ def test_usm_formats(test_images: dict[str, Image.Image]) -> None: im.convert("YCbCr").filter(usm) -def test_blur_formats(test_images: dict[str, Image.Image]) -> None: +def test_blur_formats(test_images: dict[str, ImageFile.ImageFile]) -> None: im = test_images["im"] blur = ImageFilter.GaussianBlur @@ -70,7 +70,7 @@ def test_blur_formats(test_images: dict[str, Image.Image]) -> None: im.convert("YCbCr").filter(blur) -def test_usm_accuracy(test_images: dict[str, Image.Image]) -> None: +def test_usm_accuracy(test_images: dict[str, ImageFile.ImageFile]) -> None: snakes = test_images["snakes"] src = snakes.convert("RGB") @@ -79,7 +79,7 @@ def test_usm_accuracy(test_images: dict[str, Image.Image]) -> None: assert i.tobytes() == src.tobytes() -def test_blur_accuracy(test_images: dict[str, Image.Image]) -> None: +def test_blur_accuracy(test_images: dict[str, ImageFile.ImageFile]) -> None: snakes = test_images["snakes"] i = snakes.filter(ImageFilter.GaussianBlur(0.4)) diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index e7339ecbe..3e9aa73f8 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -227,6 +227,18 @@ Methods .. versionadded:: 5.3.0 +.. py:method:: ImageDraw.circle(xy, radius, fill=None, outline=None, width=1) + + Draws a circle with a given radius centering on a point. + + .. versionadded:: 10.4.0 + + :param xy: The point for the center of the circle, e.g. ``(x, y)``. + :param radius: Radius of the circle. + :param outline: Color to use for the outline. + :param fill: Color to use for the fill. + :param width: The line width, in pixels. + .. py:method:: ImageDraw.ellipse(xy, fill=None, outline=None, width=1) Draws an ellipse inside the given bounding box. diff --git a/docs/releasenotes/10.4.0.rst b/docs/releasenotes/10.4.0.rst index 3150bf4e0..e0d695a8b 100644 --- a/docs/releasenotes/10.4.0.rst +++ b/docs/releasenotes/10.4.0.rst @@ -45,6 +45,13 @@ TODO API Additions ============= +ImageDraw.circle +^^^^^^^^^^^^^^^^ + +Added :py:meth:`~PIL.ImageDraw.ImageDraw.circle`. It provides the same functionality as +:py:meth:`~PIL.ImageDraw.ImageDraw.ellipse`, but instead of taking a bounding box, it +takes a center point and radius. + TODO ^^^^ @@ -53,7 +60,9 @@ TODO Other Changes ============= -TODO -^^^^ +Python 3.13 beta +^^^^^^^^^^^^^^^^ -TODO +To help others prepare for Python 3.13, wheels have been built against the 3.13 beta as +a preview. This is not official support for Python 3.13, but simply an opportunity for +users to test how Pillow works with the beta and report any problems. diff --git a/selftest.py b/selftest.py index 661abcddb..9e049367e 100755 --- a/selftest.py +++ b/selftest.py @@ -165,9 +165,9 @@ if __name__ == "__main__": print("Running selftest:") status = doctest.testmod(sys.modules[__name__]) if status[0]: - print("*** %s tests of %d failed." % status) + print(f"*** {status[0]} tests of {status[1]} failed.") exit_status = 1 else: - print("--- %s tests passed." % status[1]) + print(f"--- {status[1]} tests passed.") sys.exit(exit_status) diff --git a/setup.py b/setup.py index 7d8e1c1ee..abdd87ea2 100644 --- a/setup.py +++ b/setup.py @@ -23,8 +23,7 @@ from setuptools.command.build_ext import build_ext def get_version(): version_file = "src/PIL/_version.py" with open(version_file, encoding="utf-8") as f: - exec(compile(f.read(), version_file, "exec")) - return locals()["__version__"] + return f.read().split('"')[1] configuration = {} diff --git a/src/PIL/BlpImagePlugin.py b/src/PIL/BlpImagePlugin.py index 8d351ce91..bdf54baae 100644 --- a/src/PIL/BlpImagePlugin.py +++ b/src/PIL/BlpImagePlugin.py @@ -253,7 +253,7 @@ class BlpImageFile(ImageFile.ImageFile): format = "BLP" format_description = "Blizzard Mipmap Format" - def _open(self): + def _open(self) -> None: self.magic = self.fp.read(4) self.fp.seek(5, os.SEEK_CUR) @@ -333,7 +333,7 @@ class _BLPBaseDecoder(ImageFile.PyDecoder): class BLP1Decoder(_BLPBaseDecoder): - def _load(self): + def _load(self) -> None: if self._blp_compression == Format.JPEG: self._decode_jpeg_stream() @@ -418,7 +418,7 @@ class BLP2Decoder(_BLPBaseDecoder): class BLPEncoder(ImageFile.PyEncoder): _pushes_fd = True - def _write_palette(self): + def _write_palette(self) -> bytes: data = b"" palette = self.im.getpalette("RGBA", "RGBA") for i in range(len(palette) // 4): diff --git a/src/PIL/BmpImagePlugin.py b/src/PIL/BmpImagePlugin.py index 9ce0fed88..c5d1cd40d 100644 --- a/src/PIL/BmpImagePlugin.py +++ b/src/PIL/BmpImagePlugin.py @@ -283,7 +283,7 @@ class BmpImageFile(ImageFile.ImageFile): ) ] - def _open(self): + def _open(self) -> None: """Open file, check magic number and read header""" # read 14 bytes: magic number, filesize, reserved, header final offset head_data = self.fp.read(14) @@ -376,7 +376,7 @@ class DibImageFile(BmpImageFile): format = "DIB" format_description = "Windows Bitmap" - def _open(self): + def _open(self) -> None: self._bitmap() diff --git a/src/PIL/BufrStubImagePlugin.py b/src/PIL/BufrStubImagePlugin.py index 1cbd50d19..271db7258 100644 --- a/src/PIL/BufrStubImagePlugin.py +++ b/src/PIL/BufrStubImagePlugin.py @@ -37,7 +37,7 @@ class BufrStubImageFile(ImageFile.StubImageFile): format = "BUFR" format_description = "BUFR" - def _open(self): + def _open(self) -> None: offset = self.fp.tell() if not _accept(self.fp.read(4)): diff --git a/src/PIL/CurImagePlugin.py b/src/PIL/CurImagePlugin.py index b8790e209..85e2145e7 100644 --- a/src/PIL/CurImagePlugin.py +++ b/src/PIL/CurImagePlugin.py @@ -37,7 +37,7 @@ class CurImageFile(BmpImagePlugin.BmpImageFile): format = "CUR" format_description = "Windows Cursor" - def _open(self): + def _open(self) -> None: offset = self.fp.tell() # check magic diff --git a/src/PIL/DcxImagePlugin.py b/src/PIL/DcxImagePlugin.py index b24c16329..1c455b032 100644 --- a/src/PIL/DcxImagePlugin.py +++ b/src/PIL/DcxImagePlugin.py @@ -63,7 +63,7 @@ class DcxImageFile(PcxImageFile): self.is_animated = self.n_frames > 1 self.seek(0) - def seek(self, frame): + def seek(self, frame: int) -> None: if not self._seek_check(frame): return self.frame = frame @@ -71,7 +71,7 @@ class DcxImageFile(PcxImageFile): self.fp.seek(self._offset[frame]) PcxImageFile._open(self) - def tell(self): + def tell(self) -> int: return self.frame diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 2496088af..1575f2d88 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -331,7 +331,7 @@ class DdsImageFile(ImageFile.ImageFile): format = "DDS" format_description = "DirectDraw Surface" - def _open(self): + def _open(self) -> None: if not _accept(self.fp.read(4)): msg = "not a DDS file" raise SyntaxError(msg) @@ -472,7 +472,7 @@ class DdsImageFile(ImageFile.ImageFile): else: self.tile = [ImageFile._Tile("raw", extents, 0, rawmode or self.mode)] - def load_seek(self, pos): + def load_seek(self, pos: int) -> None: pass diff --git a/src/PIL/EpsImagePlugin.py b/src/PIL/EpsImagePlugin.py index ec6705742..5a44baa49 100644 --- a/src/PIL/EpsImagePlugin.py +++ b/src/PIL/EpsImagePlugin.py @@ -42,7 +42,7 @@ gs_binary: str | bool | None = None gs_windows_binary = None -def has_ghostscript(): +def has_ghostscript() -> bool: global gs_binary, gs_windows_binary if gs_binary is None: if sys.platform.startswith("win"): @@ -178,7 +178,7 @@ class PSFile: self.char = None self.fp.seek(offset, whence) - def readline(self): + def readline(self) -> str: s = [self.char or b""] self.char = None @@ -212,7 +212,7 @@ class EpsImageFile(ImageFile.ImageFile): mode_map = {1: "L", 2: "LAB", 3: "RGB", 4: "CMYK"} - def _open(self): + def _open(self) -> None: (length, offset) = self._find_offset(self.fp) # go to offset - start of "%!PS" @@ -404,7 +404,7 @@ class EpsImageFile(ImageFile.ImageFile): self.tile = [] return Image.Image.load(self) - def load_seek(self, pos): + def load_seek(self, pos: int) -> None: # we can't incrementally load, so force ImageFile.parser to # use our custom load method by defining this method. pass diff --git a/src/PIL/FliImagePlugin.py b/src/PIL/FliImagePlugin.py index 7a233d015..dceb83927 100644 --- a/src/PIL/FliImagePlugin.py +++ b/src/PIL/FliImagePlugin.py @@ -123,7 +123,7 @@ class FliImageFile(ImageFile.ImageFile): palette[i] = (r, g, b) i += 1 - def seek(self, frame): + def seek(self, frame: int) -> None: if not self._seek_check(frame): return if frame < self.__frame: @@ -132,7 +132,7 @@ class FliImageFile(ImageFile.ImageFile): for f in range(self.__frame + 1, frame + 1): self._seek(f) - def _seek(self, frame): + def _seek(self, frame: int) -> None: if frame == 0: self.__frame = -1 self._fp.seek(self.__rewind) @@ -162,7 +162,7 @@ class FliImageFile(ImageFile.ImageFile): self.__offset += framesize - def tell(self): + def tell(self) -> int: return self.__frame diff --git a/src/PIL/FpxImagePlugin.py b/src/PIL/FpxImagePlugin.py index cfaf86239..4ba93bb39 100644 --- a/src/PIL/FpxImagePlugin.py +++ b/src/PIL/FpxImagePlugin.py @@ -237,7 +237,7 @@ class FpxImageFile(ImageFile.ImageFile): return ImageFile.ImageFile.load(self) - def close(self): + def close(self) -> None: self.ole.close() super().close() diff --git a/src/PIL/FtexImagePlugin.py b/src/PIL/FtexImagePlugin.py index a746959a3..5acbb4912 100644 --- a/src/PIL/FtexImagePlugin.py +++ b/src/PIL/FtexImagePlugin.py @@ -71,7 +71,7 @@ class FtexImageFile(ImageFile.ImageFile): format = "FTEX" format_description = "Texture File Format (IW2:EOC)" - def _open(self): + def _open(self) -> None: if not _accept(self.fp.read(4)): msg = "not an FTEX file" raise SyntaxError(msg) @@ -103,7 +103,7 @@ class FtexImageFile(ImageFile.ImageFile): self.fp.close() self.fp = BytesIO(data) - def load_seek(self, pos): + def load_seek(self, pos: int) -> None: pass diff --git a/src/PIL/GbrImagePlugin.py b/src/PIL/GbrImagePlugin.py index 62197e36c..93e89b1e6 100644 --- a/src/PIL/GbrImagePlugin.py +++ b/src/PIL/GbrImagePlugin.py @@ -41,7 +41,7 @@ class GbrImageFile(ImageFile.ImageFile): format = "GBR" format_description = "GIMP brush file" - def _open(self): + def _open(self) -> None: header_size = i32(self.fp.read(4)) if header_size < 20: msg = "not a GIMP brush" diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 93be7fefb..962a92834 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -30,6 +30,7 @@ import math import os import subprocess from enum import IntEnum +from functools import cached_property from . import ( Image, @@ -76,19 +77,19 @@ class GifImageFile(ImageFile.ImageFile): global_palette = None - def data(self): + def data(self) -> bytes | None: s = self.fp.read(1) if s and s[0]: return self.fp.read(s[0]) return None - def _is_palette_needed(self, p): + def _is_palette_needed(self, p: bytes) -> bool: for i in range(0, len(p), 3): if not (i // 3 == p[i] == p[i + 1] == p[i + 2]): return True return False - def _open(self): + def _open(self) -> None: # Screen s = self.fp.read(13) if not _accept(s): @@ -112,8 +113,7 @@ class GifImageFile(ImageFile.ImageFile): self._fp = self.fp # FIXME: hack self.__rewind = self.fp.tell() - self._n_frames = None - self._is_animated = None + self._n_frames: int | None = None self._seek(0) # get ready to read first frame @property @@ -128,26 +128,25 @@ class GifImageFile(ImageFile.ImageFile): self.seek(current) return self._n_frames - @property - def is_animated(self): - if self._is_animated is None: - if self._n_frames is not None: - self._is_animated = self._n_frames != 1 - else: - current = self.tell() - if current: - self._is_animated = True - else: - try: - self._seek(1, False) - self._is_animated = True - except EOFError: - self._is_animated = False + @cached_property + def is_animated(self) -> bool: + if self._n_frames is not None: + return self._n_frames != 1 - self.seek(current) - return self._is_animated + current = self.tell() + if current: + return True - def seek(self, frame): + try: + self._seek(1, False) + is_animated = True + except EOFError: + is_animated = False + + self.seek(current) + return is_animated + + def seek(self, frame: int) -> None: if not self._seek_check(frame): return if frame < self.__frame: @@ -417,7 +416,7 @@ class GifImageFile(ImageFile.ImageFile): elif k in self.info: del self.info[k] - def load_prepare(self): + def load_prepare(self) -> None: temp_mode = "P" if self._frame_palette else "L" self._prev_im = None if self.__frame == 0: @@ -437,7 +436,7 @@ class GifImageFile(ImageFile.ImageFile): super().load_prepare() - def load_end(self): + def load_end(self) -> None: if self.__frame == 0: if self.mode == "P" and LOADING_STRATEGY == LoadingStrategy.RGB_ALWAYS: if self._frame_transparency is not None: @@ -463,7 +462,7 @@ class GifImageFile(ImageFile.ImageFile): else: self.im.paste(frame_im, self.dispose_extent) - def tell(self): + def tell(self) -> int: return self.__frame @@ -474,7 +473,7 @@ class GifImageFile(ImageFile.ImageFile): RAWMODE = {"1": "L", "L": "L", "P": "P"} -def _normalize_mode(im): +def _normalize_mode(im: Image.Image) -> Image.Image: """ Takes an image (or frame), returns an image in a mode that is appropriate for saving in a Gif. @@ -887,7 +886,7 @@ def _get_optimize(im, info): return used_palette_colors -def _get_color_table_size(palette_bytes): +def _get_color_table_size(palette_bytes: bytes) -> int: # calculate the palette size for the header if not palette_bytes: return 0 @@ -897,7 +896,7 @@ def _get_color_table_size(palette_bytes): return math.ceil(math.log(len(palette_bytes) // 3, 2)) - 1 -def _get_header_palette(palette_bytes): +def _get_header_palette(palette_bytes: bytes) -> bytes: """ Returns the palette, null padded to the next power of 2 (*3) bytes suitable for direct inclusion in the GIF header @@ -915,7 +914,7 @@ def _get_header_palette(palette_bytes): return palette_bytes -def _get_palette_bytes(im): +def _get_palette_bytes(im: Image.Image) -> bytes: """ Gets the palette for inclusion in the gif header diff --git a/src/PIL/GimpPaletteFile.py b/src/PIL/GimpPaletteFile.py index a3109ebaa..2274f1a8b 100644 --- a/src/PIL/GimpPaletteFile.py +++ b/src/PIL/GimpPaletteFile.py @@ -53,5 +53,5 @@ class GimpPaletteFile: self.palette = b"".join(self.palette) - def getpalette(self): + def getpalette(self) -> tuple[bytes, str]: return self.palette, self.rawmode diff --git a/src/PIL/GribStubImagePlugin.py b/src/PIL/GribStubImagePlugin.py index a80fe0a23..13bdfa616 100644 --- a/src/PIL/GribStubImagePlugin.py +++ b/src/PIL/GribStubImagePlugin.py @@ -37,7 +37,7 @@ class GribStubImageFile(ImageFile.StubImageFile): format = "GRIB" format_description = "GRIB" - def _open(self): + def _open(self) -> None: offset = self.fp.tell() if not _accept(self.fp.read(8)): diff --git a/src/PIL/Hdf5StubImagePlugin.py b/src/PIL/Hdf5StubImagePlugin.py index f50e6bf16..afbfd1639 100644 --- a/src/PIL/Hdf5StubImagePlugin.py +++ b/src/PIL/Hdf5StubImagePlugin.py @@ -37,7 +37,7 @@ class HDF5StubImageFile(ImageFile.StubImageFile): format = "HDF5" format_description = "HDF5" - def _open(self): + def _open(self) -> None: offset = self.fp.tell() if not _accept(self.fp.read(8)): diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index c2c950863..0a86ba883 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -252,7 +252,7 @@ class IcnsImageFile(ImageFile.ImageFile): format = "ICNS" format_description = "Mac OS icns resource" - def _open(self): + def _open(self) -> None: self.icns = IcnsFile(self.fp) self._mode = "RGBA" self.info["sizes"] = self.icns.itersizes() diff --git a/src/PIL/IcoImagePlugin.py b/src/PIL/IcoImagePlugin.py index 82b190eb8..cea093f9c 100644 --- a/src/PIL/IcoImagePlugin.py +++ b/src/PIL/IcoImagePlugin.py @@ -302,7 +302,7 @@ class IcoImageFile(ImageFile.ImageFile): format = "ICO" format_description = "Windows Icon" - def _open(self): + def _open(self) -> None: self.ico = IcoFile(self.fp) self.info["sizes"] = self.ico.sizes() self.size = self.ico.entry[0]["dim"] @@ -341,7 +341,7 @@ class IcoImageFile(ImageFile.ImageFile): self.size = im.size - def load_seek(self, pos): + def load_seek(self, pos: int) -> None: # Flag the ImageFile.Parser so that it # just does all the decode at the end. pass diff --git a/src/PIL/ImImagePlugin.py b/src/PIL/ImImagePlugin.py index 77b396387..8e949ebaf 100644 --- a/src/PIL/ImImagePlugin.py +++ b/src/PIL/ImImagePlugin.py @@ -119,7 +119,7 @@ class ImImageFile(ImageFile.ImageFile): format_description = "IFUNC Image Memory" _close_exclusive_fp_after_loading = False - def _open(self): + def _open(self) -> None: # Quick rejection: if there's not an LF among the first # 100 bytes, this is (probably) not a text header. @@ -271,14 +271,14 @@ class ImImageFile(ImageFile.ImageFile): self.tile = [("raw", (0, 0) + self.size, offs, (self.rawmode, 0, -1))] @property - def n_frames(self): + def n_frames(self) -> int: return self.info[FRAMES] @property - def is_animated(self): + def is_animated(self) -> bool: return self.info[FRAMES] > 1 - def seek(self, frame): + def seek(self, frame: int) -> None: if not self._seek_check(frame): return @@ -296,7 +296,7 @@ class ImImageFile(ImageFile.ImageFile): self.tile = [("raw", (0, 0) + self.size, offs, (self.rawmode, 0, -1))] - def tell(self): + def tell(self) -> int: return self.frame diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 236122c6b..da61ef4dd 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -258,7 +258,28 @@ def _conv_type_shape(im): return shape, m.typestr -MODES = ["1", "CMYK", "F", "HSV", "I", "L", "LAB", "P", "RGB", "RGBA", "RGBX", "YCbCr"] +MODES = [ + "1", + "CMYK", + "F", + "HSV", + "I", + "I;16", + "I;16B", + "I;16L", + "I;16N", + "L", + "LA", + "La", + "LAB", + "P", + "PA", + "RGB", + "RGBA", + "RGBa", + "RGBX", + "YCbCr", +] # raw modes that may be memory mapped. NOTE: if you change this, you # may have to modify the stride calculation in map.c too! @@ -1333,7 +1354,10 @@ class Image: self.load() return self._new(self.im.expand(xmargin, ymargin)) - def filter(self, filter): + if TYPE_CHECKING: + from . import ImageFilter + + def filter(self, filter: ImageFilter.Filter | type[ImageFilter.Filter]) -> Image: """ Filters this image using the given filter. For a list of available filters, see the :py:mod:`~PIL.ImageFilter` module. @@ -1345,7 +1369,7 @@ class Image: self.load() - if isinstance(filter, Callable): + if callable(filter): filter = filter() if not hasattr(filter, "filter"): msg = "filter argument should be ImageFilter.Filter instance or class" diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 5c179000c..1d7678443 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -34,7 +34,7 @@ from __future__ import annotations import math import numbers import struct -from typing import Sequence, cast +from typing import TYPE_CHECKING, Sequence, cast from . import Image, ImageColor from ._typing import Coords @@ -92,7 +92,10 @@ class ImageDraw: self.fontmode = "L" # aliasing is okay for other modes self.fill = False - def getfont(self): + if TYPE_CHECKING: + from . import ImageFont + + def getfont(self) -> ImageFont.FreeTypeFont | ImageFont.ImageFont: """ Get the current default font. @@ -178,6 +181,13 @@ class ImageDraw: if ink is not None and ink != fill and width != 0: self.draw.draw_ellipse(xy, ink, 0, width) + def circle( + self, xy: Sequence[float], radius: float, fill=None, outline=None, width=1 + ) -> None: + """Draw a circle given center coordinates and a radius.""" + ellipse_xy = (xy[0] - radius, xy[1] - radius, xy[0] + radius, xy[1] + radius) + self.ellipse(ellipse_xy, fill, outline, width) + def line(self, xy: Coords, fill=None, width=0, joint=None) -> None: """Draw a line, or a connected sequence of line segments.""" ink = self._getink(fill)[0] diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py index 27885e654..33467fc4f 100644 --- a/src/PIL/ImageFile.py +++ b/src/PIL/ImageFile.py @@ -311,7 +311,7 @@ class ImageFile(Image.Image): return Image.Image.load(self) - def load_prepare(self): + def load_prepare(self) -> None: # create image memory if necessary if not self.im or self.im.mode != self.mode or self.im.size != self.size: self.im = Image.core.new(self.mode, self.size) @@ -319,16 +319,16 @@ class ImageFile(Image.Image): if self.mode == "P": Image.Image.load(self) - def load_end(self): + def load_end(self) -> None: # may be overridden pass # may be defined for contained formats - # def load_seek(self, pos): + # def load_seek(self, pos: int) -> None: # pass # may be defined for blocked formats (e.g. PNG) - # def load_read(self, read_bytes): + # def load_read(self, read_bytes: int) -> bytes: # pass def _seek_check(self, frame): @@ -390,7 +390,7 @@ class Parser: offset = 0 finished = 0 - def reset(self): + def reset(self) -> None: """ (Consumer) Reset the parser. Note that you can only call this method immediately after you've created a parser; parser @@ -605,7 +605,7 @@ def _safe_read(fp, size): class PyCodecState: - def __init__(self): + def __init__(self) -> None: self.xsize = 0 self.ysize = 0 self.xoff = 0 @@ -634,7 +634,7 @@ class PyCodec: """ self.args = args - def cleanup(self): + def cleanup(self) -> None: """ Override to perform codec specific cleanup diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py index b2c4950d6..678bd29a2 100644 --- a/src/PIL/ImageFilter.py +++ b/src/PIL/ImageFilter.py @@ -16,11 +16,14 @@ # from __future__ import annotations +import abc import functools class Filter: - pass + @abc.abstractmethod + def filter(self, image): + pass class MultibandFilter(Filter): @@ -541,7 +544,7 @@ class Color3DLUT(MultibandFilter): _copy_table=False, ) - def __repr__(self): + def __repr__(self) -> str: r = [ f"{self.__class__.__name__} from {self.table.__class__.__name__}", "size={:d}x{:d}x{:d}".format(*self.size), diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 256c581df..ad5f75459 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -160,10 +160,6 @@ class ImageFont: .. versionadded:: 9.2.0 :param text: Text to render. - :param mode: Used by some graphics drivers to indicate what mode the - driver prefers; if empty, the renderer may return either - mode. Note that the mode is always a string, to simplify - C-level implementations. :return: ``(left, top, right, bottom)`` bounding box """ diff --git a/src/PIL/ImagePalette.py b/src/PIL/ImagePalette.py index 770d10025..ae5c5dec0 100644 --- a/src/PIL/ImagePalette.py +++ b/src/PIL/ImagePalette.py @@ -66,7 +66,7 @@ class ImagePalette: def colors(self, colors): self._colors = colors - def copy(self): + def copy(self) -> ImagePalette: new = ImagePalette() new.mode = self.mode @@ -77,7 +77,7 @@ class ImagePalette: return new - def getdata(self): + def getdata(self) -> tuple[str, bytes]: """ Get palette contents in format suitable for the low-level ``im.putpalette`` primitive. @@ -88,7 +88,7 @@ class ImagePalette: return self.rawmode, self.palette return self.mode, self.tobytes() - def tobytes(self): + def tobytes(self) -> bytes: """Convert palette to bytes. .. warning:: This method is experimental. diff --git a/src/PIL/ImageTk.py b/src/PIL/ImageTk.py index 10b2cc69a..6e2e7db1e 100644 --- a/src/PIL/ImageTk.py +++ b/src/PIL/ImageTk.py @@ -128,7 +128,7 @@ class PhotoImage: if image: self.paste(image) - def __del__(self): + def __del__(self) -> None: name = self.__photo.name self.__photo.name = None try: @@ -136,7 +136,7 @@ class PhotoImage: except Exception: pass # ignore internal errors - def __str__(self): + def __str__(self) -> str: """ Get the Tkinter photo image identifier. This method is automatically called by Tkinter whenever a PhotoImage object is passed to a Tkinter @@ -146,7 +146,7 @@ class PhotoImage: """ return str(self.__photo) - def width(self): + def width(self) -> int: """ Get the width of the image. @@ -154,7 +154,7 @@ class PhotoImage: """ return self.__size[0] - def height(self): + def height(self) -> int: """ Get the height of the image. @@ -219,7 +219,7 @@ class BitmapImage: kw["data"] = image.tobitmap() self.__photo = tkinter.BitmapImage(**kw) - def __del__(self): + def __del__(self) -> None: name = self.__photo.name self.__photo.name = None try: @@ -227,7 +227,7 @@ class BitmapImage: except Exception: pass # ignore internal errors - def width(self): + def width(self) -> int: """ Get the width of the image. @@ -235,7 +235,7 @@ class BitmapImage: """ return self.__size[0] - def height(self): + def height(self) -> int: """ Get the height of the image. @@ -243,7 +243,7 @@ class BitmapImage: """ return self.__size[1] - def __str__(self): + def __str__(self) -> str: """ Get the Tkinter bitmap image identifier. This method is automatically called by Tkinter whenever a BitmapImage object is passed to a Tkinter diff --git a/src/PIL/ImageWin.py b/src/PIL/ImageWin.py index f6ea138bc..77e57a415 100644 --- a/src/PIL/ImageWin.py +++ b/src/PIL/ImageWin.py @@ -204,7 +204,7 @@ class Window: def ui_handle_damage(self, x0, y0, x1, y1): pass - def ui_handle_destroy(self): + def ui_handle_destroy(self) -> None: pass def ui_handle_repair(self, dc, x0, y0, x1, y1): @@ -213,7 +213,7 @@ class Window: def ui_handle_resize(self, width, height): pass - def mainloop(self): + def mainloop(self) -> None: Image.core.eventloop() diff --git a/src/PIL/IptcImagePlugin.py b/src/PIL/IptcImagePlugin.py index 409609434..73df83bfb 100644 --- a/src/PIL/IptcImagePlugin.py +++ b/src/PIL/IptcImagePlugin.py @@ -57,7 +57,7 @@ def dump(c: Sequence[int | bytes]) -> None: """.. deprecated:: 10.2.0""" deprecate("IptcImagePlugin.dump", 12) for i in c: - print("%02x" % _i8(i), end=" ") + print(f"{_i8(i):02x}", end=" ") print() diff --git a/src/PIL/Jpeg2KImagePlugin.py b/src/PIL/Jpeg2KImagePlugin.py index 697bad221..ce6342bdb 100644 --- a/src/PIL/Jpeg2KImagePlugin.py +++ b/src/PIL/Jpeg2KImagePlugin.py @@ -63,12 +63,12 @@ class BoxReader: data = self._read_bytes(size) return struct.unpack(field_format, data) - def read_boxes(self): + def read_boxes(self) -> BoxReader: size = self.remaining_in_box data = self._read_bytes(size) return BoxReader(io.BytesIO(data), size) - def has_next_box(self): + def has_next_box(self) -> bool: if self.has_length: return self.fp.tell() + self.remaining_in_box < self.length else: @@ -215,7 +215,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile): format = "JPEG2000" format_description = "JPEG 2000 (ISO 15444)" - def _open(self): + def _open(self) -> None: sig = self.fp.read(4) if sig == b"\xff\x4f\xff\x51": self.codec = "j2k" @@ -267,7 +267,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile): ) ] - def _parse_comment(self): + def _parse_comment(self) -> None: hdr = self.fp.read(2) length = _binary.i16be(hdr) self.fp.seek(length - 2, os.SEEK_CUR) diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index 715a358a3..909911dfe 100644 --- a/src/PIL/JpegImagePlugin.py +++ b/src/PIL/JpegImagePlugin.py @@ -408,7 +408,7 @@ class JpegImageFile(ImageFile.ImageFile): msg = "no marker found" raise SyntaxError(msg) - def load_read(self, read_bytes): + def load_read(self, read_bytes: int) -> bytes: """ internal: read more image data For premature EOF and LOAD_TRUNCATED_IMAGES adds EOI marker @@ -462,7 +462,7 @@ class JpegImageFile(ImageFile.ImageFile): box = (0, 0, original_size[0] / scale, original_size[1] / scale) return self.mode, box - def load_djpeg(self): + def load_djpeg(self) -> None: # ALTERNATIVE: handle JPEGs via the IJG command line utilities f, path = tempfile.mkstemp() diff --git a/src/PIL/MicImagePlugin.py b/src/PIL/MicImagePlugin.py index 96de386a8..5aef94dfb 100644 --- a/src/PIL/MicImagePlugin.py +++ b/src/PIL/MicImagePlugin.py @@ -38,7 +38,7 @@ class MicImageFile(TiffImagePlugin.TiffImageFile): format_description = "Microsoft Image Composer" _close_exclusive_fp_after_loading = False - def _open(self): + def _open(self) -> None: # read the OLE directory and see if this is a likely # to be a Microsoft Image Composer file @@ -88,7 +88,7 @@ class MicImageFile(TiffImagePlugin.TiffImageFile): def tell(self): return self.frame - def close(self): + def close(self) -> None: self.__fp.close() self.ole.close() super().close() diff --git a/src/PIL/MpegImagePlugin.py b/src/PIL/MpegImagePlugin.py index 1565612f8..ad4d3e937 100644 --- a/src/PIL/MpegImagePlugin.py +++ b/src/PIL/MpegImagePlugin.py @@ -53,6 +53,10 @@ class BitStream: return v +def _accept(prefix: bytes) -> bool: + return prefix[:4] == b"\x00\x00\x01\xb3" + + ## # Image plugin for MPEG streams. This plugin can identify a stream, # but it cannot read it. @@ -77,7 +81,7 @@ class MpegImageFile(ImageFile.ImageFile): # -------------------------------------------------------------------- # Registry stuff -Image.register_open(MpegImageFile.format, MpegImageFile) +Image.register_open(MpegImageFile.format, MpegImageFile, _accept) Image.register_extensions(MpegImageFile.format, [".mpg", ".mpeg"]) diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index ac9820bbf..766e1290c 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -100,7 +100,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): format_description = "MPO (CIPA DC-007)" _close_exclusive_fp_after_loading = False - def _open(self): + def _open(self) -> None: self.fp.seek(0) # prep the fp in order to pass the JPEG test JpegImagePlugin.JpegImageFile._open(self) self._after_jpeg_open() @@ -124,10 +124,10 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): # for now we can only handle reading and individual frame extraction self.readonly = 1 - def load_seek(self, pos): + def load_seek(self, pos: int) -> None: self._fp.seek(pos) - def seek(self, frame): + def seek(self, frame: int) -> None: if not self._seek_check(frame): return self.fp = self._fp @@ -149,7 +149,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): self.tile = [("jpeg", (0, 0) + self.size, self.offset, self.tile[0][-1])] self.__frame = frame - def tell(self): + def tell(self) -> int: return self.__frame @staticmethod diff --git a/src/PIL/PSDraw.py b/src/PIL/PSDraw.py index 848fc2f71..49c06ce13 100644 --- a/src/PIL/PSDraw.py +++ b/src/PIL/PSDraw.py @@ -54,7 +54,7 @@ class PSDraw: self.fp.write(b"%%EndProlog\n") self.isofont = {} - def end_document(self): + def end_document(self) -> None: """Ends printing. (Write PostScript DSC footer.)""" self.fp.write(b"%%EndDocument\nrestore showpage\n%%End\n") if hasattr(self.fp, "flush"): diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py index c1ed78797..68501d625 100644 --- a/src/PIL/PdfParser.py +++ b/src/PIL/PdfParser.py @@ -87,10 +87,10 @@ class IndirectReferenceTuple(NamedTuple): class IndirectReference(IndirectReferenceTuple): - def __str__(self): + def __str__(self) -> str: return f"{self.object_id} {self.generation} R" - def __bytes__(self): + def __bytes__(self) -> bytes: return self.__str__().encode("us-ascii") def __eq__(self, other): @@ -108,7 +108,7 @@ class IndirectReference(IndirectReferenceTuple): class IndirectObjectDef(IndirectReference): - def __str__(self): + def __str__(self) -> str: return f"{self.object_id} {self.generation} obj" @@ -150,7 +150,7 @@ class XrefTable: def __contains__(self, key): return key in self.existing_entries or key in self.new_entries - def __len__(self): + def __len__(self) -> int: return len( set(self.existing_entries.keys()) | set(self.new_entries.keys()) @@ -211,7 +211,7 @@ class PdfName: else: self.name = name.encode("us-ascii") - def name_as_str(self): + def name_as_str(self) -> str: return self.name.decode("us-ascii") def __eq__(self, other): @@ -222,7 +222,7 @@ class PdfName: def __hash__(self): return hash(self.name) - def __repr__(self): + def __repr__(self) -> str: return f"{self.__class__.__name__}({repr(self.name)})" @classmethod @@ -231,7 +231,7 @@ class PdfName: allowed_chars = set(range(33, 127)) - {ord(c) for c in "#%/()<>[]{}"} - def __bytes__(self): + def __bytes__(self) -> bytes: result = bytearray(b"/") for b in self.name: if b in self.allowed_chars: @@ -242,7 +242,7 @@ class PdfName: class PdfArray(List[Any]): - def __bytes__(self): + def __bytes__(self) -> bytes: return b"[ " + b" ".join(pdf_repr(x) for x in self) + b" ]" @@ -286,7 +286,7 @@ class PdfDict(_DictBase): value = time.gmtime(calendar.timegm(value) + offset) return value - def __bytes__(self): + def __bytes__(self) -> bytes: out = bytearray(b"<<") for key, value in self.items(): if value is None: @@ -304,7 +304,7 @@ class PdfBinary: def __init__(self, data): self.data = data - def __bytes__(self): + def __bytes__(self) -> bytes: return b"<%s>" % b"".join(b"%02X" % b for b in self.data) @@ -409,28 +409,28 @@ class PdfParser: self.close() return False # do not suppress exceptions - def start_writing(self): + def start_writing(self) -> None: self.close_buf() self.seek_end() - def close_buf(self): + def close_buf(self) -> None: try: self.buf.close() except AttributeError: pass self.buf = None - def close(self): + def close(self) -> None: if self.should_close_buf: self.close_buf() if self.f is not None and self.should_close_file: self.f.close() self.f = None - def seek_end(self): + def seek_end(self) -> None: self.f.seek(0, os.SEEK_END) - def write_header(self): + def write_header(self) -> None: self.f.write(b"%PDF-1.4\n") def write_comment(self, s): @@ -450,7 +450,7 @@ class PdfParser: ) return self.root_ref - def rewrite_pages(self): + def rewrite_pages(self) -> None: pages_tree_nodes_to_delete = [] for i, page_ref in enumerate(self.orig_pages): page_info = self.cached_objects[page_ref] @@ -529,7 +529,7 @@ class PdfParser: f.write(b"endobj\n") return ref - def del_root(self): + def del_root(self) -> None: if self.root_ref is None: return del self.xref_table[self.root_ref.object_id] @@ -547,7 +547,7 @@ class PdfParser: except ValueError: # cannot mmap an empty file return b"" - def read_pdf_info(self): + def read_pdf_info(self) -> None: self.file_size_total = len(self.buf) self.file_size_this = self.file_size_total - self.start_offset self.read_trailer() @@ -823,11 +823,10 @@ class PdfParser: m = cls.re_stream_start.match(data, offset) if m: try: - stream_len = int(result[b"Length"]) - except (TypeError, KeyError, ValueError) as e: - msg = "bad or missing Length in stream dict (%r)" % result.get( - b"Length", None - ) + stream_len_str = result.get(b"Length") + stream_len = int(stream_len_str) + except (TypeError, ValueError) as e: + msg = f"bad or missing Length in stream dict ({stream_len_str})" raise PdfFormatError(msg) from e stream_data = data[m.end() : m.end() + stream_len] m = cls.re_stream_end.match(data, m.end() + stream_len) diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index ff8f5fcc9..0d5751962 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -39,6 +39,7 @@ import struct import warnings import zlib from enum import IntEnum +from typing import IO from . import Image, ImageChops, ImageFile, ImagePalette, ImageSequence from ._binary import i16be as i16 @@ -149,14 +150,15 @@ def _crc32(data, seed=0): class ChunkStream: - def __init__(self, fp): - self.fp = fp - self.queue = [] + def __init__(self, fp: IO[bytes]) -> None: + self.fp: IO[bytes] | None = fp + self.queue: list[tuple[bytes, int, int]] | None = [] - def read(self): + def read(self) -> tuple[bytes, int, int]: """Fetch a new chunk. Returns header information.""" cid = None + assert self.fp is not None if self.queue: cid, pos, length = self.queue.pop() self.fp.seek(pos) @@ -173,16 +175,17 @@ class ChunkStream: return cid, pos, length - def __enter__(self): + def __enter__(self) -> ChunkStream: return self def __exit__(self, *args): self.close() - def close(self): + def close(self) -> None: self.queue = self.fp = None - def push(self, cid, pos, length): + def push(self, cid: bytes, pos: int, length: int) -> None: + assert self.queue is not None self.queue.append((cid, pos, length)) def call(self, cid, pos, length): @@ -191,7 +194,7 @@ class ChunkStream: logger.debug("STREAM %r %s %s", cid, pos, length) return getattr(self, f"chunk_{cid.decode('ascii')}")(pos, length) - def crc(self, cid, data): + def crc(self, cid: bytes, data: bytes) -> None: """Read and verify checksum""" # Skip CRC checks for ancillary chunks if allowed to load truncated @@ -201,6 +204,7 @@ class ChunkStream: self.crc_skip(cid, data) return + assert self.fp is not None try: crc1 = _crc32(data, _crc32(cid)) crc2 = i32(self.fp.read(4)) @@ -211,12 +215,13 @@ class ChunkStream: msg = f"broken PNG file (incomplete checksum in {repr(cid)})" raise SyntaxError(msg) from e - def crc_skip(self, cid, data): + def crc_skip(self, cid: bytes, data: bytes) -> None: """Read checksum""" + assert self.fp is not None self.fp.read(4) - def verify(self, endchunk=b"IEND"): + def verify(self, endchunk: bytes = b"IEND") -> list[bytes]: # Simple approach; just calculate checksum for all remaining # blocks. Must be called directly after open. @@ -361,7 +366,7 @@ class PngStream(ChunkStream): self.text_memory = 0 - def check_text_memory(self, chunklen): + def check_text_memory(self, chunklen: int) -> None: self.text_memory += chunklen if self.text_memory > MAX_TEXT_MEMORY: msg = ( @@ -370,19 +375,19 @@ class PngStream(ChunkStream): ) raise ValueError(msg) - def save_rewind(self): + def save_rewind(self) -> None: self.rewind_state = { "info": self.im_info.copy(), "tile": self.im_tile, "seq_num": self._seq_num, } - def rewind(self): + def rewind(self) -> None: self.im_info = self.rewind_state["info"].copy() self.im_tile = self.rewind_state["tile"] self._seq_num = self.rewind_state["seq_num"] - def chunk_iCCP(self, pos, length): + def chunk_iCCP(self, pos: int, length: int) -> bytes: # ICC profile s = ImageFile._safe_read(self.fp, length) # according to PNG spec, the iCCP chunk contains: @@ -409,7 +414,7 @@ class PngStream(ChunkStream): self.im_info["icc_profile"] = icc_profile return s - def chunk_IHDR(self, pos, length): + def chunk_IHDR(self, pos: int, length: int) -> bytes: # image header s = ImageFile._safe_read(self.fp, length) if length < 13: @@ -446,14 +451,14 @@ class PngStream(ChunkStream): msg = "end of PNG image" raise EOFError(msg) - def chunk_PLTE(self, pos, length): + def chunk_PLTE(self, pos: int, length: int) -> bytes: # palette s = ImageFile._safe_read(self.fp, length) if self.im_mode == "P": self.im_palette = "RGB", s return s - def chunk_tRNS(self, pos, length): + def chunk_tRNS(self, pos: int, length: int) -> bytes: # transparency s = ImageFile._safe_read(self.fp, length) if self.im_mode == "P": @@ -473,13 +478,13 @@ class PngStream(ChunkStream): self.im_info["transparency"] = i16(s), i16(s, 2), i16(s, 4) return s - def chunk_gAMA(self, pos, length): + def chunk_gAMA(self, pos: int, length: int) -> bytes: # gamma setting s = ImageFile._safe_read(self.fp, length) self.im_info["gamma"] = i32(s) / 100000.0 return s - def chunk_cHRM(self, pos, length): + def chunk_cHRM(self, pos: int, length: int) -> bytes: # chromaticity, 8 unsigned ints, actual value is scaled by 100,000 # WP x,y, Red x,y, Green x,y Blue x,y @@ -488,7 +493,7 @@ class PngStream(ChunkStream): self.im_info["chromaticity"] = tuple(elt / 100000.0 for elt in raw_vals) return s - def chunk_sRGB(self, pos, length): + def chunk_sRGB(self, pos: int, length: int) -> bytes: # srgb rendering intent, 1 byte # 0 perceptual # 1 relative colorimetric @@ -504,7 +509,7 @@ class PngStream(ChunkStream): self.im_info["srgb"] = s[0] return s - def chunk_pHYs(self, pos, length): + def chunk_pHYs(self, pos: int, length: int) -> bytes: # pixels per unit s = ImageFile._safe_read(self.fp, length) if length < 9: @@ -521,7 +526,7 @@ class PngStream(ChunkStream): self.im_info["aspect"] = px, py return s - def chunk_tEXt(self, pos, length): + def chunk_tEXt(self, pos: int, length: int) -> bytes: # text s = ImageFile._safe_read(self.fp, length) try: @@ -540,7 +545,7 @@ class PngStream(ChunkStream): return s - def chunk_zTXt(self, pos, length): + def chunk_zTXt(self, pos: int, length: int) -> bytes: # compressed text s = ImageFile._safe_read(self.fp, length) try: @@ -574,7 +579,7 @@ class PngStream(ChunkStream): return s - def chunk_iTXt(self, pos, length): + def chunk_iTXt(self, pos: int, length: int) -> bytes: # international text r = s = ImageFile._safe_read(self.fp, length) try: @@ -614,13 +619,13 @@ class PngStream(ChunkStream): return s - def chunk_eXIf(self, pos, length): + def chunk_eXIf(self, pos: int, length: int) -> bytes: s = ImageFile._safe_read(self.fp, length) self.im_info["exif"] = b"Exif\x00\x00" + s return s # APNG chunks - def chunk_acTL(self, pos, length): + def chunk_acTL(self, pos: int, length: int) -> bytes: s = ImageFile._safe_read(self.fp, length) if length < 8: if ImageFile.LOAD_TRUNCATED_IMAGES: @@ -640,7 +645,7 @@ class PngStream(ChunkStream): self.im_custom_mimetype = "image/apng" return s - def chunk_fcTL(self, pos, length): + def chunk_fcTL(self, pos: int, length: int) -> bytes: s = ImageFile._safe_read(self.fp, length) if length < 26: if ImageFile.LOAD_TRUNCATED_IMAGES: @@ -669,7 +674,7 @@ class PngStream(ChunkStream): self.im_info["blend"] = s[25] return s - def chunk_fdAT(self, pos, length): + def chunk_fdAT(self, pos: int, length: int) -> bytes: if length < 4: if ImageFile.LOAD_TRUNCATED_IMAGES: s = ImageFile._safe_read(self.fp, length) @@ -701,7 +706,7 @@ class PngImageFile(ImageFile.ImageFile): format = "PNG" format_description = "Portable network graphics" - def _open(self): + def _open(self) -> None: if not _accept(self.fp.read(8)): msg = "not a PNG file" raise SyntaxError(msg) @@ -711,8 +716,8 @@ class PngImageFile(ImageFile.ImageFile): # # Parse headers up to the first IDAT or fDAT chunk - self.private_chunks = [] - self.png = PngStream(self.fp) + self.private_chunks: list[tuple[bytes, bytes] | tuple[bytes, bytes, bool]] = [] + self.png: PngStream | None = PngStream(self.fp) while True: # @@ -793,6 +798,7 @@ class PngImageFile(ImageFile.ImageFile): # back up to beginning of IDAT block self.fp.seek(self.tile[0][2] - 8) + assert self.png is not None self.png.verify() self.png.close() @@ -800,7 +806,7 @@ class PngImageFile(ImageFile.ImageFile): self.fp.close() self.fp = None - def seek(self, frame): + def seek(self, frame: int) -> None: if not self._seek_check(frame): return if frame < self.__frame: @@ -909,10 +915,10 @@ class PngImageFile(ImageFile.ImageFile): else: self.dispose = None - def tell(self): + def tell(self) -> int: return self.__frame - def load_prepare(self): + def load_prepare(self) -> None: """internal: prepare to read PNG file""" if self.info.get("interlace"): @@ -921,9 +927,10 @@ class PngImageFile(ImageFile.ImageFile): self.__idat = self.__prepare_idat # used by load_read() ImageFile.ImageFile.load_prepare(self) - def load_read(self, read_bytes): + def load_read(self, read_bytes: int) -> bytes: """internal: read more image data""" + assert self.png is not None while self.__idat == 0: # end of chunk, skip forward to next one @@ -954,8 +961,9 @@ class PngImageFile(ImageFile.ImageFile): return self.fp.read(read_bytes) - def load_end(self): + def load_end(self) -> None: """internal: finished reading image data""" + assert self.png is not None if self.__idat != 0: self.fp.read(self.__idat) while True: @@ -1042,22 +1050,22 @@ class PngImageFile(ImageFile.ImageFile): # PNG writer _OUTMODES = { - # supported PIL modes, and corresponding rawmodes/bits/color combinations - "1": ("1", b"\x01\x00"), - "L;1": ("L;1", b"\x01\x00"), - "L;2": ("L;2", b"\x02\x00"), - "L;4": ("L;4", b"\x04\x00"), - "L": ("L", b"\x08\x00"), - "LA": ("LA", b"\x08\x04"), - "I": ("I;16B", b"\x10\x00"), - "I;16": ("I;16B", b"\x10\x00"), - "I;16B": ("I;16B", b"\x10\x00"), - "P;1": ("P;1", b"\x01\x03"), - "P;2": ("P;2", b"\x02\x03"), - "P;4": ("P;4", b"\x04\x03"), - "P": ("P", b"\x08\x03"), - "RGB": ("RGB", b"\x08\x02"), - "RGBA": ("RGBA", b"\x08\x06"), + # supported PIL modes, and corresponding rawmode, bit depth and color type + "1": ("1", b"\x01", b"\x00"), + "L;1": ("L;1", b"\x01", b"\x00"), + "L;2": ("L;2", b"\x02", b"\x00"), + "L;4": ("L;4", b"\x04", b"\x00"), + "L": ("L", b"\x08", b"\x00"), + "LA": ("LA", b"\x08", b"\x04"), + "I": ("I;16B", b"\x10", b"\x00"), + "I;16": ("I;16B", b"\x10", b"\x00"), + "I;16B": ("I;16B", b"\x10", b"\x00"), + "P;1": ("P;1", b"\x01", b"\x03"), + "P;2": ("P;2", b"\x02", b"\x03"), + "P;4": ("P;4", b"\x04", b"\x03"), + "P": ("P", b"\x08", b"\x03"), + "RGB": ("RGB", b"\x08", b"\x02"), + "RGBA": ("RGBA", b"\x08", b"\x06"), } @@ -1079,7 +1087,7 @@ class _idat: self.fp = fp self.chunk = chunk - def write(self, data): + def write(self, data: bytes) -> None: self.chunk(self.fp, b"IDAT", data) @@ -1091,7 +1099,7 @@ class _fdat: self.chunk = chunk self.seq_num = seq_num - def write(self, data): + def write(self, data: bytes) -> None: self.chunk(self.fp, b"fdAT", o32(self.seq_num), data) self.seq_num += 1 @@ -1286,7 +1294,7 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False): # get the corresponding PNG mode try: - rawmode, mode = _OUTMODES[mode] + rawmode, bit_depth, color_type = _OUTMODES[mode] except KeyError as e: msg = f"cannot write mode {mode} as PNG" raise OSError(msg) from e @@ -1301,7 +1309,8 @@ def _save(im, fp, filename, chunk=putchunk, save_all=False): b"IHDR", o32(size[0]), # 0: size o32(size[1]), - mode, # 8: depth/type + bit_depth, + color_type, b"\0", # 10: compression b"\0", # 11: filter category b"\0", # 12: interlace flag @@ -1436,10 +1445,10 @@ def getchunks(im, **params): class collector: data = [] - def write(self, data): + def write(self, data: bytes) -> None: pass - def append(self, chunk): + def append(self, chunk: bytes) -> None: self.data.append(chunk) def append(fp, cid, *data): diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py index b15918313..86c1a6763 100644 --- a/src/PIL/PsdImagePlugin.py +++ b/src/PIL/PsdImagePlugin.py @@ -57,7 +57,7 @@ class PsdImageFile(ImageFile.ImageFile): format_description = "Adobe Photoshop" _close_exclusive_fp_after_loading = False - def _open(self): + def _open(self) -> None: read = self.fp.read # @@ -141,23 +141,22 @@ class PsdImageFile(ImageFile.ImageFile): self.frame = 1 self._min_frame = 1 - def seek(self, layer): + def seek(self, layer: int) -> None: if not self._seek_check(layer): return # seek to given layer (1..max) try: - name, mode, bbox, tile = self.layers[layer - 1] + _, mode, _, tile = self.layers[layer - 1] self._mode = mode self.tile = tile self.frame = layer self.fp = self._fp - return name, bbox except IndexError as e: msg = "no such layer" raise EOFError(msg) from e - def tell(self): + def tell(self) -> int: # return layer number (0=image, 1..max=layers) return self.frame diff --git a/src/PIL/QoiImagePlugin.py b/src/PIL/QoiImagePlugin.py index 2875b8d75..cea8b60da 100644 --- a/src/PIL/QoiImagePlugin.py +++ b/src/PIL/QoiImagePlugin.py @@ -21,7 +21,7 @@ class QoiImageFile(ImageFile.ImageFile): format = "QOI" format_description = "Quite OK Image" - def _open(self): + def _open(self) -> None: if not _accept(self.fp.read(4)): msg = "not a QOI file" raise SyntaxError(msg) diff --git a/src/PIL/SpiderImagePlugin.py b/src/PIL/SpiderImagePlugin.py index 69b27dc9d..5b8ad47f0 100644 --- a/src/PIL/SpiderImagePlugin.py +++ b/src/PIL/SpiderImagePlugin.py @@ -37,6 +37,7 @@ from __future__ import annotations import os import struct import sys +from typing import TYPE_CHECKING from . import Image, ImageFile @@ -97,7 +98,7 @@ class SpiderImageFile(ImageFile.ImageFile): format_description = "Spider 2D image" _close_exclusive_fp_after_loading = False - def _open(self): + def _open(self) -> None: # check header n = 27 * 4 # read 27 float values f = self.fp.read(n) @@ -157,21 +158,21 @@ class SpiderImageFile(ImageFile.ImageFile): self._fp = self.fp # FIXME: hack @property - def n_frames(self): + def n_frames(self) -> int: return self._nimages @property - def is_animated(self): + def is_animated(self) -> bool: return self._nimages > 1 # 1st image index is zero (although SPIDER imgnumber starts at 1) - def tell(self): + def tell(self) -> int: if self.imgnumber < 1: return 0 else: return self.imgnumber - 1 - def seek(self, frame): + def seek(self, frame: int) -> None: if self.istack == 0: msg = "attempt to seek in a non-stack file" raise EOFError(msg) @@ -191,8 +192,11 @@ class SpiderImageFile(ImageFile.ImageFile): b = -m * minimum return self.point(lambda i, m=m, b=b: i * m + b).convert("L") + if TYPE_CHECKING: + from . import ImageTk + # returns a ImageTk.PhotoImage object, after rescaling to 0..255 - def tkPhotoImage(self): + def tkPhotoImage(self) -> ImageTk.PhotoImage: from . import ImageTk return ImageTk.PhotoImage(self.convert2byte(), palette=256) diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 13069ce75..54faa59c5 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -381,7 +381,7 @@ class IFDRational(Rational): f = self._val.limit_denominator(max_denominator) return f.numerator, f.denominator - def __repr__(self): + def __repr__(self) -> str: return str(float(self._val)) def __hash__(self): @@ -603,7 +603,7 @@ class ImageFileDirectory_v2(_IFDv2Base): self._next = None self._offset = None - def __str__(self): + def __str__(self) -> str: return str(dict(self)) def named(self): @@ -617,7 +617,7 @@ class ImageFileDirectory_v2(_IFDv2Base): for code, value in self.items() } - def __len__(self): + def __len__(self) -> int: return len(set(self._tagdata) | set(self._tags_v2)) def __getitem__(self, tag): @@ -1041,7 +1041,7 @@ class ImageFileDirectory_v1(ImageFileDirectory_v2): ifd.next = original.next # an indicator for multipage tiffs return ifd - def to_v2(self): + def to_v2(self) -> ImageFileDirectory_v2: """Returns an :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v2` instance with the same data as is contained in the original @@ -1061,7 +1061,7 @@ class ImageFileDirectory_v1(ImageFileDirectory_v2): def __contains__(self, tag): return tag in self._tags_v1 or tag in self._tagdata - def __len__(self): + def __len__(self) -> int: return len(set(self._tagdata) | set(self._tags_v1)) def __iter__(self): @@ -1143,7 +1143,7 @@ class TiffImageFile(ImageFile.ImageFile): self.seek(current) return self._n_frames - def seek(self, frame): + def seek(self, frame: int) -> None: """Select a given frame as current image""" if not self._seek_check(frame): return @@ -1154,7 +1154,7 @@ class TiffImageFile(ImageFile.ImageFile): Image._decompression_bomb_check(self.size) self.im = Image.core.new(self.mode, self.size) - def _seek(self, frame): + def _seek(self, frame: int) -> None: self.fp = self._fp # reset buffered io handle in case fp @@ -1198,7 +1198,7 @@ class TiffImageFile(ImageFile.ImageFile): self.__frame = frame self._setup() - def tell(self): + def tell(self) -> int: """Return the current frame number""" return self.__frame @@ -1237,7 +1237,7 @@ class TiffImageFile(ImageFile.ImageFile): return self._load_libtiff() return super().load() - def load_end(self): + def load_end(self) -> None: # allow closing if we're on the first frame, there's no next # This is the ImageFile.load path only, libtiff specific below. if not self.is_animated: @@ -1942,7 +1942,7 @@ class AppendingTiffWriter: self.beginning = self.f.tell() self.setup() - def setup(self): + def setup(self) -> None: # Reset everything. self.f.seek(self.beginning, os.SEEK_SET) @@ -1967,7 +1967,7 @@ class AppendingTiffWriter: self.skipIFDs() self.goToEnd() - def finalize(self): + def finalize(self) -> None: if self.isFirst: return @@ -1990,7 +1990,7 @@ class AppendingTiffWriter: self.f.seek(ifd_offset) self.fixIFD() - def newFrame(self): + def newFrame(self) -> None: # Call this to finish a frame. self.finalize() self.setup() @@ -2003,7 +2003,7 @@ class AppendingTiffWriter: self.close() return False - def tell(self): + def tell(self) -> int: return self.f.tell() - self.offsetOfNewPage def seek(self, offset, whence=io.SEEK_SET): @@ -2013,7 +2013,7 @@ class AppendingTiffWriter: self.f.seek(offset, whence) return self.tell() - def goToEnd(self): + def goToEnd(self) -> None: self.f.seek(0, os.SEEK_END) pos = self.f.tell() @@ -2029,7 +2029,7 @@ class AppendingTiffWriter: self.shortFmt = f"{self.endian}H" self.tagFormat = f"{self.endian}HHL" - def skipIFDs(self): + def skipIFDs(self) -> None: while True: ifd_offset = self.readLong() if ifd_offset == 0: @@ -2084,11 +2084,11 @@ class AppendingTiffWriter: msg = f"wrote only {bytes_written} bytes but wanted 4" raise RuntimeError(msg) - def close(self): + def close(self) -> None: self.finalize() self.f.close() - def fixIFD(self): + def fixIFD(self) -> None: num_tags = self.readShort() for i in range(num_tags): diff --git a/src/PIL/WalImageFile.py b/src/PIL/WalImageFile.py index c5bf3e04c..fbd7be6ed 100644 --- a/src/PIL/WalImageFile.py +++ b/src/PIL/WalImageFile.py @@ -32,7 +32,7 @@ class WalImageFile(ImageFile.ImageFile): format = "WAL" format_description = "Quake2 Texture" - def _open(self): + def _open(self) -> None: self._mode = "P" # read header fields diff --git a/src/PIL/WebPImagePlugin.py b/src/PIL/WebPImagePlugin.py index 9c8d53336..cae124e9f 100644 --- a/src/PIL/WebPImagePlugin.py +++ b/src/PIL/WebPImagePlugin.py @@ -43,7 +43,7 @@ class WebPImageFile(ImageFile.ImageFile): __loaded = 0 __logical_frame = 0 - def _open(self): + def _open(self) -> None: if not _webp.HAVE_WEBPANIM: # Legacy mode data, width, height, self._mode, icc_profile, exif = _webp.WebPDecode( @@ -109,7 +109,7 @@ class WebPImageFile(ImageFile.ImageFile): """ return self._getxmp(self.info["xmp"]) if "xmp" in self.info else {} - def seek(self, frame): + def seek(self, frame: int) -> None: if not self._seek_check(frame): return @@ -144,7 +144,7 @@ class WebPImageFile(ImageFile.ImageFile): timestamp -= duration return data, timestamp, duration - def _seek(self, frame): + def _seek(self, frame: int) -> None: if self.__physical_frame == frame: return # Nothing to do if frame < self.__physical_frame: @@ -171,10 +171,10 @@ class WebPImageFile(ImageFile.ImageFile): return super().load() - def load_seek(self, pos): + def load_seek(self, pos: int) -> None: pass - def tell(self): + def tell(self) -> int: if not _webp.HAVE_WEBPANIM: return super().tell() diff --git a/src/PIL/WmfImagePlugin.py b/src/PIL/WmfImagePlugin.py index 7f045ec7d..b0328657b 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -79,7 +79,7 @@ class WmfStubImageFile(ImageFile.StubImageFile): format = "WMF" format_description = "Windows Metafile" - def _open(self): + def _open(self) -> None: self._inch = None # check placable header diff --git a/src/PIL/XpmImagePlugin.py b/src/PIL/XpmImagePlugin.py index a638547af..8d56331e6 100644 --- a/src/PIL/XpmImagePlugin.py +++ b/src/PIL/XpmImagePlugin.py @@ -36,7 +36,7 @@ class XpmImageFile(ImageFile.ImageFile): format = "XPM" format_description = "X11 Pixel Map" - def _open(self): + def _open(self) -> None: if not _accept(self.fp.read(9)): msg = "not an XPM file" raise SyntaxError(msg) @@ -103,16 +103,13 @@ class XpmImageFile(ImageFile.ImageFile): self.tile = [("raw", (0, 0) + self.size, self.fp.tell(), ("P", 0, 1))] - def load_read(self, read_bytes): + def load_read(self, read_bytes: int) -> bytes: # # load all image data in one chunk xsize, ysize = self.size - s = [None] * ysize - - for i in range(ysize): - s[i] = self.fp.readline()[1 : xsize + 1].ljust(xsize) + s = [self.fp.readline()[1 : xsize + 1].ljust(xsize) for i in range(ysize)] return b"".join(s) diff --git a/src/PIL/features.py b/src/PIL/features.py index 95c6c84cc..16c749f14 100644 --- a/src/PIL/features.py +++ b/src/PIL/features.py @@ -18,7 +18,7 @@ modules = { } -def check_module(feature): +def check_module(feature: str) -> bool: """ Checks if a module is available. @@ -42,7 +42,7 @@ def check_module(feature): return False -def version_module(feature): +def version_module(feature: str) -> str | None: """ :param feature: The module to check for. :returns: @@ -54,13 +54,10 @@ def version_module(feature): module, ver = modules[feature] - if ver is None: - return None - return getattr(__import__(module, fromlist=[ver]), ver) -def get_supported_modules(): +def get_supported_modules() -> list[str]: """ :returns: A list of all supported modules. """ @@ -75,7 +72,7 @@ codecs = { } -def check_codec(feature): +def check_codec(feature: str) -> bool: """ Checks if a codec is available. @@ -92,7 +89,7 @@ def check_codec(feature): return f"{codec}_encoder" in dir(Image.core) -def version_codec(feature): +def version_codec(feature: str) -> str | None: """ :param feature: The codec to check for. :returns: @@ -113,7 +110,7 @@ def version_codec(feature): return version -def get_supported_codecs(): +def get_supported_codecs() -> list[str]: """ :returns: A list of all supported codecs. """ @@ -133,7 +130,7 @@ features = { } -def check_feature(feature): +def check_feature(feature: str) -> bool | None: """ Checks if a feature is available. @@ -157,7 +154,7 @@ def check_feature(feature): return None -def version_feature(feature): +def version_feature(feature: str) -> str | None: """ :param feature: The feature to check for. :returns: The version number as a string, or ``None`` if not available. @@ -174,14 +171,14 @@ def version_feature(feature): return getattr(__import__(module, fromlist=[ver]), ver) -def get_supported_features(): +def get_supported_features() -> list[str]: """ :returns: A list of all supported features. """ return [f for f in features if check_feature(f)] -def check(feature): +def check(feature: str) -> bool | None: """ :param feature: A module, codec, or feature name. :returns: @@ -199,7 +196,7 @@ def check(feature): return False -def version(feature): +def version(feature: str) -> str | None: """ :param feature: The module, codec, or feature to check for. @@ -215,7 +212,7 @@ def version(feature): return None -def get_supported(): +def get_supported() -> list[str]: """ :returns: A list of all supported modules, features, and codecs. """ diff --git a/src/Tk/tkImaging.c b/src/Tk/tkImaging.c index bd3cafe95..ef1c00a94 100644 --- a/src/Tk/tkImaging.c +++ b/src/Tk/tkImaging.c @@ -128,14 +128,7 @@ PyImagingPhotoPut( block.pixelPtr = (unsigned char *)im->block; TK_PHOTO_PUT_BLOCK( - interp, - photo, - &block, - 0, - 0, - block.width, - block.height, - TK_PHOTO_COMPOSITE_SET); + interp, photo, &block, 0, 0, block.width, block.height, TK_PHOTO_COMPOSITE_SET); return TCL_OK; } @@ -287,7 +280,7 @@ load_tkinter_funcs(void) { * Return 0 for success, non-zero for failure. */ - HMODULE* hMods = NULL; + HMODULE *hMods = NULL; HANDLE hProcess; DWORD cbNeeded; unsigned int i; @@ -313,7 +306,7 @@ load_tkinter_funcs(void) { #endif return 1; } - if (!(hMods = (HMODULE*) malloc(cbNeeded))) { + if (!(hMods = (HMODULE *)malloc(cbNeeded))) { PyErr_NoMemory(); return 1; } @@ -345,7 +338,7 @@ load_tkinter_funcs(void) { } else if (found_tk == 0) { PyErr_SetString(PyExc_RuntimeError, "Could not find Tk routines"); } - return (int) ((found_tcl != 1) || (found_tk != 1)); + return (int)((found_tcl != 1) || (found_tk != 1)); } #else /* not Windows */ @@ -400,8 +393,8 @@ _func_loader(void *lib) { return 1; } return ( - (TK_PHOTO_PUT_BLOCK = - (Tk_PhotoPutBlock_t)_dfunc(lib, "Tk_PhotoPutBlock")) == NULL); + (TK_PHOTO_PUT_BLOCK = (Tk_PhotoPutBlock_t)_dfunc(lib, "Tk_PhotoPutBlock")) == + NULL); } int diff --git a/src/_imaging.c b/src/_imaging.c index 9b521f552..c565c21bb 100644 --- a/src/_imaging.c +++ b/src/_imaging.c @@ -110,7 +110,7 @@ #define B16(p, i) ((((int)p[(i)]) << 8) + p[(i) + 1]) #define L16(p, i) ((((int)p[(i) + 1]) << 8) + p[(i)]) -#define S16(v) ((v) < 32768 ? (v) : ((v)-65536)) +#define S16(v) ((v) < 32768 ? (v) : ((v) - 65536)) /* -------------------------------------------------------------------- */ /* OBJECT ADMINISTRATION */ @@ -533,7 +533,9 @@ getink(PyObject *color, Imaging im, char *ink) { /* unsigned integer, single layer */ if (rIsInt != 1) { if (tupleSize != 1) { - PyErr_SetString(PyExc_TypeError, "color must be int or single-element tuple"); + PyErr_SetString( + PyExc_TypeError, + "color must be int or single-element tuple"); return NULL; } else if (!PyArg_ParseTuple(color, "L", &r)) { return NULL; @@ -552,7 +554,9 @@ getink(PyObject *color, Imaging im, char *ink) { a = 255; if (im->bands == 2) { if (tupleSize != 1 && tupleSize != 2) { - PyErr_SetString(PyExc_TypeError, "color must be int, or tuple of one or two elements"); + PyErr_SetString( + PyExc_TypeError, + "color must be int, or tuple of one or two elements"); return NULL; } else if (!PyArg_ParseTuple(color, "L|i", &r, &a)) { return NULL; @@ -560,7 +564,10 @@ getink(PyObject *color, Imaging im, char *ink) { g = b = r; } else { if (tupleSize != 3 && tupleSize != 4) { - PyErr_SetString(PyExc_TypeError, "color must be int, or tuple of one, three or four elements"); + PyErr_SetString( + PyExc_TypeError, + "color must be int, or tuple of one, three or four " + "elements"); return NULL; } else if (!PyArg_ParseTuple(color, "Lii|i", &r, &g, &b, &a)) { return NULL; @@ -599,7 +606,9 @@ getink(PyObject *color, Imaging im, char *ink) { g = (UINT8)(r >> 8); r = (UINT8)r; } else if (tupleSize != 3) { - PyErr_SetString(PyExc_TypeError, "color must be int, or tuple of one or three elements"); + PyErr_SetString( + PyExc_TypeError, + "color must be int, or tuple of one or three elements"); return NULL; } else if (!PyArg_ParseTuple(color, "iiL", &b, &g, &r)) { return NULL; @@ -1537,14 +1546,14 @@ _putdata(ImagingObject *self, PyObject *args) { return NULL; } -#define set_value_to_item(seq, i) \ -op = PySequence_Fast_GET_ITEM(seq, i); \ -if (PySequence_Check(op)) { \ - PyErr_SetString(PyExc_TypeError, "sequence must be flattened"); \ - return NULL; \ -} else { \ - value = PyFloat_AsDouble(op); \ -} +#define set_value_to_item(seq, i) \ + op = PySequence_Fast_GET_ITEM(seq, i); \ + if (PySequence_Check(op)) { \ + PyErr_SetString(PyExc_TypeError, "sequence must be flattened"); \ + return NULL; \ + } else { \ + value = PyFloat_AsDouble(op); \ + } if (image->image8) { if (PyBytes_Check(data)) { unsigned char *p; @@ -1596,8 +1605,10 @@ if (PySequence_Check(op)) { \ value = value * scale + offset; } if (image->type == IMAGING_TYPE_SPECIAL) { - image->image8[y][x * 2 + (bigendian ? 1 : 0)] = CLIP8((int)value % 256); - image->image8[y][x * 2 + (bigendian ? 0 : 1)] = CLIP8((int)value >> 8); + image->image8[y][x * 2 + (bigendian ? 1 : 0)] = + CLIP8((int)value % 256); + image->image8[y][x * 2 + (bigendian ? 0 : 1)] = + CLIP8((int)value >> 8); } else { image->image8[y][x] = (UINT8)CLIP8(value); } @@ -1639,8 +1650,7 @@ if (PySequence_Check(op)) { \ for (i = x = y = 0; i < n; i++) { double value; set_value_to_item(seq, i); - IMAGING_PIXEL_INT32(image, x, y) = - (INT32)(value * scale + offset); + IMAGING_PIXEL_INT32(image, x, y) = (INT32)(value * scale + offset); if (++x >= (int)image->xsize) { x = 0, y++; } @@ -2785,8 +2795,8 @@ _font_getmask(ImagingFontObject *self, PyObject *args) { glyph = &self->glyphs[text[i]]; if (i == 0 || text[i] != text[i - 1]) { ImagingDelete(bitmap); - bitmap = - ImagingCrop(self->bitmap, glyph->sx0, glyph->sy0, glyph->sx1, glyph->sy1); + bitmap = ImagingCrop( + self->bitmap, glyph->sx0, glyph->sy0, glyph->sx1, glyph->sy1); if (!bitmap) { goto failed; } @@ -3315,7 +3325,8 @@ _draw_polygon(ImagingDrawObject *self, PyObject *args) { free(xy); - if (ImagingDrawPolygon(self->image->image, n, ixy, &ink, fill, width, self->blend) < 0) { + if (ImagingDrawPolygon(self->image->image, n, ixy, &ink, fill, width, self->blend) < + 0) { free(ixy); return NULL; } @@ -4411,7 +4422,8 @@ setup_module(PyObject *m) { PyModule_AddObject(m, "HAVE_XCB", have_xcb); PyObject *pillow_version = PyUnicode_FromString(version); - PyDict_SetItemString(d, "PILLOW_VERSION", pillow_version ? pillow_version : Py_None); + PyDict_SetItemString( + d, "PILLOW_VERSION", pillow_version ? pillow_version : Py_None); Py_XDECREF(pillow_version); return 0; diff --git a/src/_imagingcms.c b/src/_imagingcms.c index 63d78f84d..2b9612db7 100644 --- a/src/_imagingcms.c +++ b/src/_imagingcms.c @@ -213,11 +213,8 @@ cms_transform_dealloc(CmsTransformObject *self) { static cmsUInt32Number findLCMStype(char *PILmode) { - if ( - strcmp(PILmode, "RGB") == 0 || - strcmp(PILmode, "RGBA") == 0 || - strcmp(PILmode, "RGBX") == 0 - ) { + if (strcmp(PILmode, "RGB") == 0 || strcmp(PILmode, "RGBA") == 0 || + strcmp(PILmode, "RGBX") == 0) { return TYPE_RGBA_8; } if (strcmp(PILmode, "RGBA;16B") == 0) { @@ -232,10 +229,7 @@ findLCMStype(char *PILmode) { if (strcmp(PILmode, "L;16B") == 0) { return TYPE_GRAY_16_SE; } - if ( - strcmp(PILmode, "YCCA") == 0 || - strcmp(PILmode, "YCC") == 0 - ) { + if (strcmp(PILmode, "YCCA") == 0 || strcmp(PILmode, "YCC") == 0) { return TYPE_YCbCr_8; } if (strcmp(PILmode, "LAB") == 0) { @@ -391,7 +385,7 @@ _buildTransform( iRenderingIntent, cmsFLAGS); - Py_END_ALLOW_THREADS + Py_END_ALLOW_THREADS; if (!hTransform) { PyErr_SetString(PyExc_ValueError, "cannot build transform"); @@ -425,7 +419,7 @@ _buildProofTransform( iProofIntent, cmsFLAGS); - Py_END_ALLOW_THREADS + Py_END_ALLOW_THREADS; if (!hTransform) { PyErr_SetString(PyExc_ValueError, "cannot build proof transform"); @@ -622,7 +616,7 @@ cms_profile_is_intent_supported(CmsProfileObject *self, PyObject *args) { static PyObject * cms_get_display_profile_win32(PyObject *self, PyObject *args) { char filename[MAX_PATH]; - cmsUInt32Number filename_size; + DWORD filename_size; BOOL ok; HANDLE handle = 0; diff --git a/src/_imagingft.c b/src/_imagingft.c index 6e24fcf95..e83ddfec1 100644 --- a/src/_imagingft.c +++ b/src/_imagingft.c @@ -47,17 +47,17 @@ ; #ifdef HAVE_RAQM -# ifdef HAVE_RAQM_SYSTEM -# include -# else -# include "thirdparty/raqm/raqm.h" -# ifdef HAVE_FRIBIDI_SYSTEM -# include -# else -# include "thirdparty/fribidi-shim/fribidi.h" -# include -# endif -# endif +#ifdef HAVE_RAQM_SYSTEM +#include +#else +#include "thirdparty/raqm/raqm.h" +#ifdef HAVE_FRIBIDI_SYSTEM +#include +#else +#include "thirdparty/fribidi-shim/fribidi.h" +#include +#endif +#endif #endif static int have_raqm = 0; @@ -490,8 +490,7 @@ text_layout( size_t count; #ifdef HAVE_RAQM if (have_raqm && self->layout_engine == LAYOUT_RAQM) { - count = text_layout_raqm( - string, self, dir, features, lang, glyph_info); + count = text_layout_raqm(string, self, dir, features, lang, glyph_info); } else #endif { @@ -550,7 +549,17 @@ font_getlength(FontObject *self, PyObject *args) { } static int -bounding_box_and_anchors(FT_Face face, const char *anchor, int horizontal_dir, GlyphInfo *glyph_info, size_t count, int load_flags, int *width, int *height, int *x_offset, int *y_offset) { +bounding_box_and_anchors( + FT_Face face, + const char *anchor, + int horizontal_dir, + GlyphInfo *glyph_info, + size_t count, + int load_flags, + int *width, + int *height, + int *x_offset, + int *y_offset) { int position; /* pen position along primary axis, in 26.6 precision */ int advanced; /* pen position along primary axis, in pixels */ int px, py; /* position of current glyph, in pixels */ @@ -558,8 +567,8 @@ bounding_box_and_anchors(FT_Face face, const char *anchor, int horizontal_dir, G int x_anchor, y_anchor; /* offset of point drawn at (0, 0), in pixels */ int error; FT_Glyph glyph; - FT_BBox bbox; /* glyph bounding box */ - size_t i; /* glyph_info index */ + FT_BBox bbox; /* glyph bounding box */ + size_t i; /* glyph_info index */ /* * text bounds are given by: * - bounding boxes of individual glyphs @@ -654,8 +663,7 @@ bounding_box_and_anchors(FT_Face face, const char *anchor, int horizontal_dir, G break; case 'm': // middle (ascender + descender) / 2 y_anchor = PIXEL( - (face->size->metrics.ascender + - face->size->metrics.descender) / + (face->size->metrics.ascender + face->size->metrics.descender) / 2); break; case 's': // horizontal baseline @@ -719,7 +727,7 @@ bad_anchor: static PyObject * font_getsize(FontObject *self, PyObject *args) { int width, height, x_offset, y_offset; - int load_flags; /* FreeType load_flags parameter */ + int load_flags; /* FreeType load_flags parameter */ int error; GlyphInfo *glyph_info = NULL; /* computed text layout */ size_t count; /* glyph_info length */ @@ -758,7 +766,17 @@ font_getsize(FontObject *self, PyObject *args) { load_flags |= FT_LOAD_COLOR; } - error = bounding_box_and_anchors(self->face, anchor, horizontal_dir, glyph_info, count, load_flags, &width, &height, &x_offset, &y_offset); + error = bounding_box_and_anchors( + self->face, + anchor, + horizontal_dir, + glyph_info, + count, + load_flags, + &width, + &height, + &x_offset, + &y_offset); if (glyph_info) { PyMem_Free(glyph_info); glyph_info = NULL; @@ -767,12 +785,7 @@ font_getsize(FontObject *self, PyObject *args) { return NULL; } - return Py_BuildValue( - "(ii)(ii)", - width, - height, - x_offset, - y_offset); + return Py_BuildValue("(ii)(ii)", width, height, x_offset, y_offset); } static PyObject * @@ -869,7 +882,17 @@ font_render(FontObject *self, PyObject *args) { horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1; - error = bounding_box_and_anchors(self->face, anchor, horizontal_dir, glyph_info, count, load_flags, &width, &height, &x_offset, &y_offset); + error = bounding_box_and_anchors( + self->face, + anchor, + horizontal_dir, + glyph_info, + count, + load_flags, + &width, + &height, + &x_offset, + &y_offset); if (error) { PyMem_Del(glyph_info); return NULL; @@ -1066,17 +1089,26 @@ font_render(FontObject *self, PyObject *args) { /* paste only if source has data */ if (src_alpha > 0) { /* unpremultiply BGRa */ - int src_red = CLIP8((255 * (int)source[k * 4 + 2]) / src_alpha); - int src_green = CLIP8((255 * (int)source[k * 4 + 1]) / src_alpha); - int src_blue = CLIP8((255 * (int)source[k * 4 + 0]) / src_alpha); + int src_red = + CLIP8((255 * (int)source[k * 4 + 2]) / src_alpha); + int src_green = + CLIP8((255 * (int)source[k * 4 + 1]) / src_alpha); + int src_blue = + CLIP8((255 * (int)source[k * 4 + 0]) / src_alpha); /* blend required if target has data */ if (target[k * 4 + 3] > 0) { /* blend RGBA colors */ - target[k * 4 + 0] = BLEND(src_alpha, target[k * 4 + 0], src_red, tmp); - target[k * 4 + 1] = BLEND(src_alpha, target[k * 4 + 1], src_green, tmp); - target[k * 4 + 2] = BLEND(src_alpha, target[k * 4 + 2], src_blue, tmp); - target[k * 4 + 3] = CLIP8(src_alpha + MULDIV255(target[k * 4 + 3], (255 - src_alpha), tmp)); + target[k * 4 + 0] = + BLEND(src_alpha, target[k * 4 + 0], src_red, tmp); + target[k * 4 + 1] = + BLEND(src_alpha, target[k * 4 + 1], src_green, tmp); + target[k * 4 + 2] = + BLEND(src_alpha, target[k * 4 + 2], src_blue, tmp); + target[k * 4 + 3] = CLIP8( + src_alpha + + MULDIV255( + target[k * 4 + 3], (255 - src_alpha), tmp)); } else { /* paste unpremultiplied RGBA values */ target[k * 4 + 0] = src_red; @@ -1093,10 +1125,16 @@ font_render(FontObject *self, PyObject *args) { unsigned int src_alpha = source[k] * convert_scale; if (src_alpha > 0) { if (target[k * 4 + 3] > 0) { - target[k * 4 + 0] = BLEND(src_alpha, target[k * 4 + 0], ink[0], tmp); - target[k * 4 + 1] = BLEND(src_alpha, target[k * 4 + 1], ink[1], tmp); - target[k * 4 + 2] = BLEND(src_alpha, target[k * 4 + 2], ink[2], tmp); - target[k * 4 + 3] = CLIP8(src_alpha + MULDIV255(target[k * 4 + 3], (255 - src_alpha), tmp)); + target[k * 4 + 0] = BLEND( + src_alpha, target[k * 4 + 0], ink[0], tmp); + target[k * 4 + 1] = BLEND( + src_alpha, target[k * 4 + 1], ink[1], tmp); + target[k * 4 + 2] = BLEND( + src_alpha, target[k * 4 + 2], ink[2], tmp); + target[k * 4 + 3] = CLIP8( + src_alpha + + MULDIV255( + target[k * 4 + 3], (255 - src_alpha), tmp)); } else { target[k * 4 + 0] = ink[0]; target[k * 4 + 1] = ink[1]; @@ -1109,7 +1147,13 @@ font_render(FontObject *self, PyObject *args) { for (k = x0; k < x1; k++) { unsigned int src_alpha = source[k] * convert_scale; if (src_alpha > 0) { - target[k] = target[k] > 0 ? CLIP8(src_alpha + MULDIV255(target[k], (255 - src_alpha), tmp)) : src_alpha; + target[k] = + target[k] > 0 + ? CLIP8( + src_alpha + + MULDIV255( + target[k], (255 - src_alpha), tmp)) + : src_alpha; } } } @@ -1249,7 +1293,8 @@ font_getvaraxes(FontObject *self) { if (name.name_id == axis.strid) { axis_name = Py_BuildValue("y#", name.string, name.string_len); - PyDict_SetItemString(list_axis, "name", axis_name ? axis_name : Py_None); + PyDict_SetItemString( + list_axis, "name", axis_name ? axis_name : Py_None); Py_XDECREF(axis_name); break; } @@ -1299,7 +1344,7 @@ font_setvaraxes(FontObject *self, PyObject *args) { } num_coords = PyObject_Length(axes); - coords = (FT_Fixed*)malloc(num_coords * sizeof(FT_Fixed)); + coords = (FT_Fixed *)malloc(num_coords * sizeof(FT_Fixed)); if (coords == NULL) { return PyErr_NoMemory(); } diff --git a/src/display.c b/src/display.c index 6b66ddafb..abf94f1e1 100644 --- a/src/display.c +++ b/src/display.c @@ -716,7 +716,7 @@ PyImaging_DrawWmf(PyObject *self, PyObject *args) { HDC dc; RECT rect; PyObject *buffer = NULL; - char *ptr; + void *ptr; char *data; Py_ssize_t datasize; diff --git a/src/encode.c b/src/encode.c index c7dd51015..442b5d04f 100644 --- a/src/encode.c +++ b/src/encode.c @@ -1163,8 +1163,10 @@ PyImaging_JpegEncoderNew(PyObject *self, PyObject *args) { ((JPEGENCODERSTATE *)encoder->state.context)->streamtype = streamtype; ((JPEGENCODERSTATE *)encoder->state.context)->xdpi = xdpi; ((JPEGENCODERSTATE *)encoder->state.context)->ydpi = ydpi; - ((JPEGENCODERSTATE *)encoder->state.context)->restart_marker_blocks = restart_marker_blocks; - ((JPEGENCODERSTATE *)encoder->state.context)->restart_marker_rows = restart_marker_rows; + ((JPEGENCODERSTATE *)encoder->state.context)->restart_marker_blocks = + restart_marker_blocks; + ((JPEGENCODERSTATE *)encoder->state.context)->restart_marker_rows = + restart_marker_rows; ((JPEGENCODERSTATE *)encoder->state.context)->comment = comment; ((JPEGENCODERSTATE *)encoder->state.context)->comment_size = comment_size; ((JPEGENCODERSTATE *)encoder->state.context)->extra = extra; @@ -1333,9 +1335,7 @@ PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args) { if (comment && comment_size > 0) { /* Size is stored as as an uint16, subtract 4 bytes for the header */ if (comment_size >= 65532) { - PyErr_SetString( - PyExc_ValueError, - "JPEG 2000 comment is too long"); + PyErr_SetString(PyExc_ValueError, "JPEG 2000 comment is too long"); Py_DECREF(encoder); return NULL; } diff --git a/src/libImaging/Access.c b/src/libImaging/Access.c index 04618df09..3a5e918e8 100644 --- a/src/libImaging/Access.c +++ b/src/libImaging/Access.c @@ -185,11 +185,11 @@ put_pixel_32(Imaging im, int x, int y, const void *color) { void ImagingAccessInit() { -#define ADD(mode_, get_pixel_, put_pixel_) \ - { \ - ImagingAccess access = add_item(mode_); \ - access->get_pixel = get_pixel_; \ - access->put_pixel = put_pixel_; \ +#define ADD(mode_, get_pixel_, put_pixel_) \ + { \ + ImagingAccess access = add_item(mode_); \ + access->get_pixel = get_pixel_; \ + access->put_pixel = put_pixel_; \ } /* populate access table */ diff --git a/src/libImaging/BcnDecode.c b/src/libImaging/BcnDecode.c index 5e4296eeb..72f478d8d 100644 --- a/src/libImaging/BcnDecode.c +++ b/src/libImaging/BcnDecode.c @@ -83,7 +83,6 @@ decode_bc1_color(rgba *dst, const UINT8 *src, int separate_alpha) { g1 = p[1].g; b1 = p[1].b; - /* NOTE: BC2 and BC3 reuse BC1 color blocks but always act like c0 > c1 */ if (col.c0 > col.c1 || separate_alpha) { p[2].r = (2 * r0 + 1 * r1) / 3; @@ -354,8 +353,7 @@ decode_bc7_block(rgba *col, const UINT8 *src) { } return; } - while (!(mode & (1 << bit++))) - ; + while (!(mode & (1 << bit++))); mode = bit - 1; info = &bc7_modes[mode]; /* color selection bits: {subset}{endpoint} */ @@ -546,7 +544,7 @@ static const UINT8 bc6_bit_packings[][75] = { 21, 22, 23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 10, 112, 113, 114, 115, 64, 65, 66, 67, 26, 176, 160, 161, 162, 163, 80, 81, 82, 83, 42, 177, 128, 129, 130, 131, - 96, 97, 98, 99, 100, 178, 144, 145, 146, 147, 148, 179}, + 96, 97, 98, 99, 100, 178, 144, 145, 146, 147, 148, 179}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 10, 164, 112, 113, 114, 115, 64, 65, 66, 67, 68, @@ -684,7 +682,7 @@ bc6_clamp(float value) { } else if (value > 1.0f) { return 255; } else { - return (UINT8) (value * 255.0f); + return (UINT8)(value * 255.0f); } } @@ -826,7 +824,13 @@ put_block(Imaging im, ImagingCodecState state, const char *col, int sz, int C) { static int decode_bcn( - Imaging im, ImagingCodecState state, const UINT8 *src, int bytes, int N, int C, char *pixel_format) { + Imaging im, + ImagingCodecState state, + const UINT8 *src, + int bytes, + int N, + int C, + char *pixel_format) { int ymax = state->ysize + state->yoff; const UINT8 *ptr = src; switch (N) { @@ -849,8 +853,7 @@ decode_bcn( DECODE_LOOP(2, 16, rgba); DECODE_LOOP(3, 16, rgba); DECODE_LOOP(4, 8, lum); - case 5: - { + case 5: { int sign = strcmp(pixel_format, "BC5S") == 0 ? 1 : 0; while (bytes >= 16) { rgba col[16]; @@ -865,8 +868,7 @@ decode_bcn( } break; } - case 6: - { + case 6: { int sign = strcmp(pixel_format, "BC6HS") == 0 ? 1 : 0; while (bytes >= 16) { rgba col[16]; @@ -880,7 +882,7 @@ decode_bcn( } break; } - DECODE_LOOP(7, 16, rgba); + DECODE_LOOP(7, 16, rgba); #undef DECODE_LOOP } return (int)(ptr - src); diff --git a/src/libImaging/BoxBlur.c b/src/libImaging/BoxBlur.c index adf425d0d..4ea9c7717 100644 --- a/src/libImaging/BoxBlur.c +++ b/src/libImaging/BoxBlur.c @@ -313,12 +313,12 @@ _gaussian_blur_radius(float radius, int passes) { } Imaging -ImagingGaussianBlur(Imaging imOut, Imaging imIn, float xradius, float yradius, int passes) { +ImagingGaussianBlur( + Imaging imOut, Imaging imIn, float xradius, float yradius, int passes) { return ImagingBoxBlur( - imOut, - imIn, - _gaussian_blur_radius(xradius, passes), - _gaussian_blur_radius(yradius, passes), - passes - ); + imOut, + imIn, + _gaussian_blur_radius(xradius, passes), + _gaussian_blur_radius(yradius, passes), + passes); } diff --git a/src/libImaging/Convert.c b/src/libImaging/Convert.c index 64840d08c..fcb5f7ad9 100644 --- a/src/libImaging/Convert.c +++ b/src/libImaging/Convert.c @@ -518,8 +518,8 @@ rgba2rgb_(UINT8 *out, const UINT8 *in, int xsize) { /* * Conversion of RGB + single transparent color either to - * RGBA or LA, where any pixel matching the color will have the alpha channel set to 0, or - * RGBa or La, where any pixel matching the color will have all channels set to 0 + * RGBA or LA, where any pixel matching the color will have the alpha channel set to 0, + * or RGBa or La, where any pixel matching the color will have all channels set to 0 */ static void @@ -1676,7 +1676,8 @@ convert( return (Imaging)ImagingError_ValueError("conversion not supported"); #else static char buf[100]; - snprintf(buf, 100, "conversion from %.10s to %.10s not supported", imIn->mode, mode); + snprintf( + buf, 100, "conversion from %.10s to %.10s not supported", imIn->mode, mode); return (Imaging)ImagingError_ValueError(buf); #endif } @@ -1720,25 +1721,24 @@ ImagingConvertTransparent(Imaging imIn, const char *mode, int r, int g, int b) { return (Imaging)ImagingError_ModeError(); } - if (strcmp(imIn->mode, "RGB") == 0 && (strcmp(mode, "RGBA") == 0 || strcmp(mode, "RGBa") == 0)) { + if (strcmp(imIn->mode, "RGB") == 0 && + (strcmp(mode, "RGBA") == 0 || strcmp(mode, "RGBa") == 0)) { convert = rgb2rgba; if (strcmp(mode, "RGBa") == 0) { premultiplied = 1; } - } else if (strcmp(imIn->mode, "RGB") == 0 && (strcmp(mode, "LA") == 0 || strcmp(mode, "La") == 0)) { + } else if ( + strcmp(imIn->mode, "RGB") == 0 && + (strcmp(mode, "LA") == 0 || strcmp(mode, "La") == 0)) { convert = rgb2la; source_transparency = 1; if (strcmp(mode, "La") == 0) { premultiplied = 1; } - } else if ((strcmp(imIn->mode, "1") == 0 || - strcmp(imIn->mode, "I") == 0 || - strcmp(imIn->mode, "I;16") == 0 || - strcmp(imIn->mode, "L") == 0 - ) && ( - strcmp(mode, "RGBA") == 0 || - strcmp(mode, "LA") == 0 - )) { + } else if ( + (strcmp(imIn->mode, "1") == 0 || strcmp(imIn->mode, "I") == 0 || + strcmp(imIn->mode, "I;16") == 0 || strcmp(imIn->mode, "L") == 0) && + (strcmp(mode, "RGBA") == 0 || strcmp(mode, "LA") == 0)) { if (strcmp(imIn->mode, "1") == 0) { convert = bit2rgb; } else if (strcmp(imIn->mode, "I") == 0) { diff --git a/src/libImaging/Dib.c b/src/libImaging/Dib.c index 1b5bfe132..269be1058 100644 --- a/src/libImaging/Dib.c +++ b/src/libImaging/Dib.c @@ -94,8 +94,8 @@ ImagingNewDIB(const char *mode, int xsize, int ysize) { return (ImagingDIB)ImagingError_MemoryError(); } - dib->bitmap = - CreateDIBSection(dib->dc, dib->info, DIB_RGB_COLORS, &dib->bits, NULL, 0); + dib->bitmap = CreateDIBSection( + dib->dc, dib->info, DIB_RGB_COLORS, (void **)&dib->bits, NULL, 0); if (!dib->bitmap) { free(dib->info); free(dib); diff --git a/src/libImaging/Draw.c b/src/libImaging/Draw.c index 0ccf22d58..133696dd8 100644 --- a/src/libImaging/Draw.c +++ b/src/libImaging/Draw.c @@ -48,7 +48,7 @@ * This guarantees that ROUND_UP|DOWN(f) == -ROUND_UP|DOWN(-f) */ #define ROUND_UP(f) ((int)((f) >= 0.0 ? floor((f) + 0.5F) : -floor(fabs(f) + 0.5F))) -#define ROUND_DOWN(f) ((int)((f) >= 0.0 ? ceil((f)-0.5F) : -ceil(fabs(f) - 0.5F))) +#define ROUND_DOWN(f) ((int)((f) >= 0.0 ? ceil((f) - 0.5F) : -ceil(fabs(f) - 0.5F))) /* -------------------------------------------------------------------- */ /* Primitives */ @@ -439,7 +439,14 @@ draw_horizontal_lines( * Filled polygon draw function using scan line algorithm. */ static inline int -polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler hline, int hasAlpha) { +polygon_generic( + Imaging im, + int n, + Edge *e, + int ink, + int eofill, + hline_handler hline, + int hasAlpha) { Edge **edge_table; float *xx; int edge_count = 0; @@ -499,7 +506,7 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h // Needed to draw consistent polygons xx[j] = xx[j - 1]; j++; - } else if (current->dx != 0 && roundf(xx[j-1]) == xx[j-1]) { + } else if (current->dx != 0 && roundf(xx[j - 1]) == xx[j - 1]) { // Connect discontiguous corners for (k = 0; k < i; k++) { Edge *other_edge = edge_table[k]; @@ -510,23 +517,38 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h // Check if the two edges join to make a corner if (((ymin == current->ymin && ymin == other_edge->ymin) || (ymin == current->ymax && ymin == other_edge->ymax)) && - xx[j-1] == (ymin - other_edge->y0) * other_edge->dx + other_edge->x0) { + xx[j - 1] == (ymin - other_edge->y0) * other_edge->dx + + other_edge->x0) { // Determine points from the edges on the next row // Or if this is the last row, check the previous row int offset = ymin == ymax ? -1 : 1; - adjacent_line_x = (ymin + offset - current->y0) * current->dx + current->x0; - adjacent_line_x_other_edge = (ymin + offset - other_edge->y0) * other_edge->dx + other_edge->x0; + adjacent_line_x = + (ymin + offset - current->y0) * current->dx + + current->x0; + adjacent_line_x_other_edge = + (ymin + offset - other_edge->y0) * other_edge->dx + + other_edge->x0; if (ymin == current->ymax) { if (current->dx > 0) { - xx[k] = fmax(adjacent_line_x, adjacent_line_x_other_edge) + 1; + xx[k] = fmax( + adjacent_line_x, + adjacent_line_x_other_edge) + + 1; } else { - xx[k] = fmin(adjacent_line_x, adjacent_line_x_other_edge) - 1; + xx[k] = fmin( + adjacent_line_x, + adjacent_line_x_other_edge) - + 1; } } else { if (current->dx > 0) { - xx[k] = fmin(adjacent_line_x, adjacent_line_x_other_edge); + xx[k] = fmin( + adjacent_line_x, adjacent_line_x_other_edge); } else { - xx[k] = fmax(adjacent_line_x, adjacent_line_x_other_edge) + 1; + xx[k] = fmax( + adjacent_line_x, + adjacent_line_x_other_edge) + + 1; } } break; @@ -552,7 +574,8 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h int x_start = ROUND_UP(xx[i - 1]); if (x_pos > x_start) { - // Line would be partway through x_pos, so increase the starting point + // Line would be partway through x_pos, so increase the starting + // point x_start = x_pos; if (x_end < x_start) { // Line would now end before it started @@ -776,7 +799,8 @@ ImagingDrawRectangle( } int -ImagingDrawPolygon(Imaging im, int count, int *xy, const void *ink_, int fill, int width, int op) { +ImagingDrawPolygon( + Imaging im, int count, int *xy, const void *ink_, int fill, int width, int op) { int i, n, x0, y0, x1, y1; DRAW *draw; INT32 ink; @@ -803,7 +827,7 @@ ImagingDrawPolygon(Imaging im, int count, int *xy, const void *ink_, int fill, i if (y0 == y1 && i != 0 && y0 == xy[i * 2 - 1]) { // This is a horizontal line, // that immediately follows another horizontal line - Edge *last_e = &e[n-1]; + Edge *last_e = &e[n - 1]; if (x1 > x0 && x0 > xy[i * 2 - 2]) { // They are both increasing in x last_e->xmax = x1; @@ -826,14 +850,24 @@ ImagingDrawPolygon(Imaging im, int count, int *xy, const void *ink_, int fill, i /* Outline */ if (width == 1) { for (i = 0; i < count - 1; i++) { - draw->line(im, xy[i * 2], xy[i * 2 + 1], xy[i * 2 + 2], xy[i * 2 + 3], ink); + draw->line( + im, xy[i * 2], xy[i * 2 + 1], xy[i * 2 + 2], xy[i * 2 + 3], ink); } draw->line(im, xy[i * 2], xy[i * 2 + 1], xy[0], xy[1], ink); } else { for (i = 0; i < count - 1; i++) { - ImagingDrawWideLine(im, xy[i * 2], xy[i * 2 + 1], xy[i * 2 + 2], xy[i * 2 + 3], ink_, width, op); + ImagingDrawWideLine( + im, + xy[i * 2], + xy[i * 2 + 1], + xy[i * 2 + 2], + xy[i * 2 + 3], + ink_, + width, + op); } - ImagingDrawWideLine(im, xy[i * 2], xy[i * 2 + 1], xy[0], xy[1], ink_, width, op); + ImagingDrawWideLine( + im, xy[i * 2], xy[i * 2 + 1], xy[0], xy[1], ink_, width, op); } } diff --git a/src/libImaging/Filter.c b/src/libImaging/Filter.c index 4dcd368ca..85de77fcb 100644 --- a/src/libImaging/Filter.c +++ b/src/libImaging/Filter.c @@ -106,7 +106,7 @@ ImagingExpand(Imaging imIn, int xmargin, int ymargin) { void ImagingFilter3x3(Imaging imOut, Imaging im, const float *kernel, float offset) { -#define KERNEL1x3(in0, x, kernel, d) \ +#define KERNEL1x3(in0, x, kernel, d) \ (_i2f(in0[x - d]) * (kernel)[0] + _i2f(in0[x]) * (kernel)[1] + \ _i2f(in0[x + d]) * (kernel)[2]) @@ -224,10 +224,9 @@ ImagingFilter3x3(Imaging imOut, Imaging im, const float *kernel, float offset) { void ImagingFilter5x5(Imaging imOut, Imaging im, const float *kernel, float offset) { -#define KERNEL1x5(in0, x, kernel, d) \ - (_i2f(in0[x - d - d]) * (kernel)[0] + \ - _i2f(in0[x - d]) * (kernel)[1] + _i2f(in0[x]) * (kernel)[2] + \ - _i2f(in0[x + d]) * (kernel)[3] + \ +#define KERNEL1x5(in0, x, kernel, d) \ + (_i2f(in0[x - d - d]) * (kernel)[0] + _i2f(in0[x - d]) * (kernel)[1] + \ + _i2f(in0[x]) * (kernel)[2] + _i2f(in0[x + d]) * (kernel)[3] + \ _i2f(in0[x + d + d]) * (kernel)[4]) int x = 0, y = 0; diff --git a/src/libImaging/FliDecode.c b/src/libImaging/FliDecode.c index d6e4ea0ff..6b2518d35 100644 --- a/src/libImaging/FliDecode.c +++ b/src/libImaging/FliDecode.c @@ -231,8 +231,9 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t byt } /* Note, have to check Data + size, not just ptr + size) */ if (data + (state->xsize * state->ysize) > ptr + bytes) { - /* not enough data for frame */ - /* UNDONE Unclear that we're actually going to leave the buffer at the right place. */ + // not enough data for frame + // UNDONE Unclear that we're actually going to leave the buffer at + // the right place. return ptr - buf; /* bytes consumed */ } for (y = 0; y < state->ysize; y++) { @@ -251,7 +252,7 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t byt return -1; } advance = I32(ptr); - if (advance == 0 ) { + if (advance == 0) { // If there's no advance, we're in an infinite loop state->errcode = IMAGING_CODEC_BROKEN; return -1; diff --git a/src/libImaging/Geometry.c b/src/libImaging/Geometry.c index 0c5915792..cf3bc9979 100644 --- a/src/libImaging/Geometry.c +++ b/src/libImaging/Geometry.c @@ -565,13 +565,13 @@ bilinear_filter32RGB(void *out, Imaging im, double xin, double yin) { #undef BILINEAR_HEAD #undef BILINEAR_BODY -#define BICUBIC(v, v1, v2, v3, v4, d) \ - { \ - double p1 = v2; \ - double p2 = -v1 + v3; \ - double p3 = 2 * (v1 - v2) + v3 - v4; \ - double p4 = -v1 + v2 - v3 + v4; \ - v = p1 + (d) * (p2 + (d) * (p3 + (d)*p4)); \ +#define BICUBIC(v, v1, v2, v3, v4, d) \ + { \ + double p1 = v2; \ + double p2 = -v1 + v3; \ + double p3 = 2 * (v1 - v2) + v3 - v4; \ + double p4 = -v1 + v2 - v3 + v4; \ + v = p1 + (d) * (p2 + (d) * (p3 + (d) * p4)); \ } #define BICUBIC_HEAD(type) \ @@ -966,7 +966,7 @@ affine_fixed( ysize = (int)imIn->ysize; /* use 16.16 fixed point arithmetics */ -#define FIX(v) FLOOR((v)*65536.0 + 0.5) +#define FIX(v) FLOOR((v) * 65536.0 + 0.5) a0 = FIX(a[0]); a1 = FIX(a[1]); diff --git a/src/libImaging/GetBBox.c b/src/libImaging/GetBBox.c index 86c687ca0..bd2a2778c 100644 --- a/src/libImaging/GetBBox.c +++ b/src/libImaging/GetBBox.c @@ -58,11 +58,11 @@ ImagingGetBBox(Imaging im, int bbox[4], int alpha_only) { INT32 mask = 0xffffffff; if (im->bands == 3) { ((UINT8 *)&mask)[3] = 0; - } else if (alpha_only && ( - strcmp(im->mode, "RGBa") == 0 || strcmp(im->mode, "RGBA") == 0 || - strcmp(im->mode, "La") == 0 || strcmp(im->mode, "LA") == 0 || - strcmp(im->mode, "PA") == 0 - )) { + } else if ( + alpha_only && + (strcmp(im->mode, "RGBa") == 0 || strcmp(im->mode, "RGBA") == 0 || + strcmp(im->mode, "La") == 0 || strcmp(im->mode, "LA") == 0 || + strcmp(im->mode, "PA") == 0)) { #ifdef WORDS_BIGENDIAN mask = 0x000000ff; #else diff --git a/src/libImaging/Gif.h b/src/libImaging/Gif.h index 5d7e2bdaa..8edfbc2ed 100644 --- a/src/libImaging/Gif.h +++ b/src/libImaging/Gif.h @@ -9,10 +9,10 @@ /* Max size for a LZW code word. */ -#define GIFBITS 12 +#define GIFBITS 12 -#define GIFTABLE (1<next_code = st->end_code + 1; st->max_code = 2 * st->clear_code - 1; st->code_width = st->bits + 1; memset(st->codes, 0, sizeof(st->codes)); } -static void glzwe_init(GIFENCODERSTATE *st) { +static void +glzwe_init(GIFENCODERSTATE *st) { st->clear_code = 1 << st->bits; st->end_code = st->clear_code + 1; glzwe_reset(st); @@ -64,156 +72,157 @@ static void glzwe_init(GIFENCODERSTATE *st) { st->code_buffer = 0; } -static int glzwe(GIFENCODERSTATE *st, const UINT8 *in_ptr, UINT8 *out_ptr, - UINT32 *in_avail, UINT32 *out_avail, - UINT32 end_of_data) { +static int +glzwe( + GIFENCODERSTATE *st, + const UINT8 *in_ptr, + UINT8 *out_ptr, + UINT32 *in_avail, + UINT32 *out_avail, + UINT32 end_of_data) { switch (st->entry_state) { - - case LZW_TRY_IN1: + case LZW_TRY_IN1: get_first_byte: - if (!*in_avail) { - if (end_of_data) { - goto end_of_data; + if (!*in_avail) { + if (end_of_data) { + goto end_of_data; + } + st->entry_state = LZW_TRY_IN1; + return GLZW_NO_INPUT_AVAIL; } - st->entry_state = LZW_TRY_IN1; - return GLZW_NO_INPUT_AVAIL; - } - st->head = *in_ptr++; - (*in_avail)--; + st->head = *in_ptr++; + (*in_avail)--; - case LZW_TRY_IN2: + case LZW_TRY_IN2: encode_loop: - if (!*in_avail) { - if (end_of_data) { - st->code = st->head; - st->put_state = PUT_LAST_HEAD; - goto put_code; + if (!*in_avail) { + if (end_of_data) { + st->code = st->head; + st->put_state = PUT_LAST_HEAD; + goto put_code; + } + st->entry_state = LZW_TRY_IN2; + return GLZW_NO_INPUT_AVAIL; } - st->entry_state = LZW_TRY_IN2; - return GLZW_NO_INPUT_AVAIL; - } - st->tail = *in_ptr++; - (*in_avail)--; + st->tail = *in_ptr++; + (*in_avail)--; - /* Knuth TAOCP vol 3 sec. 6.4 algorithm D. */ - /* Hash found experimentally to be pretty good. */ - /* This works ONLY with TABLE_SIZE a power of 2. */ - st->probe = ((st->head ^ (st->tail << 6)) * 31) & (TABLE_SIZE - 1); - while (st->codes[st->probe]) { - if ((st->codes[st->probe] & 0xFFFFF) == - ((st->head << 8) | st->tail)) { - st->head = st->codes[st->probe] >> 20; - goto encode_loop; - } else { - /* Reprobe decrement must be non-zero and relatively prime to table - * size. So, any odd positive number for power-of-2 size. */ - if ((st->probe -= ((st->tail << 2) | 1)) < 0) { - st->probe += TABLE_SIZE; + /* Knuth TAOCP vol 3 sec. 6.4 algorithm D. */ + /* Hash found experimentally to be pretty good. */ + /* This works ONLY with TABLE_SIZE a power of 2. */ + st->probe = ((st->head ^ (st->tail << 6)) * 31) & (TABLE_SIZE - 1); + while (st->codes[st->probe]) { + if ((st->codes[st->probe] & 0xFFFFF) == ((st->head << 8) | st->tail)) { + st->head = st->codes[st->probe] >> 20; + goto encode_loop; + } else { + // Reprobe decrement must be non-zero and relatively prime to table + // size. So, any odd positive number for power-of-2 size. + if ((st->probe -= ((st->tail << 2) | 1)) < 0) { + st->probe += TABLE_SIZE; + } } } - } - /* Key not found, probe is at empty slot. */ - st->code = st->head; - st->put_state = PUT_HEAD; - goto put_code; -insert_code_or_clear: /* jump here after put_code */ - if (st->next_code < CODE_LIMIT) { - st->codes[st->probe] = (st->next_code << 20) | - (st->head << 8) | st->tail; - if (st->next_code > st->max_code) { - st->max_code = st->max_code * 2 + 1; - st->code_width++; - } - st->next_code++; - } else { - st->code = st->clear_code; - st->put_state = PUT_CLEAR; + /* Key not found, probe is at empty slot. */ + st->code = st->head; + st->put_state = PUT_HEAD; goto put_code; +insert_code_or_clear: /* jump here after put_code */ + if (st->next_code < CODE_LIMIT) { + st->codes[st->probe] = + (st->next_code << 20) | (st->head << 8) | st->tail; + if (st->next_code > st->max_code) { + st->max_code = st->max_code * 2 + 1; + st->code_width++; + } + st->next_code++; + } else { + st->code = st->clear_code; + st->put_state = PUT_CLEAR; + goto put_code; reset_after_clear: /* jump here after put_code */ - glzwe_reset(st); - } - st->head = st->tail; - goto encode_loop; - - case LZW_INITIAL: - glzwe_reset(st); - st->code = st->clear_code; - st->put_state = PUT_INIT_CLEAR; -put_code: - st->code_bits_left = st->code_width; -check_buf_bits: - if (!st->buf_bits_left) { /* out buffer full */ - - case LZW_TRY_OUT1: - if (!*out_avail) { - st->entry_state = LZW_TRY_OUT1; - return GLZW_NO_OUTPUT_AVAIL; + glzwe_reset(st); + } + st->head = st->tail; + goto encode_loop; + + case LZW_INITIAL: + glzwe_reset(st); + st->code = st->clear_code; + st->put_state = PUT_INIT_CLEAR; +put_code: + st->code_bits_left = st->code_width; +check_buf_bits: + if (!st->buf_bits_left) { /* out buffer full */ + + case LZW_TRY_OUT1: + if (!*out_avail) { + st->entry_state = LZW_TRY_OUT1; + return GLZW_NO_OUTPUT_AVAIL; + } + *out_ptr++ = st->code_buffer; + (*out_avail)--; + st->code_buffer = 0; + st->buf_bits_left = 8; + } + /* code bits to pack */ + UINT32 n = st->buf_bits_left < st->code_bits_left ? st->buf_bits_left + : st->code_bits_left; + st->code_buffer |= (st->code & ((1 << n) - 1)) << (8 - st->buf_bits_left); + st->code >>= n; + st->buf_bits_left -= n; + st->code_bits_left -= n; + if (st->code_bits_left) { + goto check_buf_bits; + } + switch (st->put_state) { + case PUT_INIT_CLEAR: + goto get_first_byte; + case PUT_HEAD: + goto insert_code_or_clear; + case PUT_CLEAR: + goto reset_after_clear; + case PUT_LAST_HEAD: + goto end_of_data; + case PUT_END: + goto flush_code_buffer; + default: + return GLZW_INTERNAL_ERROR; } - *out_ptr++ = st->code_buffer; - (*out_avail)--; - st->code_buffer = 0; - st->buf_bits_left = 8; - } - /* code bits to pack */ - UINT32 n = st->buf_bits_left < st->code_bits_left - ? st->buf_bits_left : st->code_bits_left; - st->code_buffer |= - (st->code & ((1 << n) - 1)) << (8 - st->buf_bits_left); - st->code >>= n; - st->buf_bits_left -= n; - st->code_bits_left -= n; - if (st->code_bits_left) { - goto check_buf_bits; - } - switch (st->put_state) { - case PUT_INIT_CLEAR: - goto get_first_byte; - case PUT_HEAD: - goto insert_code_or_clear; - case PUT_CLEAR: - goto reset_after_clear; - case PUT_LAST_HEAD: - goto end_of_data; - case PUT_END: - goto flush_code_buffer; - default: - return GLZW_INTERNAL_ERROR; - } end_of_data: - st->code = st->end_code; - st->put_state = PUT_END; - goto put_code; + st->code = st->end_code; + st->put_state = PUT_END; + goto put_code; flush_code_buffer: /* jump here after put_code */ - if (st->buf_bits_left < 8) { - - case LZW_TRY_OUT2: - if (!*out_avail) { - st->entry_state = LZW_TRY_OUT2; - return GLZW_NO_OUTPUT_AVAIL; + if (st->buf_bits_left < 8) { + case LZW_TRY_OUT2: + if (!*out_avail) { + st->entry_state = LZW_TRY_OUT2; + return GLZW_NO_OUTPUT_AVAIL; + } + *out_ptr++ = st->code_buffer; + (*out_avail)--; } - *out_ptr++ = st->code_buffer; - (*out_avail)--; - } - st->entry_state = LZW_FINISHED; - return GLZW_OK; + st->entry_state = LZW_FINISHED; + return GLZW_OK; - case LZW_FINISHED: - return GLZW_OK; + case LZW_FINISHED: + return GLZW_OK; - default: - return GLZW_INTERNAL_ERROR; + default: + return GLZW_INTERNAL_ERROR; } } /* -END- GIF LZW encoder. */ int -ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) { - UINT8* ptr; - UINT8* sub_block_ptr; - UINT8* sub_block_limit; - UINT8* buf_limit; - GIFENCODERSTATE *context = (GIFENCODERSTATE*) state->context; +ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) { + UINT8 *ptr; + UINT8 *sub_block_ptr; + UINT8 *sub_block_limit; + UINT8 *buf_limit; + GIFENCODERSTATE *context = (GIFENCODERSTATE *)state->context; int r; UINT32 in_avail, in_used; @@ -278,9 +287,9 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) { return ptr - buf; } sub_block_ptr = ptr; - sub_block_limit = sub_block_ptr + - (256 < buf_limit - sub_block_ptr ? - 256 : buf_limit - sub_block_ptr); + sub_block_limit = + sub_block_ptr + + (256 < buf_limit - sub_block_ptr ? 256 : buf_limit - sub_block_ptr); *ptr++ = 0; } @@ -301,9 +310,9 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) { /* get another line of data */ state->shuffle( state->buffer, - (UINT8*) im->image[state->y + state->yoff] + - state->xoff * im->pixelsize, state->xsize - ); + (UINT8 *)im->image[state->y + state->yoff] + + state->xoff * im->pixelsize, + state->xsize); state->x = 0; /* step forward, according to the interlace settings */ @@ -331,10 +340,15 @@ ImagingGifEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) { } } - in_avail = state->xsize - state->x; /* bytes left in line */ + in_avail = state->xsize - state->x; /* bytes left in line */ out_avail = sub_block_limit - ptr; /* bytes left in sub-block */ - r = glzwe(context, &state->buffer[state->x], ptr, &in_avail, - &out_avail, state->state == FINISH); + r = glzwe( + context, + &state->buffer[state->x], + ptr, + &in_avail, + &out_avail, + state->state == FINISH); out_used = sub_block_limit - ptr - out_avail; *sub_block_ptr += out_used; ptr += out_used; diff --git a/src/libImaging/Imaging.h b/src/libImaging/Imaging.h index afcd2229b..1f2c03e93 100644 --- a/src/libImaging/Imaging.h +++ b/src/libImaging/Imaging.h @@ -108,15 +108,15 @@ struct ImagingMemoryInstance { #define IMAGING_PIXEL_1(im, x, y) ((im)->image8[(y)][(x)]) #define IMAGING_PIXEL_L(im, x, y) ((im)->image8[(y)][(x)]) -#define IMAGING_PIXEL_LA(im, x, y) ((im)->image[(y)][(x)*4]) +#define IMAGING_PIXEL_LA(im, x, y) ((im)->image[(y)][(x) * 4]) #define IMAGING_PIXEL_P(im, x, y) ((im)->image8[(y)][(x)]) -#define IMAGING_PIXEL_PA(im, x, y) ((im)->image[(y)][(x)*4]) +#define IMAGING_PIXEL_PA(im, x, y) ((im)->image[(y)][(x) * 4]) #define IMAGING_PIXEL_I(im, x, y) ((im)->image32[(y)][(x)]) #define IMAGING_PIXEL_F(im, x, y) (((FLOAT32 *)(im)->image32[y])[x]) -#define IMAGING_PIXEL_RGB(im, x, y) ((im)->image[(y)][(x)*4]) -#define IMAGING_PIXEL_RGBA(im, x, y) ((im)->image[(y)][(x)*4]) -#define IMAGING_PIXEL_CMYK(im, x, y) ((im)->image[(y)][(x)*4]) -#define IMAGING_PIXEL_YCbCr(im, x, y) ((im)->image[(y)][(x)*4]) +#define IMAGING_PIXEL_RGB(im, x, y) ((im)->image[(y)][(x) * 4]) +#define IMAGING_PIXEL_RGBA(im, x, y) ((im)->image[(y)][(x) * 4]) +#define IMAGING_PIXEL_CMYK(im, x, y) ((im)->image[(y)][(x) * 4]) +#define IMAGING_PIXEL_YCbCr(im, x, y) ((im)->image[(y)][(x) * 4]) #define IMAGING_PIXEL_UINT8(im, x, y) ((im)->image8[(y)][(x)]) #define IMAGING_PIXEL_INT32(im, x, y) ((im)->image32[(y)][(x)]) @@ -161,7 +161,7 @@ typedef struct ImagingMemoryArena { int stats_reallocated_blocks; /* Number of blocks which were actually reallocated after retrieving */ int stats_freed_blocks; /* Number of freed blocks */ -} * ImagingMemoryArena; +} *ImagingMemoryArena; /* Objects */ /* ------- */ @@ -309,7 +309,8 @@ ImagingFlipLeftRight(Imaging imOut, Imaging imIn); extern Imaging ImagingFlipTopBottom(Imaging imOut, Imaging imIn); extern Imaging -ImagingGaussianBlur(Imaging imOut, Imaging imIn, float xradius, float yradius, int passes); +ImagingGaussianBlur( + Imaging imOut, Imaging imIn, float xradius, float yradius, int passes); extern Imaging ImagingGetBand(Imaging im, int band); extern Imaging @@ -487,7 +488,8 @@ ImagingDrawPieslice( extern int ImagingDrawPoint(Imaging im, int x, int y, const void *ink, int op); extern int -ImagingDrawPolygon(Imaging im, int points, int *xy, const void *ink, int fill, int width, int op); +ImagingDrawPolygon( + Imaging im, int points, int *xy, const void *ink, int fill, int width, int op); extern int ImagingDrawRectangle( Imaging im, diff --git a/src/libImaging/ImagingUtils.h b/src/libImaging/ImagingUtils.h index 0c0c1eda9..714458ad0 100644 --- a/src/libImaging/ImagingUtils.h +++ b/src/libImaging/ImagingUtils.h @@ -21,7 +21,7 @@ #define DIV255(a, tmp) (tmp = (a) + 128, SHIFTFORDIV255(tmp)) -#define BLEND(mask, in1, in2, tmp1) DIV255(in1 *(255 - mask) + in2 * mask, tmp1) +#define BLEND(mask, in1, in2, tmp1) DIV255(in1 * (255 - mask) + in2 * mask, tmp1) #define PREBLEND(mask, in1, in2, tmp1) (MULDIV255(in1, (255 - mask), tmp1) + in2) diff --git a/src/libImaging/Jpeg2KDecode.c b/src/libImaging/Jpeg2KDecode.c index 78a09bb83..dd066c10b 100644 --- a/src/libImaging/Jpeg2KDecode.c +++ b/src/libImaging/Jpeg2KDecode.c @@ -183,9 +183,9 @@ j2ku_gray_i( UINT16 *row = (UINT16 *)im->image[y0 + y] + x0; for (x = 0; x < w; ++x) { UINT16 pixel = j2ku_shift(offset + *data++, shift); - #ifdef WORDS_BIGENDIAN - pixel = (pixel >> 8) | (pixel << 8); - #endif +#ifdef WORDS_BIGENDIAN + pixel = (pixel >> 8) | (pixel << 8); +#endif *row++ = pixel; } } @@ -778,7 +778,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) { color_space = OPJ_CLRSPC_SYCC; break; } - break; + break; } } @@ -864,7 +864,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) { a, and then a malicious file could have a smaller tile_bytes */ - for (n=0; n < tile_info.nb_comps; n++) { + for (n = 0; n < tile_info.nb_comps; n++) { // see csize /acsize calcs int csize = (image->comps[n].prec + 7) >> 3; csize = (csize == 3) ? 4 : csize; diff --git a/src/libImaging/Jpeg2KEncode.c b/src/libImaging/Jpeg2KEncode.c index 3295373fd..7f1aeaddb 100644 --- a/src/libImaging/Jpeg2KEncode.c +++ b/src/libImaging/Jpeg2KEncode.c @@ -383,8 +383,7 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) { float *pq; if (len > 0) { - if ((size_t)len > - sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0])) { + if ((size_t)len > sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0])) { len = sizeof(params.tcp_rates) / sizeof(params.tcp_rates[0]); } @@ -464,7 +463,8 @@ j2k_encode_entry(Imaging im, ImagingCodecState state) { } if (!context->num_resolutions) { - while (tile_width < (1U << (params.numresolution - 1U)) || tile_height < (1U << (params.numresolution - 1U))) { + while (tile_width < (1U << (params.numresolution - 1U)) || + tile_height < (1U << (params.numresolution - 1U))) { params.numresolution -= 1; } } diff --git a/src/libImaging/JpegEncode.c b/src/libImaging/JpegEncode.c index 00f3d5f74..ba8353c2d 100644 --- a/src/libImaging/JpegEncode.c +++ b/src/libImaging/JpegEncode.c @@ -145,8 +145,8 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) { case JCS_EXT_RGBX: #endif switch (context->subsampling) { - case -1: /* Default */ - case 0: /* No subsampling */ + case -1: /* Default */ + case 0: /* No subsampling */ break; default: /* Would subsample the green and blue @@ -305,7 +305,11 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) { case 4: if (context->comment) { - jpeg_write_marker(&context->cinfo, JPEG_COM, (unsigned char *)context->comment, context->comment_size); + jpeg_write_marker( + &context->cinfo, + JPEG_COM, + (unsigned char *)context->comment, + context->comment_size); } state->state++; diff --git a/src/libImaging/Paste.c b/src/libImaging/Paste.c index 6684b11ef..a018225b2 100644 --- a/src/libImaging/Paste.c +++ b/src/libImaging/Paste.c @@ -432,11 +432,10 @@ fill_mask_L( } } else { - int alpha_channel = strcmp(imOut->mode, "RGBa") == 0 || - strcmp(imOut->mode, "RGBA") == 0 || - strcmp(imOut->mode, "La") == 0 || - strcmp(imOut->mode, "LA") == 0 || - strcmp(imOut->mode, "PA") == 0; + int alpha_channel = + strcmp(imOut->mode, "RGBa") == 0 || strcmp(imOut->mode, "RGBA") == 0 || + strcmp(imOut->mode, "La") == 0 || strcmp(imOut->mode, "LA") == 0 || + strcmp(imOut->mode, "PA") == 0; for (y = 0; y < ysize; y++) { UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx * pixelsize; UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx; diff --git a/src/libImaging/Point.c b/src/libImaging/Point.c index 8883578cb..dd06f3940 100644 --- a/src/libImaging/Point.c +++ b/src/libImaging/Point.c @@ -134,7 +134,7 @@ ImagingPoint(Imaging imIn, const char *mode, const void *table) { ImagingSectionCookie cookie; Imaging imOut; im_point_context context; - void (*point)(Imaging imIn, Imaging imOut, im_point_context * context); + void (*point)(Imaging imIn, Imaging imOut, im_point_context *context); if (!imIn) { return (Imaging)ImagingError_ModeError(); diff --git a/src/libImaging/Quant.c b/src/libImaging/Quant.c index 2582830c4..cdc614536 100644 --- a/src/libImaging/Quant.c +++ b/src/libImaging/Quant.c @@ -260,8 +260,7 @@ mergesort_pixels(PixelList *head, int i) { return head; } for (c = t = head; c && t; - c = c->next[i], t = (t->next[i]) ? t->next[i]->next[i] : NULL) - ; + c = c->next[i], t = (t->next[i]) ? t->next[i]->next[i] : NULL); if (c) { if (c->prev[i]) { c->prev[i]->next[i] = NULL; @@ -354,12 +353,10 @@ splitlists( for (_i = 0; _i < 3; _i++) { for (_nextCount[_i] = 0, _nextTest = h[_i]; _nextTest && _nextTest->next[_i]; - _nextTest = _nextTest->next[_i], _nextCount[_i]++) - ; + _nextTest = _nextTest->next[_i], _nextCount[_i]++); for (_prevCount[_i] = 0, _prevTest = t[_i]; _prevTest && _prevTest->prev[_i]; - _prevTest = _prevTest->prev[_i], _prevCount[_i]++) - ; + _prevTest = _prevTest->prev[_i], _prevCount[_i]++); if (_nextTest != t[_i]) { printf("next-list of axis %d does not end at tail\n", _i); exit(1); @@ -368,10 +365,8 @@ splitlists( printf("prev-list of axis %d does not end at head\n", _i); exit(1); } - for (; _nextTest && _nextTest->prev[_i]; _nextTest = _nextTest->prev[_i]) - ; - for (; _prevTest && _prevTest->next[_i]; _prevTest = _prevTest->next[_i]) - ; + for (; _nextTest && _nextTest->prev[_i]; _nextTest = _nextTest->prev[_i]); + for (; _prevTest && _prevTest->next[_i]; _prevTest = _prevTest->next[_i]); if (_nextTest != h[_i]) { printf("next-list of axis %d does not loop back to head\n", _i); exit(1); @@ -548,22 +543,18 @@ split(BoxNode *node) { for (_i = 0; _i < 3; _i++) { for (_nextCount[_i] = 0, _nextTest = node->head[_i]; _nextTest && _nextTest->next[_i]; - _nextTest = _nextTest->next[_i], _nextCount[_i]++) - ; + _nextTest = _nextTest->next[_i], _nextCount[_i]++); for (_prevCount[_i] = 0, _prevTest = node->tail[_i]; _prevTest && _prevTest->prev[_i]; - _prevTest = _prevTest->prev[_i], _prevCount[_i]++) - ; + _prevTest = _prevTest->prev[_i], _prevCount[_i]++); if (_nextTest != node->tail[_i]) { printf("next-list of axis %d does not end at tail\n", _i); } if (_prevTest != node->head[_i]) { printf("prev-list of axis %d does not end at head\n", _i); } - for (; _nextTest && _nextTest->prev[_i]; _nextTest = _nextTest->prev[_i]) - ; - for (; _prevTest && _prevTest->next[_i]; _prevTest = _prevTest->next[_i]) - ; + for (; _nextTest && _nextTest->prev[_i]; _nextTest = _nextTest->prev[_i]); + for (; _prevTest && _prevTest->next[_i]; _prevTest = _prevTest->next[_i]); if (_nextTest != node->head[_i]) { printf("next-list of axis %d does not loop back to head\n", _i); } @@ -668,8 +659,7 @@ median_cut(PixelList *hl[3], uint32_t imPixelCount, int nPixels) { return NULL; } for (i = 0; i < 3; i++) { - for (tl[i] = hl[i]; tl[i] && tl[i]->next[i]; tl[i] = tl[i]->next[i]) - ; + for (tl[i] = hl[i]; tl[i] && tl[i]->next[i]; tl[i] = tl[i]->next[i]); root->head[i] = hl[i]; root->tail[i] = tl[i]; } @@ -832,16 +822,9 @@ build_distance_tables( } for (i = 0; i < nEntries; i++) { for (j = 0; j < nEntries; j++) { - dwi[j] = (DistanceWithIndex){ - &(avgDist[i * nEntries + j]), - j - }; + dwi[j] = (DistanceWithIndex){&(avgDist[i * nEntries + j]), j}; } - qsort( - dwi, - nEntries, - sizeof(DistanceWithIndex), - _distance_index_cmp); + qsort(dwi, nEntries, sizeof(DistanceWithIndex), _distance_index_cmp); for (j = 0; j < nEntries; j++) { avgDistSortKey[i * nEntries + j] = dwi[j].distance; } @@ -1213,7 +1196,7 @@ k_means( compute_palette_from_quantized_pixels( pixelData, nPixels, paletteData, nPaletteEntries, avg, count, qp); if (!build_distance_tables( - avgDist, avgDistSortKey, paletteData, nPaletteEntries)) { + avgDist, avgDistSortKey, paletteData, nPaletteEntries)) { goto error_3; } built = 1; @@ -1452,15 +1435,17 @@ quantize( hashtable_insert(h2, pixelData[i], bestmatch); } if (qp[i] != bestmatch) { - printf ("discrepancy in matching algorithms pixel %d [%d %d] %f %f\n", - i,qp[i],bestmatch, - sqrt((double)(_SQR(pixelData[i].c.r-p[qp[i]].c.r)+ - _SQR(pixelData[i].c.g-p[qp[i]].c.g)+ - _SQR(pixelData[i].c.b-p[qp[i]].c.b))), - sqrt((double)(_SQR(pixelData[i].c.r-p[bestmatch].c.r)+ - _SQR(pixelData[i].c.g-p[bestmatch].c.g)+ - _SQR(pixelData[i].c.b-p[bestmatch].c.b))) - ); + printf( + "discrepancy in matching algorithms pixel %d [%d %d] %f %f\n", + i, + qp[i], + bestmatch, + sqrt((double)(_SQR(pixelData[i].c.r - p[qp[i]].c.r) + + _SQR(pixelData[i].c.g - p[qp[i]].c.g) + + _SQR(pixelData[i].c.b - p[qp[i]].c.b))), + sqrt((double)(_SQR(pixelData[i].c.r - p[bestmatch].c.r) + + _SQR(pixelData[i].c.g - p[bestmatch].c.g) + + _SQR(pixelData[i].c.b - p[bestmatch].c.b)))); } } hashtable_free(h2); diff --git a/src/libImaging/QuantOctree.c b/src/libImaging/QuantOctree.c index 5e79bce35..1331a30ad 100644 --- a/src/libImaging/QuantOctree.c +++ b/src/libImaging/QuantOctree.c @@ -38,7 +38,7 @@ typedef struct _ColorBucket { uint64_t g; uint64_t b; uint64_t a; -} * ColorBucket; +} *ColorBucket; typedef struct _ColorCube { unsigned int rBits, gBits, bBits, aBits; @@ -47,7 +47,7 @@ typedef struct _ColorCube { unsigned long size; ColorBucket buckets; -} * ColorCube; +} *ColorCube; #define MAX(a, b) (a) > (b) ? (a) : (b) diff --git a/src/libImaging/Reduce.c b/src/libImaging/Reduce.c index 60928d2bc..61566f0c5 100644 --- a/src/libImaging/Reduce.c +++ b/src/libImaging/Reduce.c @@ -2,7 +2,7 @@ #include -#define ROUND_UP(f) ((int)((f) >= 0.0 ? (f) + 0.5F : (f)-0.5F)) +#define ROUND_UP(f) ((int)((f) >= 0.0 ? (f) + 0.5F : (f) - 0.5F)) UINT32 division_UINT32(int divider, int result_bits) { diff --git a/src/libImaging/Resample.c b/src/libImaging/Resample.c index cf79d8a4e..59c27b3f4 100644 --- a/src/libImaging/Resample.c +++ b/src/libImaging/Resample.c @@ -2,7 +2,7 @@ #include -#define ROUND_UP(f) ((int)((f) >= 0.0 ? (f) + 0.5F : (f)-0.5F)) +#define ROUND_UP(f) ((int)((f) >= 0.0 ? (f) + 0.5F : (f) - 0.5F)) struct filter { double (*filter)(double x); diff --git a/src/libImaging/SgiRleDecode.c b/src/libImaging/SgiRleDecode.c index 4eef44ba5..89dedb525 100644 --- a/src/libImaging/SgiRleDecode.c +++ b/src/libImaging/SgiRleDecode.c @@ -113,7 +113,8 @@ expandrow(UINT8 *dest, UINT8 *src, int n, int z, int xsize, UINT8 *end_of_buffer } static int -expandrow2(UINT8 *dest, const UINT8 *src, int n, int z, int xsize, UINT8 *end_of_buffer) { +expandrow2( + UINT8 *dest, const UINT8 *src, int n, int z, int xsize, UINT8 *end_of_buffer) { UINT8 pixel, count; int x = 0; @@ -197,7 +198,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t return -1; } - /* decoder initialization */ state->count = 0; state->y = 0; @@ -252,7 +252,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t c->rlelength, im->bands, im->xsize, - &ptr[c->bufsize-1]); + &ptr[c->bufsize - 1]); } else { status = expandrow2( &state->buffer[c->channo * 2], @@ -260,7 +260,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t c->rlelength, im->bands, im->xsize, - &ptr[c->bufsize-1]); + &ptr[c->bufsize - 1]); } if (status == -1) { state->errcode = IMAGING_CODEC_OVERRUN; @@ -268,7 +268,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t } else if (status == 1) { goto sgi_finish_decode; } - } /* store decompressed data in image */ diff --git a/src/libImaging/Storage.c b/src/libImaging/Storage.c index b1b03c515..b27195a35 100644 --- a/src/libImaging/Storage.c +++ b/src/libImaging/Storage.c @@ -418,9 +418,8 @@ ImagingAllocateArray(Imaging im, int dirty, int block_size) { } im->blocks[current_block] = block; /* Bulletproof code from libc _int_memalign */ - aligned_ptr = (char *)( - ((size_t) (block.ptr + arena->alignment - 1)) & - -((Py_ssize_t) arena->alignment)); + aligned_ptr = (char *)(((size_t)(block.ptr + arena->alignment - 1)) & + -((Py_ssize_t)arena->alignment)); } im->image[y] = aligned_ptr + aligned_linesize * line_in_block; diff --git a/src/libImaging/TiffDecode.c b/src/libImaging/TiffDecode.c index e3b81590e..abffdeabc 100644 --- a/src/libImaging/TiffDecode.c +++ b/src/libImaging/TiffDecode.c @@ -60,7 +60,11 @@ _tiffReadProc(thandle_t hdata, tdata_t buf, tsize_t size) { dump_state(state); if (state->loc > state->eof) { - TIFFError("_tiffReadProc", "Invalid Read at loc %" PRIu64 ", eof: %" PRIu64, state->loc, state->eof); + TIFFError( + "_tiffReadProc", + "Invalid Read at loc %" PRIu64 ", eof: %" PRIu64, + state->loc, + state->eof); return 0; } to_read = min(size, min(state->size, (tsize_t)state->eof) - (tsize_t)state->loc); @@ -217,7 +221,12 @@ ImagingLibTiffInit(ImagingCodecState state, int fp, uint32_t offset) { } int -_pickUnpackers(Imaging im, ImagingCodecState state, TIFF *tiff, uint16_t planarconfig, ImagingShuffler *unpackers) { +_pickUnpackers( + Imaging im, + ImagingCodecState state, + TIFF *tiff, + uint16_t planarconfig, + ImagingShuffler *unpackers) { // if number of bands is 1, there is no difference with contig case if (planarconfig == PLANARCONFIG_SEPARATE && im->bands > 1) { uint16_t bits_per_sample = 8; @@ -232,10 +241,14 @@ _pickUnpackers(Imaging im, ImagingCodecState state, TIFF *tiff, uint16_t planarc // We'll pick appropriate set of unpackers depending on planar_configuration // It does not matter if data is RGB(A), CMYK or LUV really, // we just copy it plane by plane - unpackers[0] = ImagingFindUnpacker("RGBA", bits_per_sample == 16 ? "R;16N" : "R", NULL); - unpackers[1] = ImagingFindUnpacker("RGBA", bits_per_sample == 16 ? "G;16N" : "G", NULL); - unpackers[2] = ImagingFindUnpacker("RGBA", bits_per_sample == 16 ? "B;16N" : "B", NULL); - unpackers[3] = ImagingFindUnpacker("RGBA", bits_per_sample == 16 ? "A;16N" : "A", NULL); + unpackers[0] = + ImagingFindUnpacker("RGBA", bits_per_sample == 16 ? "R;16N" : "R", NULL); + unpackers[1] = + ImagingFindUnpacker("RGBA", bits_per_sample == 16 ? "G;16N" : "G", NULL); + unpackers[2] = + ImagingFindUnpacker("RGBA", bits_per_sample == 16 ? "B;16N" : "B", NULL); + unpackers[3] = + ImagingFindUnpacker("RGBA", bits_per_sample == 16 ? "A;16N" : "A", NULL); return im->bands; } else { @@ -247,10 +260,10 @@ _pickUnpackers(Imaging im, ImagingCodecState state, TIFF *tiff, uint16_t planarc int _decodeAsRGBA(Imaging im, ImagingCodecState state, TIFF *tiff) { - // To avoid dealing with YCbCr subsampling and other complications, let libtiff handle it - // Use a TIFFRGBAImage wrapping the tiff image, and let libtiff handle - // all of the conversion. Metadata read from the TIFFRGBAImage could - // be different from the metadata that the base tiff returns. + // To avoid dealing with YCbCr subsampling and other complications, let libtiff + // handle it Use a TIFFRGBAImage wrapping the tiff image, and let libtiff handle all + // of the conversion. Metadata read from the TIFFRGBAImage could be different from + // the metadata that the base tiff returns. INT32 current_row; UINT8 *new_data; @@ -259,17 +272,16 @@ _decodeAsRGBA(Imaging im, ImagingCodecState state, TIFF *tiff) { TIFFRGBAImage img; char emsg[1024] = ""; - // Since using TIFFRGBAImage* functions, we can read whole tiff into rastrr in one call - // Let's select smaller block size. Multiplying image width by (tile length OR rows per strip) - // gives us manageable block size in pixels + // Since using TIFFRGBAImage* functions, we can read whole tiff into rastrr in one + // call Let's select smaller block size. Multiplying image width by (tile length OR + // rows per strip) gives us manageable block size in pixels if (TIFFIsTiled(tiff)) { ret = TIFFGetFieldDefaulted(tiff, TIFFTAG_TILELENGTH, &rows_per_block); - } - else { + } else { ret = TIFFGetFieldDefaulted(tiff, TIFFTAG_ROWSPERSTRIP, &rows_per_block); } - if (ret != 1 || rows_per_block==(UINT32)(-1)) { + if (ret != 1 || rows_per_block == (UINT32)(-1)) { rows_per_block = state->ysize; } @@ -357,7 +369,12 @@ decodergba_err: } int -_decodeTile(Imaging im, ImagingCodecState state, TIFF *tiff, int planes, ImagingShuffler *unpackers) { +_decodeTile( + Imaging im, + ImagingCodecState state, + TIFF *tiff, + int planes, + ImagingShuffler *unpackers) { INT32 x, y, tile_y, current_tile_length, current_tile_width; UINT32 tile_width, tile_length; tsize_t tile_bytes_size, row_byte_size; @@ -396,8 +413,8 @@ _decodeTile(Imaging im, ImagingCodecState state, TIFF *tiff, int planes, Imaging if (tile_bytes_size > ((tile_length * state->bits / planes + 7) / 8) * tile_width) { // If the tile size as expected by LibTiff isn't what we're expecting, abort. - // man: TIFFTileSize returns the equivalent size for a tile of data as it would be returned in a - // call to TIFFReadTile ... + // man: TIFFTileSize returns the equivalent size for a tile of data as it + // would be returned in a call to TIFFReadTile ... state->errcode = IMAGING_CODEC_BROKEN; return -1; } @@ -428,19 +445,24 @@ _decodeTile(Imaging im, ImagingCodecState state, TIFF *tiff, int planes, Imaging TRACE(("Read tile at %dx%d; \n\n", x, y)); - current_tile_width = min((INT32) tile_width, state->xsize - x); - current_tile_length = min((INT32) tile_length, state->ysize - y); + current_tile_width = min((INT32)tile_width, state->xsize - x); + current_tile_length = min((INT32)tile_length, state->ysize - y); // iterate over each line in the tile and stuff data into image for (tile_y = 0; tile_y < current_tile_length; tile_y++) { - TRACE(("Writing tile data at %dx%d using tile_width: %d; \n", tile_y + y, x, current_tile_width)); + TRACE( + ("Writing tile data at %dx%d using tile_width: %d; \n", + tile_y + y, + x, + current_tile_width)); // UINT8 * bbb = state->buffer + tile_y * row_byte_size; - // TRACE(("chars: %x%x%x%x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3])); + // TRACE(("chars: %x%x%x%x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], + // ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3])); - shuffler((UINT8*) im->image[tile_y + y] + x * im->pixelsize, - state->buffer + tile_y * row_byte_size, - current_tile_width - ); + shuffler( + (UINT8 *)im->image[tile_y + y] + x * im->pixelsize, + state->buffer + tile_y * row_byte_size, + current_tile_width); } } } @@ -450,7 +472,12 @@ _decodeTile(Imaging im, ImagingCodecState state, TIFF *tiff, int planes, Imaging } int -_decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff, int planes, ImagingShuffler *unpackers) { +_decodeStrip( + Imaging im, + ImagingCodecState state, + TIFF *tiff, + int planes, + ImagingShuffler *unpackers) { INT32 strip_row = 0; UINT8 *new_data; UINT32 rows_per_strip; @@ -458,7 +485,7 @@ _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff, int planes, Imagin tsize_t strip_size, row_byte_size, unpacker_row_byte_size; ret = TIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &rows_per_strip); - if (ret != 1 || rows_per_strip==(UINT32)(-1)) { + if (ret != 1 || rows_per_strip == (UINT32)(-1)) { rows_per_strip = state->ysize; } @@ -478,8 +505,8 @@ _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff, int planes, Imagin unpacker_row_byte_size = (state->xsize * state->bits / planes + 7) / 8; if (strip_size > (unpacker_row_byte_size * rows_per_strip)) { // If the strip size as expected by LibTiff isn't what we're expecting, abort. - // man: TIFFStripSize returns the equivalent size for a strip of data as it would be returned in a - // call to TIFFReadEncodedStrip ... + // man: TIFFStripSize returns the equivalent size for a strip of data as it + // would be returned in a call to TIFFReadEncodedStrip ... state->errcode = IMAGING_CODEC_BROKEN; return -1; } @@ -513,8 +540,13 @@ _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff, int planes, Imagin int plane; for (plane = 0; plane < planes; plane++) { ImagingShuffler shuffler = unpackers[plane]; - if (TIFFReadEncodedStrip(tiff, TIFFComputeStrip(tiff, state->y, plane), (tdata_t)state->buffer, strip_size) == -1) { - TRACE(("Decode Error, strip %d\n", TIFFComputeStrip(tiff, state->y, 0))); + if (TIFFReadEncodedStrip( + tiff, + TIFFComputeStrip(tiff, state->y, plane), + (tdata_t)state->buffer, + strip_size) == -1) { + TRACE( + ("Decode Error, strip %d\n", TIFFComputeStrip(tiff, state->y, 0))); state->errcode = IMAGING_CODEC_BROKEN; return -1; } @@ -523,16 +555,17 @@ _decodeStrip(Imaging im, ImagingCodecState state, TIFF *tiff, int planes, Imagin // iterate over each row in the strip and stuff data into image for (strip_row = 0; - strip_row < min((INT32) rows_per_strip, state->ysize - state->y); + strip_row < min((INT32)rows_per_strip, state->ysize - state->y); strip_row++) { TRACE(("Writing data into line %d ; \n", state->y + strip_row)); - // UINT8 * bbb = state->buffer + strip_row * (state->bytes / rows_per_strip); - // TRACE(("chars: %x %x %x %x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3])); + // UINT8 * bbb = state->buffer + strip_row * (state->bytes / + // rows_per_strip); TRACE(("chars: %x %x %x %x\n", ((UINT8 *)bbb)[0], + // ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3])); shuffler( - (UINT8*) im->image[state->y + state->yoff + strip_row] + - state->xoff * im->pixelsize, + (UINT8 *)im->image[state->y + state->yoff + strip_row] + + state->xoff * im->pixelsize, state->buffer + strip_row * row_byte_size, state->xsize); } @@ -666,7 +699,6 @@ ImagingLibTiffDecode( goto decode_err; } - TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric); TIFFGetField(tiff, TIFFTAG_COMPRESSION, &compression); TIFFGetFieldDefaulted(tiff, TIFFTAG_PLANARCONFIG, &planarconfig); @@ -675,16 +707,17 @@ ImagingLibTiffDecode( // Let LibTiff read them as RGBA readAsRGBA = photometric == PHOTOMETRIC_YCBCR; - if (readAsRGBA && compression == COMPRESSION_JPEG && planarconfig == PLANARCONFIG_CONTIG) { - // If using new JPEG compression, let libjpeg do RGB conversion for performance reasons + if (readAsRGBA && compression == COMPRESSION_JPEG && + planarconfig == PLANARCONFIG_CONTIG) { + // If using new JPEG compression, let libjpeg do RGB conversion for performance + // reasons TIFFSetField(tiff, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); readAsRGBA = 0; } if (readAsRGBA) { _decodeAsRGBA(im, state, tiff); - } - else { + } else { planes = _pickUnpackers(im, state, tiff, planarconfig, unpackers); if (planes <= 0) { goto decode_err; @@ -692,8 +725,7 @@ ImagingLibTiffDecode( if (TIFFIsTiled(tiff)) { _decodeTile(im, state, tiff, planes, unpackers); - } - else { + } else { _decodeStrip(im, state, tiff, planes, unpackers); } @@ -702,20 +734,20 @@ ImagingLibTiffDecode( // so we have to convert it to RGBA if (planes > 3 && strcmp(im->mode, "RGBA") == 0) { uint16_t extrasamples; - uint16_t* sampleinfo; + uint16_t *sampleinfo; ImagingShuffler shuffle; INT32 y; - TIFFGetFieldDefaulted(tiff, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); + TIFFGetFieldDefaulted( + tiff, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); - if (extrasamples >= 1 && - (sampleinfo[0] == EXTRASAMPLE_UNSPECIFIED || sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA) - ) { + if (extrasamples >= 1 && (sampleinfo[0] == EXTRASAMPLE_UNSPECIFIED || + sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA)) { shuffle = ImagingFindUnpacker("RGBA", "RGBa", NULL); for (y = state->yoff; y < state->ysize; y++) { - UINT8* ptr = (UINT8*) im->image[y + state->yoff] + - state->xoff * im->pixelsize; + UINT8 *ptr = (UINT8 *)im->image[y + state->yoff] + + state->xoff * im->pixelsize; shuffle(ptr, ptr, state->xsize); } } @@ -723,7 +755,7 @@ ImagingLibTiffDecode( } } - decode_err: +decode_err: // TIFFClose in libtiff calls tif_closeproc and TIFFCleanup if (clientstate->fp) { // Pillow will manage the closing of the file rather than libtiff @@ -973,7 +1005,8 @@ ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8 *buffer, int byt } if (state->state == 1 && !clientstate->fp) { - int read = (int)_tiffReadProc(clientstate, (tdata_t)buffer, (tsize_t)bytes); + int read = + (int)_tiffReadProc((thandle_t)clientstate, (tdata_t)buffer, (tsize_t)bytes); TRACE( ("Buffer: %p: %c%c%c%c\n", buffer, diff --git a/src/libImaging/TiffDecode.h b/src/libImaging/TiffDecode.h index 02454ba03..212b7dee6 100644 --- a/src/libImaging/TiffDecode.h +++ b/src/libImaging/TiffDecode.h @@ -30,7 +30,7 @@ typedef struct { * Should be uint32 for libtiff 3.9.x * uint64 for libtiff 4.0.x */ - TIFF *tiff; /* Used in write */ + TIFF *tiff; /* Used in write */ toff_t eof; int flrealloc; /* may we realloc */ } TIFFSTATE; diff --git a/src/libImaging/Unpack.c b/src/libImaging/Unpack.c index e351aa2f1..1b84cd68f 100644 --- a/src/libImaging/Unpack.c +++ b/src/libImaging/Unpack.c @@ -1437,90 +1437,90 @@ band3I(UINT8 *out, const UINT8 *in, int pixels) { } static void -band016B(UINT8* out, const UINT8* in, int pixels) -{ +band016B(UINT8 *out, const UINT8 *in, int pixels) { int i; /* band 0 only, big endian */ for (i = 0; i < pixels; i++) { out[0] = in[0]; - out += 4; in += 2; + out += 4; + in += 2; } } static void -band116B(UINT8* out, const UINT8* in, int pixels) -{ +band116B(UINT8 *out, const UINT8 *in, int pixels) { int i; /* band 1 only, big endian */ for (i = 0; i < pixels; i++) { out[1] = in[0]; - out += 4; in += 2; + out += 4; + in += 2; } } static void -band216B(UINT8* out, const UINT8* in, int pixels) -{ +band216B(UINT8 *out, const UINT8 *in, int pixels) { int i; /* band 2 only, big endian */ for (i = 0; i < pixels; i++) { out[2] = in[0]; - out += 4; in += 2; + out += 4; + in += 2; } } static void -band316B(UINT8* out, const UINT8* in, int pixels) -{ +band316B(UINT8 *out, const UINT8 *in, int pixels) { int i; /* band 3 only, big endian */ for (i = 0; i < pixels; i++) { out[3] = in[0]; - out += 4; in += 2; + out += 4; + in += 2; } } static void -band016L(UINT8* out, const UINT8* in, int pixels) -{ +band016L(UINT8 *out, const UINT8 *in, int pixels) { int i; /* band 0 only, little endian */ for (i = 0; i < pixels; i++) { out[0] = in[1]; - out += 4; in += 2; + out += 4; + in += 2; } } static void -band116L(UINT8* out, const UINT8* in, int pixels) -{ +band116L(UINT8 *out, const UINT8 *in, int pixels) { int i; /* band 1 only, little endian */ for (i = 0; i < pixels; i++) { out[1] = in[1]; - out += 4; in += 2; + out += 4; + in += 2; } } static void -band216L(UINT8* out, const UINT8* in, int pixels) -{ +band216L(UINT8 *out, const UINT8 *in, int pixels) { int i; /* band 2 only, little endian */ for (i = 0; i < pixels; i++) { out[2] = in[1]; - out += 4; in += 2; + out += 4; + in += 2; } } static void -band316L(UINT8* out, const UINT8* in, int pixels) -{ +band316L(UINT8 *out, const UINT8 *in, int pixels) { int i; /* band 3 only, little endian */ for (i = 0; i < pixels; i++) { out[3] = in[1]; - out += 4; in += 2; + out += 4; + in += 2; } } @@ -1687,7 +1687,6 @@ static struct { {"RGB", "G;16N", 16, band116L}, {"RGB", "B;16N", 16, band216L}, - {"RGBA", "R;16N", 16, band016L}, {"RGBA", "G;16N", 16, band116L}, {"RGBA", "B;16N", 16, band216L}, diff --git a/src/path.c b/src/path.c index cc0698c4d..6bc90abed 100644 --- a/src/path.c +++ b/src/path.c @@ -162,24 +162,24 @@ PyPath_Flatten(PyObject *data, double **pxy) { return -1; } -#define assign_item_to_array(op, decref) \ -if (PyFloat_Check(op)) { \ - xy[j++] = PyFloat_AS_DOUBLE(op); \ -} else if (PyLong_Check(op)) { \ - xy[j++] = (float)PyLong_AS_LONG(op); \ -} else if (PyNumber_Check(op)) { \ - xy[j++] = PyFloat_AsDouble(op); \ -} else if (PyArg_ParseTuple(op, "dd", &x, &y)) { \ - xy[j++] = x; \ - xy[j++] = y; \ -} else { \ - PyErr_SetString(PyExc_ValueError, "incorrect coordinate type"); \ - if (decref) { \ - Py_DECREF(op); \ - } \ - free(xy); \ - return -1; \ -} +#define assign_item_to_array(op, decref) \ + if (PyFloat_Check(op)) { \ + xy[j++] = PyFloat_AS_DOUBLE(op); \ + } else if (PyLong_Check(op)) { \ + xy[j++] = (float)PyLong_AS_LONG(op); \ + } else if (PyNumber_Check(op)) { \ + xy[j++] = PyFloat_AsDouble(op); \ + } else if (PyArg_ParseTuple(op, "dd", &x, &y)) { \ + xy[j++] = x; \ + xy[j++] = y; \ + } else { \ + PyErr_SetString(PyExc_ValueError, "incorrect coordinate type"); \ + if (decref) { \ + Py_DECREF(op); \ + } \ + free(xy); \ + return -1; \ + } /* Copy table to path array */ if (PyList_Check(data)) {