Skip to content

Commit a01c293

Browse files
authored
Merge branch 'main' into avif_gray
2 parents 8031782 + ef6951d commit a01c293

16 files changed

Lines changed: 137 additions & 40 deletions

.github/workflows/wheels-dependencies.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ ARCHIVE_SDIR=pillow-depends-main
9292
# Package versions for fresh source builds.
9393
FREETYPE_VERSION=2.14.3
9494
HARFBUZZ_VERSION=13.2.1
95-
LIBPNG_VERSION=1.6.55
95+
LIBPNG_VERSION=1.6.56
9696
JPEGTURBO_VERSION=3.1.3
9797
OPENJPEG_VERSION=2.5.4
9898
XZ_VERSION=5.8.2

Tests/test_file_jpeg2k.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,13 @@ def test_pclr() -> None:
456456
assert len(im.palette.colors) == 256
457457
assert im.palette.colors[(255, 255, 255)] == 0
458458

459+
for enumcs in (0, 15, 17):
460+
with open(f"{EXTRA_DIR}/issue104_jpxstream.jp2", "rb") as fp:
461+
data = bytearray(fp.read())
462+
data[114:115] = bytes([enumcs])
463+
with Image.open(BytesIO(data)) as im:
464+
assert im.mode == "L"
465+
459466
with Image.open(
460467
f"{EXTRA_DIR}/147af3f1083de4393666b7d99b01b58b_signal_sigsegv_130c531_6155_5136.jp2"
461468
) as im:

Tests/test_file_tga.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from __future__ import annotations
22

33
import os
4+
from io import BytesIO
45
from pathlib import Path
56

67
import pytest
78

8-
from PIL import Image, UnidentifiedImageError
9+
from PIL import Image, UnidentifiedImageError, _binary
910

1011
from .helper import assert_image_equal, assert_image_equal_tofile, hopper
1112

@@ -92,6 +93,25 @@ def test_rgba_16() -> None:
9293
assert im.getpixel((1, 0)) == (0, 255, 82, 0)
9394

9495

96+
def test_v2_no_alpha() -> None:
97+
test_file = "Tests/images/tga/common/200x32_rgba_tl_rle.tga"
98+
with open(test_file, "rb") as fp:
99+
data = fp.read()
100+
data += (
101+
b"\x00" * 495
102+
+ _binary.o32le(len(data))
103+
+ _binary.o32le(0)
104+
+ b"TRUEVISION-XFILE.\x00"
105+
)
106+
with Image.open(BytesIO(data)) as im:
107+
with Image.open(test_file) as im2:
108+
r, g, b = im2.split()[:3]
109+
a = Image.new("L", im2.size, 255)
110+
expected = Image.merge("RGBA", (r, g, b, a))
111+
112+
assert_image_equal(im, expected)
113+
114+
95115
def test_id_field() -> None:
96116
# tga file with id field
97117
test_file = "Tests/images/tga_id_field.tga"

depends/download-and-extract.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ archive=$1
55
url=$2
66

77
if [ ! -f $archive.tar.gz ]; then
8-
wget --no-verbose -O $archive.tar.gz $url
8+
wget -O $archive.tar.gz $url \
9+
--no-verbose \
10+
--retry-connrefused \
11+
--retry-on-http-error=429,503,504
912
fi
1013

1114
rmdir $archive

src/PIL/Jpeg2KImagePlugin.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ def _parse_jp2_header(
176176
nc = None
177177
dpi = None # 2-tuple of DPI info, or None
178178
palette = None
179-
cmyk = False
179+
colr = None
180180

181181
while header.has_next_box():
182182
tbox = header.next_box_type()
@@ -199,10 +199,16 @@ def _parse_jp2_header(
199199
mode = "RGBA"
200200
elif tbox == b"colr":
201201
meth, _, _, enumcs = header.read_fields(">BBBI")
202-
if cmyk := (meth == 1 and enumcs == 12):
203-
if nc == 4:
204-
mode = "CMYK"
205-
elif tbox == b"pclr" and mode in ("L", "LA"):
202+
if meth == 1:
203+
if enumcs in (0, 15):
204+
colr = "1"
205+
elif enumcs == 12:
206+
colr = "CMYK"
207+
if nc == 4:
208+
mode = "CMYK"
209+
elif enumcs == 17:
210+
colr = "L"
211+
elif tbox == b"pclr" and mode in ("L", "LA") and colr not in ("1", "L"):
206212
ne, npc = header.read_fields(">HB")
207213
assert isinstance(ne, int)
208214
assert isinstance(npc, int)
@@ -213,7 +219,7 @@ def _parse_jp2_header(
213219
max_bitdepth = bitdepth
214220
if max_bitdepth <= 8:
215221
if npc == 4:
216-
palette_mode = "CMYK" if cmyk else "RGBA"
222+
palette_mode = "CMYK" if colr == "CMYK" else "RGBA"
217223
else:
218224
palette_mode = "RGB"
219225
palette = ImagePalette.ImagePalette(palette_mode)

src/PIL/TgaImagePlugin.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
#
1818
from __future__ import annotations
1919

20+
import os
2021
import warnings
2122
from typing import IO
2223

2324
from . import Image, ImageFile, ImagePalette
2425
from ._binary import i16le as i16
26+
from ._binary import i32le as i32
2527
from ._binary import o8
2628
from ._binary import o16le as o16
2729

@@ -157,6 +159,20 @@ def _open(self) -> None:
157159
pass # cannot decode
158160

159161
def load_end(self) -> None:
162+
if self.mode == "RGBA":
163+
assert self.fp is not None
164+
self.fp.seek(-26, os.SEEK_END)
165+
footer = self.fp.read(26)
166+
if footer.endswith(b"TRUEVISION-XFILE.\x00"):
167+
# version 2
168+
extension_offset = i32(footer)
169+
if extension_offset:
170+
self.fp.seek(extension_offset + 494)
171+
attributes_type = self.fp.read(1)
172+
if attributes_type == b"\x00":
173+
# No alpha
174+
self.im.fillband(3, 255)
175+
160176
if self._flip_horizontally:
161177
self.im = self.im.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
162178

src/_avif.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -425,15 +425,15 @@ AvifEncoderNew(PyObject *self_, PyObject *args) {
425425
return (PyObject *)self;
426426
}
427427

428-
PyObject *
428+
void
429429
_encoder_dealloc(AvifEncoderObject *self) {
430430
if (self->encoder) {
431431
avifEncoderDestroy(self->encoder);
432432
}
433433
if (self->image) {
434434
avifImageDestroy(self->image);
435435
}
436-
Py_RETURN_NONE;
436+
Py_TYPE(self)->tp_free(self);
437437
}
438438

439439
PyObject *
@@ -691,13 +691,13 @@ AvifDecoderNew(PyObject *self_, PyObject *args) {
691691
return (PyObject *)self;
692692
}
693693

694-
PyObject *
694+
void
695695
_decoder_dealloc(AvifDecoderObject *self) {
696696
if (self->decoder) {
697697
avifDecoderDestroy(self->decoder);
698698
}
699699
PyBuffer_Release(&self->buffer);
700-
Py_RETURN_NONE;
700+
Py_TYPE(self)->tp_free(self);
701701
}
702702

703703
PyObject *

src/_imaging.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4324,17 +4324,19 @@ setup_module(PyObject *m) {
43244324
#else
43254325
have_libjpegturbo = Py_False;
43264326
#endif
4327-
Py_INCREF(have_libjpegturbo);
4328-
PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", have_libjpegturbo);
4327+
if (PyModule_AddObjectRef(m, "HAVE_LIBJPEGTURBO", have_libjpegturbo) < 0) {
4328+
return -1;
4329+
}
43294330

43304331
PyObject *have_mozjpeg;
43314332
#ifdef JPEG_C_PARAM_SUPPORTED
43324333
have_mozjpeg = Py_True;
43334334
#else
43344335
have_mozjpeg = Py_False;
43354336
#endif
4336-
Py_INCREF(have_mozjpeg);
4337-
PyModule_AddObject(m, "HAVE_MOZJPEG", have_mozjpeg);
4337+
if (PyModule_AddObjectRef(m, "HAVE_MOZJPEG", have_mozjpeg) < 0) {
4338+
return -1;
4339+
}
43384340

43394341
PyObject *have_libimagequant;
43404342
#ifdef HAVE_LIBIMAGEQUANT
@@ -4348,8 +4350,9 @@ setup_module(PyObject *m) {
43484350
#else
43494351
have_libimagequant = Py_False;
43504352
#endif
4351-
Py_INCREF(have_libimagequant);
4352-
PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", have_libimagequant);
4353+
if (PyModule_AddObjectRef(m, "HAVE_LIBIMAGEQUANT", have_libimagequant) < 0) {
4354+
return -1;
4355+
}
43534356

43544357
#ifdef HAVE_LIBZ
43554358
/* zip encoding strategies */
@@ -4377,8 +4380,9 @@ setup_module(PyObject *m) {
43774380
#else
43784381
have_zlibng = Py_False;
43794382
#endif
4380-
Py_INCREF(have_zlibng);
4381-
PyModule_AddObject(m, "HAVE_ZLIBNG", have_zlibng);
4383+
if (PyModule_AddObjectRef(m, "HAVE_ZLIBNG", have_zlibng) < 0) {
4384+
return -1;
4385+
}
43824386

43834387
#ifdef HAVE_LIBTIFF
43844388
{
@@ -4395,8 +4399,9 @@ setup_module(PyObject *m) {
43954399
#else
43964400
have_xcb = Py_False;
43974401
#endif
4398-
Py_INCREF(have_xcb);
4399-
PyModule_AddObject(m, "HAVE_XCB", have_xcb);
4402+
if (PyModule_AddObjectRef(m, "HAVE_XCB", have_xcb) < 0) {
4403+
return -1;
4404+
}
44004405

44014406
PyObject *pillow_version = PyUnicode_FromString(version);
44024407
PyDict_SetItemString(

src/_imagingcms.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,14 +1447,14 @@ setup_module(PyObject *m) {
14471447
int vn;
14481448

14491449
/* Ready object types */
1450-
PyType_Ready(&CmsProfile_Type);
1451-
PyType_Ready(&CmsTransform_Type);
1452-
1453-
Py_INCREF(&CmsProfile_Type);
1454-
PyModule_AddObject(m, "CmsProfile", (PyObject *)&CmsProfile_Type);
1450+
if (PyType_Ready(&CmsProfile_Type) < 0 || PyType_Ready(&CmsTransform_Type) < 0) {
1451+
return -1;
1452+
}
14551453

1456-
Py_INCREF(&CmsTransform_Type);
1457-
PyModule_AddObject(m, "CmsTransform", (PyObject *)&CmsTransform_Type);
1454+
if (PyModule_AddObjectRef(m, "CmsProfile", (PyObject *)&CmsProfile_Type) < 0 ||
1455+
PyModule_AddObjectRef(m, "CmsTransform", (PyObject *)&CmsTransform_Type) < 0) {
1456+
return -1;
1457+
}
14581458

14591459
d = PyModule_GetDict(m);
14601460

src/_imagingft.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,9 @@ setup_module(PyObject *m) {
15451545
d = PyModule_GetDict(m);
15461546

15471547
/* Ready object type */
1548-
PyType_Ready(&Font_Type);
1548+
if (PyType_Ready(&Font_Type) < 0) {
1549+
return -1;
1550+
}
15491551

15501552
if (FT_Init_FreeType(&library)) {
15511553
return 0; /* leave it uninitialized */

0 commit comments

Comments
 (0)