Skip to content

Commit 81fa4e1

Browse files
committed
If pasting image to self at lower position with mask, copy from bottom
1 parent 79f834e commit 81fa4e1

File tree

2 files changed

+38
-26
lines changed

2 files changed

+38
-26
lines changed

Tests/test_image_paste.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,17 @@ def test_image_solid(self, mode: str) -> None:
125125
assert_image_equal(im, im2)
126126

127127
@pytest.mark.parametrize("y", [10, -10])
128-
def test_image_self(self, y: int) -> None:
129-
im = self.gradient_RGB
128+
@pytest.mark.parametrize("mode", ["L", "RGB"])
129+
@pytest.mark.parametrize("mask_mode", ["", "1", "L", "LA", "RGBa"])
130+
def test_image_self(self, y: int, mode: str, mask_mode: str) -> None:
131+
im = getattr(self, "gradient_" + mode)
132+
mask = Image.new(mask_mode, im.size, 0xFFFFFFFF) if mask_mode else None
130133

131134
im_self = im.copy()
132-
im_self.paste(im_self, (0, y))
135+
im_self.paste(im_self, (0, y), mask)
133136

134137
im_copy = im.copy()
135-
im_copy.paste(im_copy.copy(), (0, y))
138+
im_copy.paste(im_copy.copy(), (0, y), mask)
136139

137140
assert_image_equal(im_self, im_copy)
138141

src/libImaging/Paste.c

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@
2323

2424
#include "Imaging.h"
2525

26+
#define PREPARE_PASTE_LOOP() \
27+
int y, y_end, offset; \
28+
if (imOut == imIn && dy > sy) { \
29+
y = ysize - 1; \
30+
y_end = -1; \
31+
offset = -1; \
32+
} else { \
33+
y = 0; \
34+
y_end = ysize; \
35+
offset = 1; \
36+
}
37+
2638
static inline void
2739
paste(
2840
Imaging imOut,
@@ -37,21 +49,14 @@ paste(
3749
) {
3850
/* paste opaque region */
3951

40-
int y;
41-
4252
dx *= pixelsize;
4353
sx *= pixelsize;
4454

4555
xsize *= pixelsize;
4656

47-
if (imOut == imIn && dy > sy) {
48-
for (y = ysize - 1; y >= 0; y--) {
49-
memcpy(imOut->image[y + dy] + dx, imIn->image[y + sy] + sx, xsize);
50-
}
51-
} else {
52-
for (y = 0; y < ysize; y++) {
53-
memcpy(imOut->image[y + dy] + dx, imIn->image[y + sy] + sx, xsize);
54-
}
57+
PREPARE_PASTE_LOOP();
58+
for (; y != y_end; y += offset) {
59+
memcpy(imOut->image[y + dy] + dx, imIn->image[y + sy] + sx, xsize);
5560
}
5661
}
5762

@@ -70,12 +75,13 @@ paste_mask_1(
7075
) {
7176
/* paste with mode "1" mask */
7277

73-
int x, y;
78+
int x;
7479

80+
PREPARE_PASTE_LOOP();
7581
if (imOut->image8) {
7682
int in_i16 = strncmp(imIn->mode, "I;16", 4) == 0;
7783
int out_i16 = strncmp(imOut->mode, "I;16", 4) == 0;
78-
for (y = 0; y < ysize; y++) {
84+
for (; y != y_end; y += offset) {
7985
UINT8 *out = imOut->image8[y + dy] + dx;
8086
if (out_i16) {
8187
out += dx;
@@ -103,7 +109,7 @@ paste_mask_1(
103109
}
104110

105111
} else {
106-
for (y = 0; y < ysize; y++) {
112+
for (; y != y_end; y += offset) {
107113
INT32 *out = imOut->image32[y + dy] + dx;
108114
INT32 *in = imIn->image32[y + sy] + sx;
109115
UINT8 *mask = imMask->image8[y + sy] + sx;
@@ -132,11 +138,12 @@ paste_mask_L(
132138
) {
133139
/* paste with mode "L" matte */
134140

135-
int x, y;
141+
int x;
136142
unsigned int tmp1;
137143

144+
PREPARE_PASTE_LOOP();
138145
if (imOut->image8) {
139-
for (y = 0; y < ysize; y++) {
146+
for (; y != y_end; y += offset) {
140147
UINT8 *out = imOut->image8[y + dy] + dx;
141148
UINT8 *in = imIn->image8[y + sy] + sx;
142149
UINT8 *mask = imMask->image8[y + sy] + sx;
@@ -147,7 +154,7 @@ paste_mask_L(
147154
}
148155

149156
} else {
150-
for (y = 0; y < ysize; y++) {
157+
for (; y != y_end; y += offset) {
151158
UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
152159
UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
153160
UINT8 *mask = (UINT8 *)(imMask->image8[y + sy] + sx);
@@ -180,11 +187,12 @@ paste_mask_RGBA(
180187
) {
181188
/* paste with mode "RGBA" matte */
182189

183-
int x, y;
190+
int x;
184191
unsigned int tmp1;
185192

193+
PREPARE_PASTE_LOOP();
186194
if (imOut->image8) {
187-
for (y = 0; y < ysize; y++) {
195+
for (; y != y_end; y += offset) {
188196
UINT8 *out = imOut->image8[y + dy] + dx;
189197
UINT8 *in = imIn->image8[y + sy] + sx;
190198
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 4 + 3;
@@ -195,7 +203,7 @@ paste_mask_RGBA(
195203
}
196204

197205
} else {
198-
for (y = 0; y < ysize; y++) {
206+
for (; y != y_end; y += offset) {
199207
UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
200208
UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
201209
UINT8 *mask = (UINT8 *)(imMask->image32[y + sy] + sx);
@@ -228,11 +236,12 @@ paste_mask_RGBa(
228236
) {
229237
/* paste with mode "RGBa" matte */
230238

231-
int x, y;
239+
int x;
232240
unsigned int tmp1;
233241

242+
PREPARE_PASTE_LOOP();
234243
if (imOut->image8) {
235-
for (y = 0; y < ysize; y++) {
244+
for (; y != y_end; y += offset) {
236245
UINT8 *out = imOut->image8[y + dy] + dx;
237246
UINT8 *in = imIn->image8[y + sy] + sx;
238247
UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx * 4 + 3;
@@ -243,7 +252,7 @@ paste_mask_RGBa(
243252
}
244253

245254
} else {
246-
for (y = 0; y < ysize; y++) {
255+
for (; y != y_end; y += offset) {
247256
UINT8 *out = (UINT8 *)(imOut->image32[y + dy] + dx);
248257
UINT8 *in = (UINT8 *)(imIn->image32[y + sy] + sx);
249258
UINT8 *mask = (UINT8 *)(imMask->image32[y + sy] + sx);

0 commit comments

Comments
 (0)