If pasting image to self at lower position with mask, copy from bottom

This commit is contained in:
Andrew Murray 2025-04-12 08:19:18 +10:00
parent 79f834ef65
commit 81fa4e18c7
2 changed files with 38 additions and 26 deletions

View File

@ -125,14 +125,17 @@ class TestImagingPaste:
assert_image_equal(im, im2)
@pytest.mark.parametrize("y", [10, -10])
def test_image_self(self, y: int) -> None:
im = self.gradient_RGB
@pytest.mark.parametrize("mode", ["L", "RGB"])
@pytest.mark.parametrize("mask_mode", ["", "1", "L", "LA", "RGBa"])
def test_image_self(self, y: int, mode: str, mask_mode: str) -> None:
im = getattr(self, "gradient_" + mode)
mask = Image.new(mask_mode, im.size, 0xFFFFFFFF) if mask_mode else None
im_self = im.copy()
im_self.paste(im_self, (0, y))
im_self.paste(im_self, (0, y), mask)
im_copy = im.copy()
im_copy.paste(im_copy.copy(), (0, y))
im_copy.paste(im_copy.copy(), (0, y), mask)
assert_image_equal(im_self, im_copy)

View File

@ -23,6 +23,18 @@
#include "Imaging.h"
#define PREPARE_PASTE_LOOP() \
int y, y_end, offset; \
if (imOut == imIn && dy > sy) { \
y = ysize - 1; \
y_end = -1; \
offset = -1; \
} else { \
y = 0; \
y_end = ysize; \
offset = 1; \
}
static inline void
paste(
Imaging imOut,
@ -37,21 +49,14 @@ paste(
) {
/* paste opaque region */
int y;
dx *= pixelsize;
sx *= pixelsize;
xsize *= pixelsize;
if (imOut == imIn && dy > sy) {
for (y = ysize - 1; y >= 0; y--) {
memcpy(imOut->image[y + dy] + dx, imIn->image[y + sy] + sx, xsize);
}
} else {
for (y = 0; y < ysize; y++) {
memcpy(imOut->image[y + dy] + dx, imIn->image[y + sy] + sx, xsize);
}
PREPARE_PASTE_LOOP();
for (; y != y_end; y += offset) {
memcpy(imOut->image[y + dy] + dx, imIn->image[y + sy] + sx, xsize);
}
}
@ -70,12 +75,13 @@ paste_mask_1(
) {
/* paste with mode "1" mask */
int x, y;
int x;
PREPARE_PASTE_LOOP();
if (imOut->image8) {
int in_i16 = strncmp(imIn->mode, "I;16", 4) == 0;
int out_i16 = strncmp(imOut->mode, "I;16", 4) == 0;
for (y = 0; y < ysize; y++) {
for (; y != y_end; y += offset) {
UINT8 *out = imOut->image8[y + dy] + dx;
if (out_i16) {
out += dx;
@ -103,7 +109,7 @@ paste_mask_1(
}
} else {
for (y = 0; y < ysize; y++) {
for (; y != y_end; y += offset) {
INT32 *out = imOut->image32[y + dy] + dx;
INT32 *in = imIn->image32[y + sy] + sx;
UINT8 *mask = imMask->image8[y + sy] + sx;
@ -132,11 +138,12 @@ paste_mask_L(
) {
/* paste with mode "L" matte */
int x, y;
int x;
unsigned int tmp1;
PREPARE_PASTE_LOOP();
if (imOut->image8) {
for (y = 0; y < ysize; y++) {
for (; y != y_end; y += offset) {
UINT8 *out = imOut->image8[y + dy] + dx;
UINT8 *in = imIn->image8[y + sy] + sx;
UINT8 *mask = imMask->image8[y + sy] + sx;
@ -147,7 +154,7 @@ paste_mask_L(
}
} else {
for (y = 0; y < ysize; y++) {
for (; y != y_end; y += offset) {
UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
UINT8 *mask = (UINT8 *)(imMask->image8[y + sy] + sx);
@ -180,11 +187,12 @@ paste_mask_RGBA(
) {
/* paste with mode "RGBA" matte */
int x, y;
int x;
unsigned int tmp1;
PREPARE_PASTE_LOOP();
if (imOut->image8) {
for (y = 0; y < ysize; y++) {
for (; y != y_end; y += offset) {
UINT8 *out = imOut->image8[y + dy] + dx;
UINT8 *in = imIn->image8[y + sy] + sx;
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 4 + 3;
@ -195,7 +203,7 @@ paste_mask_RGBA(
}
} else {
for (y = 0; y < ysize; y++) {
for (; y != y_end; y += offset) {
UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
UINT8 *mask = (UINT8 *)(imMask->image32[y + sy] + sx);
@ -228,11 +236,12 @@ paste_mask_RGBa(
) {
/* paste with mode "RGBa" matte */
int x, y;
int x;
unsigned int tmp1;
PREPARE_PASTE_LOOP();
if (imOut->image8) {
for (y = 0; y < ysize; y++) {
for (; y != y_end; y += offset) {
UINT8 *out = imOut->image8[y + dy] + dx;
UINT8 *in = imIn->image8[y + sy] + sx;
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 4 + 3;
@ -243,7 +252,7 @@ paste_mask_RGBa(
}
} else {
for (y = 0; y < ysize; y++) {
for (; y != y_end; y += offset) {
UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
UINT8 *mask = (UINT8 *)(imMask->image32[y + sy] + sx);