Skip to content

Implement correct draw functions for 16-bpp modes - #9982

Open
akx wants to merge 4 commits into
python-pillow:mainfrom
akx:draw16
Open

Implement correct draw functions for 16-bpp modes#9982
akx wants to merge 4 commits into
python-pillow:mainfrom
akx:draw16

Conversation

@akx

@akx akx commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

While reworking #9772, I noticed 16bpp drawing was piggybacking on draw8... and then it kind of turned out that not all 16bpp modes were drawing things correctly.

This PR:

  • moves explicit I;16 draw tests into their own file
  • adds (failing) tests covering more draw functions in all of the I;16 modes
  • steals the Bresenham detriplication from Speed up rectangle, polygon and line drawing #9772
  • implements draw16, the suite of point/hline/line functions for 16-bpp images, with some additional twists and turns of big-endian support (which was also incorrect in another special way).

Along with correctness, this should also yield a bit of performance since draw8 functions don't need to do per-pixel checks for the image mode (and the Bresenham de-triplication commit also adds the option to use hline).

Comment thread src/libImaging/Draw.c
@akx
akx marked this pull request as ready for review September 10, 2026 13:38
@codspeed-hq

codspeed-hq Bot commented Sep 10, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by ×2.4

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
✅ 602 untouched benchmarks
⏩ 335 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
test_draw_lines[1237x811-L] 912.2 µs 380.7 µs ×2.4

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing akx:draw16 (e3266fc) with main (05fcca1)

Open in CodSpeed

Footnotes

  1. 335 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Comment on lines +57 to +75
@pytest.mark.parametrize("mode", I16_MODES)
def test_horizontal_line_I16(mode: str) -> None:
img, draw = create_I16_image_draw(mode)
draw.line((0, 4, 7, 4), fill=I16_INK)
assert img.getpixel((4, 4)) == I16_INK


@pytest.mark.parametrize("mode", I16_MODES)
def test_vertical_line_I16(mode: str) -> None:
img, draw = create_I16_image_draw(mode)
draw.line((4, 0, 4, 7), fill=I16_INK)
assert img.getpixel((4, 4)) == I16_INK


@pytest.mark.parametrize("mode", I16_MODES)
def test_diagonal_line_I16(mode: str) -> None:
img, draw = create_I16_image_draw(mode)
draw.line((0, 0, 7, 7), fill=I16_INK)
assert img.getpixel((4, 4)) == I16_INK

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@pytest.mark.parametrize("mode", I16_MODES)
def test_horizontal_line_I16(mode: str) -> None:
img, draw = create_I16_image_draw(mode)
draw.line((0, 4, 7, 4), fill=I16_INK)
assert img.getpixel((4, 4)) == I16_INK
@pytest.mark.parametrize("mode", I16_MODES)
def test_vertical_line_I16(mode: str) -> None:
img, draw = create_I16_image_draw(mode)
draw.line((4, 0, 4, 7), fill=I16_INK)
assert img.getpixel((4, 4)) == I16_INK
@pytest.mark.parametrize("mode", I16_MODES)
def test_diagonal_line_I16(mode: str) -> None:
img, draw = create_I16_image_draw(mode)
draw.line((0, 0, 7, 7), fill=I16_INK)
assert img.getpixel((4, 4)) == I16_INK
@pytest.mark.parametrize("mode", I16_MODES)
@pytest.mark.parametrize(
"xy",
# horizontal, vertical, diagonal
((0, 4, 7, 4), (4, 0, 4, 7), (0, 0, 7, 7)),
)
def test_horizontal_line_I16(mode: str, xy: tuple[int, int, int, int]) -> None:
img, draw = create_I16_image_draw(mode)
draw.line(xy, fill=I16_INK)
assert img.getpixel((4, 4)) == I16_INK

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants