Skip to content

Fix Sun RLE decoding when rows are padded - #10375

Open
PerryLink wants to merge 1 commit into
python-pillow:mainfrom
PerryLink:fix/sun-rle-padded-rows
Open

PerryLink wants to merge 1 commit into
python-pillow:mainfrom
PerryLink:fix/sun-rle-padded-rows

Conversation

@PerryLink

Copy link
Copy Markdown

Fixes #10370.

What happens

Sun raster stored scanlines are rounded up to 16 bits, and type-2 RLE encodes the padding bytes too. ImagingSunRleDecode advanced rows at the unpadded state->bytes, so whenever a row's pixel data had an odd length the padding byte was written as the first pixel of the next row:

3x2, 8-bit: before [16, 32, 48, 0, 64, 80], after [16, 32, 48, 64, 80, 96]

Fix

  • Compute the padded stride = state->bytes + (state->bytes & 1) and track state->x within the padded row.
  • Write into state->buffer only when x < state->bytes; the padding bytes are consumed but not stored.
  • Emit runs across scanlines, skipping the padding portion of each row. This replaces the old extra_bytes bookkeeping, which could not account for the padded stride.

Tests

Added to Tests/test_file_sun.py:

  • test_rle_padded_row: a literal 3x2 8-bit image with one padding byte per row.
  • test_rle_run_crosses_padded_rows: one run of 8 pixels covering two padded rows.

python -m pytest Tests/test_file_sun.py -q → 8 passed, 2 skipped (the skips need the extra image files, as before).

I also checked the 24-bit marbles.sun sample linked in the issue (1419 px wide): the installed Pillow 13.0.0 and this patch produce identical decoded pixel hashes, so the ImageMagick parity you verified is unchanged.

Prepared with AI assistance; the patch and tests were reviewed and run locally.

Stored scanlines are rounded up to 16 bits and the RLE stream encodes
the padding bytes. The decoder advanced rows at the unpadded
state->bytes, so a padding byte became the first pixel of the next row
whenever a row's pixel data had an odd length.

Advance rows on the padded stride, write only bytes that fall inside
the row, and let runs cross scanlines while skipping padding. Add
regression tests for literal rows and for a run crossing two padded
rows.
@radarhere radarhere added the 🤖-assisted AI-assisted label Nov 1, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🤖-assisted AI-assisted

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sun raster files with RLE encoding and odd-width rows decode shifted

2 participants