Pillow icon indicating copy to clipboard operation
Pillow copied to clipboard

`image.paste(image, box=(x, y))` is unexpected if both images are identical and `y` is positive

Open TS53 opened this issue 7 months ago • 3 comments

I searched for a solution to get a high performance shift operation with Pillow (in-place, SIMD, executed on C-level) but have not found one. It seems they all require one/multiple memory allocations or manual python loops.

I then realized image.paste(image, box) should do it. But the resulting image shifts the y-amount again and again (if y is positive). My first guess was that I used the box parameter wrongly, but image.paste(image.copy(), box) works as expected.

I conclude that a check is missing if the image pasted in is the same like self or that it should get mentioned in the docs that in this case the function has a different semantic.

Maybe, if copying started from below would fix the given example. When box=(0, -10), it works as expected.

Repeatedly shifted, working unexpected:

img = Image.open("some_random_image.jpg")
img.paste(img, box=(0, 10))
img.save("img_pasted.jpg")

Working as expected:

img = Image.open("some_random_image.jpg")
img.paste(img.copy(), box=(0, 10))
img.save("img_pasted.jpg")
img = Image.open("some_random_image.jpg")
img.paste(img, box=(0, -10))
img.save("img_pasted.jpg")
img = Image.open("some_random_image.jpg")
img.paste(img, box=(-10, -10))
img.save("img_pasted.jpg")
img = Image.open("some_random_image.jpg")
img.paste(img, box=(10, -10))
img.save("img_pasted.jpg")
img = Image.open("some_random_image.jpg")
img.paste(img, box=(0, 0))
img.save("img_pasted.jpg")
img = Image.open("some_random_image.jpg")
img.paste(img, box=(-10, 0))
img.save("img_pasted.jpg")
img = Image.open("some_random_image.jpg")
img.paste(img, box=(10, 0))
img.save("img_pasted.jpg")

To sum up: if other_img is self, and box parameter is given and is box=(x, y) with y > 0 it works unexpected. All other combinations work as expected. When a deep-copy of the image is given, all combinations of x and y work already as expected.

  • img.paste(img, box=(x, y)) should always give the same result like img.paste(img.copy(), box=(x, y)) for all possible combinations of x and y.

Unfortunately, the single case that does not work is exactly my use-case for fast frame manipulation.

TS53 avatar Apr 11 '25 07:04 TS53

I've created #8882. That should fix the resulting image.

radarhere avatar Apr 11 '25 12:04 radarhere

Perfect, thank you very much!

ghost avatar Apr 11 '25 12:04 ghost