Skip to content

Commit 67ffa32

Browse files
authored
Merge branch 'main' into cibuildwheel_delocate
2 parents 27dd70a + af3b904 commit 67ffa32

17 files changed

+173
-84
lines changed

.github/workflows/test-cygwin.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
persist-credentials: false
5353

5454
- name: Install Cygwin
55-
uses: cygwin/cygwin-install-action@v4
55+
uses: cygwin/cygwin-install-action@v5
5656
with:
5757
packages: >
5858
gcc-g++

.github/workflows/wheels-dependencies.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ ARCHIVE_SDIR=pillow-depends-main
3939
# Package versions for fresh source builds
4040
FREETYPE_VERSION=2.13.3
4141
HARFBUZZ_VERSION=10.1.0
42-
LIBPNG_VERSION=1.6.44
42+
LIBPNG_VERSION=1.6.45
4343
JPEGTURBO_VERSION=3.1.0
4444
OPENJPEG_VERSION=2.5.3
4545
XZ_VERSION=5.6.3

.github/workflows/wheels.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ on:
1313
paths:
1414
- ".ci/requirements-cibw.txt"
1515
- ".github/workflows/wheel*"
16+
- "pyproject.toml"
1617
- "setup.py"
1718
- "wheels/*"
1819
- "winbuild/build_prepare.py"
@@ -23,6 +24,7 @@ on:
2324
paths:
2425
- ".ci/requirements-cibw.txt"
2526
- ".github/workflows/wheel*"
27+
- "pyproject.toml"
2628
- "setup.py"
2729
- "wheels/*"
2830
- "winbuild/build_prepare.py"

Tests/test_file_ico.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,7 @@ def test_truncated_mask() -> None:
253253

254254
try:
255255
with Image.open(io.BytesIO(data)) as im:
256-
with Image.open("Tests/images/hopper_mask.png") as expected:
257-
assert im.mode == "1"
256+
assert im.mode == "1"
258257

259258
# 32 bpp
260259
output = io.BytesIO()

Tests/test_file_jpeg.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def test(xdpi: int, ydpi: int | None = None) -> tuple[int, int] | None:
181181
assert test(100, 200) == (100, 200)
182182
assert test(0) is None # square pixels
183183

184-
def test_dpi_jfif_cm(self):
184+
def test_dpi_jfif_cm(self) -> None:
185185
with Image.open("Tests/images/jfif_unit_cm.jpg") as im:
186186
assert im.info["dpi"] == (2.54, 5.08)
187187

@@ -281,7 +281,10 @@ def test_progressive(self) -> None:
281281
assert not im2.info.get("progressive")
282282
assert im3.info.get("progressive")
283283

284-
assert_image_equal(im1, im3)
284+
if features.check_feature("mozjpeg"):
285+
assert_image_similar(im1, im3, 9.39)
286+
else:
287+
assert_image_equal(im1, im3)
285288
assert im1_bytes >= im3_bytes
286289

287290
def test_progressive_large_buffer(self, tmp_path: Path) -> None:
@@ -423,8 +426,12 @@ def test_progressive_compat(self) -> None:
423426

424427
im2 = self.roundtrip(hopper(), progressive=1)
425428
im3 = self.roundtrip(hopper(), progression=1) # compatibility
426-
assert_image_equal(im1, im2)
427-
assert_image_equal(im1, im3)
429+
if features.check_feature("mozjpeg"):
430+
assert_image_similar(im1, im2, 9.39)
431+
assert_image_similar(im1, im3, 9.39)
432+
else:
433+
assert_image_equal(im1, im2)
434+
assert_image_equal(im1, im3)
428435
assert im2.info.get("progressive")
429436
assert im2.info.get("progression")
430437
assert im3.info.get("progressive")
@@ -1030,7 +1037,7 @@ def decode(
10301037

10311038
with Image.open(TEST_FILE) as im:
10321039
im.tile = [
1033-
("INFINITE", (0, 0, 128, 128), 0, ("RGB", 0, 1)),
1040+
ImageFile._Tile("INFINITE", (0, 0, 128, 128), 0, ("RGB", 0, 1)),
10341041
]
10351042
ImageFile.LOAD_TRUNCATED_IMAGES = True
10361043
im.load()

Tests/test_file_libtiff.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1146,7 +1146,7 @@ def test_realloc_overflow(self, monkeypatch: pytest.MonkeyPatch) -> None:
11461146
im.load()
11471147

11481148
# Assert that the error code is IMAGING_CODEC_MEMORY
1149-
assert str(e.value) == "-9"
1149+
assert str(e.value) == "decoder error -9"
11501150

11511151
@pytest.mark.parametrize("compression", ("tiff_adobe_deflate", "jpeg"))
11521152
def test_save_multistrip(self, compression: str, tmp_path: Path) -> None:

Tests/test_file_png.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ def test_textual_chunks_after_idat(self) -> None:
618618
with Image.open("Tests/images/truncated_image.png") as im:
619619
# The file is truncated
620620
with pytest.raises(OSError):
621-
im.text()
621+
im.text
622622
ImageFile.LOAD_TRUNCATED_IMAGES = True
623623
assert isinstance(im.text, dict)
624624
ImageFile.LOAD_TRUNCATED_IMAGES = False

Tests/test_file_spider.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import pytest
99

10-
from PIL import Image, ImageSequence, SpiderImagePlugin
10+
from PIL import Image, SpiderImagePlugin
1111

1212
from .helper import assert_image_equal, hopper, is_pypy
1313

@@ -153,8 +153,8 @@ def test_nonstack_file() -> None:
153153

154154
def test_nonstack_dos() -> None:
155155
with Image.open(TEST_FILE) as im:
156-
for i, frame in enumerate(ImageSequence.Iterator(im)):
157-
assert i <= 1, "Non-stack DOS file test failed"
156+
with pytest.raises(EOFError):
157+
im.seek(0)
158158

159159

160160
# for issue #4093

Tests/test_file_tiff.py

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,16 @@ def test_bigtiff(self, tmp_path: Path) -> None:
117117

118118
def test_bigtiff_save(self, tmp_path: Path) -> None:
119119
outfile = str(tmp_path / "temp.tif")
120-
hopper().save(outfile, big_tiff=True)
120+
im = hopper()
121+
im.save(outfile, big_tiff=True)
121122

122-
with Image.open(outfile) as im:
123-
assert im.tag_v2._bigtiff is True
123+
with Image.open(outfile) as reloaded:
124+
assert reloaded.tag_v2._bigtiff is True
125+
126+
im.save(outfile, save_all=True, append_images=[im], big_tiff=True)
127+
128+
with Image.open(outfile) as reloaded:
129+
assert reloaded.tag_v2._bigtiff is True
124130

125131
def test_seek_too_large(self) -> None:
126132
with pytest.raises(ValueError, match="Unable to seek to frame"):
@@ -740,7 +746,7 @@ def im_generator(ims: list[Image.Image]) -> Generator[Image.Image, None, None]:
740746
assert reread.n_frames == 3
741747

742748
def test_fixoffsets(self) -> None:
743-
b = BytesIO(b"II\x2a\x00\x00\x00\x00\x00")
749+
b = BytesIO(b"II\x2A\x00\x00\x00\x00\x00")
744750
with TiffImagePlugin.AppendingTiffWriter(b) as a:
745751
b.seek(0)
746752
a.fixOffsets(1, isShort=True)
@@ -753,6 +759,37 @@ def test_fixoffsets(self) -> None:
753759
with pytest.raises(RuntimeError):
754760
a.fixOffsets(1)
755761

762+
b = BytesIO(b"II\x2A\x00\x00\x00\x00\x00")
763+
with TiffImagePlugin.AppendingTiffWriter(b) as a:
764+
a.offsetOfNewPage = 2**16
765+
766+
b.seek(0)
767+
a.fixOffsets(1, isShort=True)
768+
769+
b = BytesIO(b"II\x2B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
770+
with TiffImagePlugin.AppendingTiffWriter(b) as a:
771+
a.offsetOfNewPage = 2**32
772+
773+
b.seek(0)
774+
a.fixOffsets(1, isShort=True)
775+
776+
b.seek(0)
777+
a.fixOffsets(1, isLong=True)
778+
779+
def test_appending_tiff_writer_writelong(self) -> None:
780+
data = b"II\x2A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
781+
b = BytesIO(data)
782+
with TiffImagePlugin.AppendingTiffWriter(b) as a:
783+
a.writeLong(2**32 - 1)
784+
assert b.getvalue() == data + b"\xff\xff\xff\xff"
785+
786+
def test_appending_tiff_writer_rewritelastshorttolong(self) -> None:
787+
data = b"II\x2A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
788+
b = BytesIO(data)
789+
with TiffImagePlugin.AppendingTiffWriter(b) as a:
790+
a.rewriteLastShortToLong(2**32 - 1)
791+
assert b.getvalue() == data[:-2] + b"\xff\xff\xff\xff"
792+
756793
def test_saving_icc_profile(self, tmp_path: Path) -> None:
757794
# Tests saving TIFF with icc_profile set.
758795
# At the time of writing this will only work for non-compressed tiffs

src/PIL/BlpImagePlugin.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -374,14 +374,10 @@ def _decode_jpeg_stream(self) -> None:
374374
image = JpegImageFile(BytesIO(data))
375375
Image._decompression_bomb_check(image.size)
376376
if image.mode == "CMYK":
377-
decoder_name, extents, offset, args = image.tile[0]
377+
args = image.tile[0].args
378378
assert isinstance(args, tuple)
379-
image.tile = [
380-
ImageFile._Tile(decoder_name, extents, offset, (args[0], "CMYK"))
381-
]
382-
r, g, b = image.convert("RGB").split()
383-
reversed_image = Image.merge("RGB", (b, g, r))
384-
self.set_as_raw(reversed_image.tobytes())
379+
image.tile = [image.tile[0]._replace(args=(args[0], "CMYK"))]
380+
self.set_as_raw(image.convert("RGB").tobytes(), "BGR")
385381

386382

387383
class BLP2Decoder(_BLPBaseDecoder):

0 commit comments

Comments
 (0)