Skip to content

Improve pasting onto I;16 images - #10398

Merged
radarhere merged 4 commits into
python-pillow:mainfrom
radarhere:paste
Nov 3, 2026
Merged

radarhere merged 4 commits into
python-pillow:mainfrom
radarhere:paste

Conversation

@radarhere

@radarhere radarhere commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Resolves #10388

  1. Correct using a L mode mask when pasting I;16 image onto I;16 image. Similar to Consider I;16 pixel size when using a 1 mode mask #8112
  2. Correct using 1 mode mask when pasting colour onto I;16 image. Similar to Consider I;16 pixel size when drawing text #5598
  3. Correct pasting colour onto I;16 image without a mask.

Comment thread src/libImaging/Paste.c
Comment on lines +146 to +166
int in_i16 = imIn->type == IMAGING_TYPE_I16;
int out_i16 = imOut->type == IMAGING_TYPE_I16;
for (; y != y_end; y += offset) {
UINT8 *out = imOut->image8[y + dy] + dx;
if (out_i16) {
out += dx;
}
UINT8 *in = imIn->image8[y + sy] + sx;
if (in_i16) {
in += sx;
}
UINT8 *mask = imMask->image8[y + sy] + sx;
for (x = 0; x < xsize; x++) {
*out = BLEND(*mask, *out, *in, tmp1);
if (in_i16) {
in++;
}
if (out_i16) {
out++;
*out = BLEND(*mask, *out, *in, tmp1);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For performance, this would be better unswitched to separate loops for the I16 case...

@radarhere radarhere Nov 3, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

the i16 case

Isn't there one case where in_i16 is true, another where out_i16 is true, and one where both are true? I don't think three loops instead of one is a very elegant solution.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sorry, yeah, meant cases.

Anyway, ran a quick benchmark locally (we don't seem to have one that covers paste so CodSpeed is happy here) and this makes L-L and P-P some 4 times slower, likely since the BLEND can't be vectorized anymore.

I think just splitting the loop into 2 would be enough, though: one for the "something might be 16-bit" case and the other for the common "everything is 8-bit" case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

A commit has now been pushed for this.

Comment thread src/libImaging/Paste.c Resolved
Co-authored-by: Aarni Koskela <akx@iki.fi>
@radarhere
radarhere merged commit 32c04ea into python-pillow:main Nov 3, 2026
60 checks passed
@radarhere
radarhere deleted the paste branch November 3, 2026 23:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Image.paste() into an I;16 image writes bytes instead of 16-bit pixels for colour fills and for some masks

2 participants