Skip to content

Commit 0d72994

Browse files
committed
Handle packets that cross scan lines
1 parent 17d342b commit 0d72994

File tree

4 files changed

+43
-15
lines changed

4 files changed

+43
-15
lines changed

Tests/images/cross_scan_line.png

71 Bytes
Loading

Tests/images/cross_scan_line.tga

49 Bytes
Binary file not shown.

Tests/test_file_tga.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ def test_id_field_rle():
9797
assert im.size == (199, 199)
9898

9999

100+
def test_cross_scan_line():
101+
with Image.open("Tests/images/cross_scan_line.tga") as im:
102+
assert_image_equal_tofile(im, "Tests/images/cross_scan_line.png")
103+
104+
100105
def test_save(tmp_path):
101106
test_file = "Tests/images/tga_id_field.tga"
102107
with Image.open(test_file) as im:

src/libImaging/TgaRleDecode.c

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ int
2020
ImagingTgaRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t bytes) {
2121
int n, depth;
2222
UINT8 *ptr;
23+
UINT8 extra_data = 0;
24+
int extra_bytes = 0;
2325

2426
ptr = buf;
2527

@@ -72,8 +74,10 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t
7274
}
7375

7476
if (state->x + n > state->bytes) {
75-
state->errcode = IMAGING_CODEC_OVERRUN;
76-
return -1;
77+
extra_bytes = n; /* full value */
78+
n = state->bytes - state->x;
79+
extra_bytes -= n;
80+
extra_data = ptr[1];
7781
}
7882

7983
memcpy(state->buffer + state->x, ptr + 1, n);
@@ -82,24 +86,43 @@ ImagingTgaRleDecode(Imaging im, ImagingCodecState state, UINT8 *buf, Py_ssize_t
8286
bytes -= 1 + n;
8387
}
8488

85-
state->x += n;
89+
for (;;) {
90+
state->x += n;
8691

87-
if (state->x >= state->bytes) {
88-
/* Got a full line, unpack it */
89-
state->shuffle(
90-
(UINT8 *)im->image[state->y + state->yoff] +
91-
state->xoff * im->pixelsize,
92-
state->buffer,
93-
state->xsize);
92+
if (state->x >= state->bytes) {
93+
/* Got a full line, unpack it */
94+
state->shuffle(
95+
(UINT8 *)im->image[state->y + state->yoff] +
96+
state->xoff * im->pixelsize,
97+
state->buffer,
98+
state->xsize);
9499

95-
state->x = 0;
100+
state->x = 0;
96101

97-
state->y += state->ystep;
102+
state->y += state->ystep;
98103

99-
if (state->y < 0 || state->y >= state->ysize) {
100-
/* End of file (errcode = 0) */
101-
return -1;
104+
if (state->y < 0 || state->y >= state->ysize) {
105+
/* End of file (errcode = 0) */
106+
return -1;
107+
}
108+
}
109+
110+
if (extra_bytes == 0) {
111+
break;
112+
}
113+
114+
if (state->x > 0) {
115+
break; // assert
116+
}
117+
118+
if (extra_bytes >= state->bytes) {
119+
n = state->bytes;
120+
} else {
121+
n = extra_bytes;
102122
}
123+
memcpy(state->buffer + state->x, ptr, n);
124+
ptr += n;
125+
extra_bytes -= n;
103126
}
104127
}
105128

0 commit comments

Comments
 (0)