Pillow

Форк
0
/
test_image_paste.py 
348 строк · 10.4 Кб
1
from __future__ import annotations
2

3
import pytest
4

5
from PIL import Image
6

7
from .helper import CachedProperty, assert_image_equal
8

9

10
class TestImagingPaste:
11
    size = 128
12

13
    def assert_9points_image(
14
        self, im: Image.Image, expected: list[tuple[int, int, int, int]]
15
    ) -> None:
16
        px = im.load()
17
        assert px is not None
18
        actual = [
19
            px[0, 0],
20
            px[self.size // 2, 0],
21
            px[self.size - 1, 0],
22
            px[0, self.size // 2],
23
            px[self.size // 2, self.size // 2],
24
            px[self.size - 1, self.size // 2],
25
            px[0, self.size - 1],
26
            px[self.size // 2, self.size - 1],
27
            px[self.size - 1, self.size - 1],
28
        ]
29
        assert actual == [
30
            point[0] if im.mode == "L" else point[: len(im.mode)] for point in expected
31
        ]
32

33
    def assert_9points_paste(
34
        self,
35
        im: Image.Image,
36
        im2: Image.Image | str | tuple[int, ...],
37
        mask: Image.Image,
38
        expected: list[tuple[int, int, int, int]],
39
    ) -> None:
40
        im3 = im.copy()
41
        im3.paste(im2, (0, 0), mask)
42
        self.assert_9points_image(im3, expected)
43

44
        # Abbreviated syntax
45
        im.paste(im2, mask)
46
        self.assert_9points_image(im, expected)
47

48
    @CachedProperty
49
    def mask_1(self) -> Image.Image:
50
        mask = Image.new("1", (self.size, self.size))
51
        px = mask.load()
52
        assert px is not None
53
        for y in range(mask.height):
54
            for x in range(mask.width):
55
                px[y, x] = (x + y) % 2
56
        return mask
57

58
    @CachedProperty
59
    def mask_L(self) -> Image.Image:
60
        return self.gradient_L.transpose(Image.Transpose.ROTATE_270)
61

62
    @CachedProperty
63
    def gradient_L(self) -> Image.Image:
64
        gradient = Image.new("L", (self.size, self.size))
65
        px = gradient.load()
66
        assert px is not None
67
        for y in range(gradient.height):
68
            for x in range(gradient.width):
69
                px[y, x] = (x + y) % 255
70
        return gradient
71

72
    @CachedProperty
73
    def gradient_RGB(self) -> Image.Image:
74
        return Image.merge(
75
            "RGB",
76
            [
77
                self.gradient_L,
78
                self.gradient_L.transpose(Image.Transpose.ROTATE_90),
79
                self.gradient_L.transpose(Image.Transpose.ROTATE_180),
80
            ],
81
        )
82

83
    @CachedProperty
84
    def gradient_LA(self) -> Image.Image:
85
        return Image.merge(
86
            "LA",
87
            [
88
                self.gradient_L,
89
                self.gradient_L.transpose(Image.Transpose.ROTATE_90),
90
            ],
91
        )
92

93
    @CachedProperty
94
    def gradient_RGBA(self) -> Image.Image:
95
        return Image.merge(
96
            "RGBA",
97
            [
98
                self.gradient_L,
99
                self.gradient_L.transpose(Image.Transpose.ROTATE_90),
100
                self.gradient_L.transpose(Image.Transpose.ROTATE_180),
101
                self.gradient_L.transpose(Image.Transpose.ROTATE_270),
102
            ],
103
        )
104

105
    @CachedProperty
106
    def gradient_RGBa(self) -> Image.Image:
107
        return Image.merge(
108
            "RGBa",
109
            [
110
                self.gradient_L,
111
                self.gradient_L.transpose(Image.Transpose.ROTATE_90),
112
                self.gradient_L.transpose(Image.Transpose.ROTATE_180),
113
                self.gradient_L.transpose(Image.Transpose.ROTATE_270),
114
            ],
115
        )
116

117
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
118
    def test_image_solid(self, mode: str) -> None:
119
        im = Image.new(mode, (200, 200), "red")
120
        im2 = getattr(self, "gradient_" + mode)
121

122
        im.paste(im2, (12, 23))
123

124
        im = im.crop((12, 23, im2.width + 12, im2.height + 23))
125
        assert_image_equal(im, im2)
126

127
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
128
    def test_image_mask_1(self, mode: str) -> None:
129
        im = Image.new(mode, (200, 200), "white")
130
        im2 = getattr(self, "gradient_" + mode)
131

132
        self.assert_9points_paste(
133
            im,
134
            im2,
135
            self.mask_1,
136
            [
137
                (255, 255, 255, 255),
138
                (255, 255, 255, 255),
139
                (127, 254, 127, 0),
140
                (255, 255, 255, 255),
141
                (255, 255, 255, 255),
142
                (191, 190, 63, 64),
143
                (127, 0, 127, 254),
144
                (191, 64, 63, 190),
145
                (255, 255, 255, 255),
146
            ],
147
        )
148

149
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
150
    def test_image_mask_L(self, mode: str) -> None:
151
        im = Image.new(mode, (200, 200), "white")
152
        im2 = getattr(self, "gradient_" + mode)
153

154
        self.assert_9points_paste(
155
            im,
156
            im2,
157
            self.mask_L,
158
            [
159
                (128, 191, 255, 191),
160
                (208, 239, 239, 208),
161
                (255, 255, 255, 255),
162
                (112, 111, 206, 207),
163
                (192, 191, 191, 191),
164
                (239, 239, 207, 207),
165
                (128, 1, 128, 254),
166
                (207, 113, 112, 207),
167
                (255, 191, 128, 191),
168
            ],
169
        )
170

171
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
172
    def test_image_mask_LA(self, mode: str) -> None:
173
        im = Image.new(mode, (200, 200), "white")
174
        im2 = getattr(self, "gradient_" + mode)
175

176
        self.assert_9points_paste(
177
            im,
178
            im2,
179
            self.gradient_LA,
180
            [
181
                (128, 191, 255, 191),
182
                (112, 207, 206, 111),
183
                (128, 254, 128, 1),
184
                (208, 208, 239, 239),
185
                (192, 191, 191, 191),
186
                (207, 207, 112, 113),
187
                (255, 255, 255, 255),
188
                (239, 207, 207, 239),
189
                (255, 191, 128, 191),
190
            ],
191
        )
192

193
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
194
    def test_image_mask_RGBA(self, mode: str) -> None:
195
        im = Image.new(mode, (200, 200), "white")
196
        im2 = getattr(self, "gradient_" + mode)
197

198
        self.assert_9points_paste(
199
            im,
200
            im2,
201
            self.gradient_RGBA,
202
            [
203
                (128, 191, 255, 191),
204
                (208, 239, 239, 208),
205
                (255, 255, 255, 255),
206
                (112, 111, 206, 207),
207
                (192, 191, 191, 191),
208
                (239, 239, 207, 207),
209
                (128, 1, 128, 254),
210
                (207, 113, 112, 207),
211
                (255, 191, 128, 191),
212
            ],
213
        )
214

215
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
216
    def test_image_mask_RGBa(self, mode: str) -> None:
217
        im = Image.new(mode, (200, 200), "white")
218
        im2 = getattr(self, "gradient_" + mode)
219

220
        self.assert_9points_paste(
221
            im,
222
            im2,
223
            self.gradient_RGBa,
224
            [
225
                (128, 255, 126, 255),
226
                (0, 127, 126, 255),
227
                (126, 253, 126, 255),
228
                (128, 127, 254, 255),
229
                (0, 255, 254, 255),
230
                (126, 125, 254, 255),
231
                (128, 1, 128, 255),
232
                (0, 129, 128, 255),
233
                (126, 255, 128, 255),
234
            ],
235
        )
236

237
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
238
    def test_color_solid(self, mode: str) -> None:
239
        im = Image.new(mode, (200, 200), "black")
240

241
        rect = (12, 23, 128 + 12, 128 + 23)
242
        im.paste("white", rect)
243

244
        hist = im.crop(rect).histogram()
245
        while hist:
246
            head, hist = hist[:256], hist[256:]
247
            assert head[255] == 128 * 128
248
            assert sum(head[:255]) == 0
249

250
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
251
    def test_color_mask_1(self, mode: str) -> None:
252
        im = Image.new(mode, (200, 200), (50, 60, 70, 80)[: len(mode)])
253
        color = (10, 20, 30, 40)[: len(mode)]
254

255
        self.assert_9points_paste(
256
            im,
257
            color,
258
            self.mask_1,
259
            [
260
                (50, 60, 70, 80),
261
                (50, 60, 70, 80),
262
                (10, 20, 30, 40),
263
                (50, 60, 70, 80),
264
                (50, 60, 70, 80),
265
                (10, 20, 30, 40),
266
                (10, 20, 30, 40),
267
                (10, 20, 30, 40),
268
                (50, 60, 70, 80),
269
            ],
270
        )
271

272
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
273
    def test_color_mask_L(self, mode: str) -> None:
274
        im = getattr(self, "gradient_" + mode).copy()
275
        color = "white"
276

277
        self.assert_9points_paste(
278
            im,
279
            color,
280
            self.mask_L,
281
            [
282
                (127, 191, 254, 191),
283
                (111, 207, 206, 110),
284
                (127, 254, 127, 0),
285
                (207, 207, 239, 239),
286
                (191, 191, 190, 191),
287
                (207, 206, 111, 112),
288
                (254, 254, 254, 255),
289
                (239, 206, 206, 238),
290
                (254, 191, 127, 191),
291
            ],
292
        )
293

294
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
295
    def test_color_mask_RGBA(self, mode: str) -> None:
296
        im = getattr(self, "gradient_" + mode).copy()
297
        color = "white"
298

299
        self.assert_9points_paste(
300
            im,
301
            color,
302
            self.gradient_RGBA,
303
            [
304
                (127, 191, 254, 191),
305
                (111, 207, 206, 110),
306
                (127, 254, 127, 0),
307
                (207, 207, 239, 239),
308
                (191, 191, 190, 191),
309
                (207, 206, 111, 112),
310
                (254, 254, 254, 255),
311
                (239, 206, 206, 238),
312
                (254, 191, 127, 191),
313
            ],
314
        )
315

316
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
317
    def test_color_mask_RGBa(self, mode: str) -> None:
318
        im = getattr(self, "gradient_" + mode).copy()
319
        color = "white"
320

321
        self.assert_9points_paste(
322
            im,
323
            color,
324
            self.gradient_RGBa,
325
            [
326
                (255, 63, 126, 63),
327
                (47, 143, 142, 46),
328
                (126, 253, 126, 255),
329
                (15, 15, 47, 47),
330
                (63, 63, 62, 63),
331
                (142, 141, 46, 47),
332
                (255, 255, 255, 0),
333
                (48, 15, 15, 47),
334
                (126, 63, 255, 63),
335
            ],
336
        )
337

338
    def test_different_sizes(self) -> None:
339
        im = Image.new("RGB", (100, 100))
340
        im2 = Image.new("RGB", (50, 50))
341

342
        im.copy().paste(im2)
343
        im.copy().paste(im2, (0, 0))
344

345
    def test_incorrect_abbreviated_form(self) -> None:
346
        im = Image.new("L", (1, 1))
347
        with pytest.raises(ValueError):
348
            im.paste(im, im, im)
349

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.