1
from __future__ import annotations
5
from itertools import product
6
from pathlib import Path
10
from PIL import Image, UnidentifiedImageError
12
from .helper import assert_image_equal, assert_image_equal_tofile, hopper
14
_TGA_DIR = os.path.join("Tests", "images", "tga")
15
_TGA_DIR_COMMON = os.path.join(_TGA_DIR, "common")
18
_MODES = ("L", "LA", "P", "RGB", "RGBA")
19
_ORIGINS = ("tl", "bl")
21
_ORIGIN_TO_ORIENTATION = {"tl": 1, "bl": -1}
24
@pytest.mark.parametrize("mode", _MODES)
25
def test_sanity(mode: str, tmp_path: Path) -> None:
26
def roundtrip(original_im: Image.Image) -> None:
27
out = str(tmp_path / "temp.tga")
29
original_im.save(out, rle=rle)
30
with Image.open(out) as saved_im:
32
assert saved_im.info["compression"] == original_im.info["compression"]
33
assert saved_im.info["orientation"] == original_im.info["orientation"]
35
assert saved_im.getpalette() == original_im.getpalette()
37
assert_image_equal(saved_im, original_im)
39
png_paths = glob(os.path.join(_TGA_DIR_COMMON, f"*x*_{mode.lower()}.png"))
41
for png_path in png_paths:
42
with Image.open(png_path) as reference_im:
43
assert reference_im.mode == mode
45
path_no_ext = os.path.splitext(png_path)[0]
46
for origin, rle in product(_ORIGINS, (True, False)):
47
tga_path = "{}_{}_{}.tga".format(
48
path_no_ext, origin, "rle" if rle else "raw"
51
with Image.open(tga_path) as original_im:
52
assert original_im.format == "TGA"
53
assert original_im.get_format_mimetype() == "image/x-tga"
55
assert original_im.info["compression"] == "tga_rle"
57
original_im.info["orientation"]
58
== _ORIGIN_TO_ORIENTATION[origin]
61
assert original_im.getpalette() == reference_im.getpalette()
63
assert_image_equal(original_im, reference_im)
65
roundtrip(original_im)
68
def test_palette_depth_8(tmp_path: Path) -> None:
69
with pytest.raises(UnidentifiedImageError):
70
Image.open("Tests/images/p_8.tga")
73
def test_palette_depth_16(tmp_path: Path) -> None:
74
with Image.open("Tests/images/p_16.tga") as im:
75
assert im.palette.mode == "RGBA"
76
assert_image_equal_tofile(im.convert("RGBA"), "Tests/images/p_16.png")
78
out = str(tmp_path / "temp.png")
80
with Image.open(out) as reloaded:
81
assert_image_equal_tofile(reloaded.convert("RGBA"), "Tests/images/p_16.png")
84
def test_rgba_16() -> None:
85
with Image.open("Tests/images/rgba16.tga") as im:
86
assert im.mode == "RGBA"
88
assert im.getpixel((0, 0)) == (172, 0, 255, 255)
89
assert im.getpixel((1, 0)) == (0, 255, 82, 0)
92
def test_id_field() -> None:
94
test_file = "Tests/images/tga_id_field.tga"
97
with Image.open(test_file) as im:
99
assert im.size == (100, 100)
102
def test_id_field_rle() -> None:
104
test_file = "Tests/images/rgb32rle.tga"
107
with Image.open(test_file) as im:
109
assert im.size == (199, 199)
112
def test_cross_scan_line() -> None:
113
with Image.open("Tests/images/cross_scan_line.tga") as im:
114
assert_image_equal_tofile(im, "Tests/images/cross_scan_line.png")
116
with Image.open("Tests/images/cross_scan_line_truncated.tga") as im:
117
with pytest.raises(OSError):
121
def test_save(tmp_path: Path) -> None:
122
test_file = "Tests/images/tga_id_field.tga"
123
with Image.open(test_file) as im:
124
out = str(tmp_path / "temp.tga")
128
with Image.open(out) as test_im:
129
assert test_im.size == (100, 100)
130
assert test_im.info["id_section"] == im.info["id_section"]
133
im.convert("RGBA").save(out)
134
with Image.open(out) as test_im:
135
assert test_im.size == (100, 100)
138
def test_small_palette(tmp_path: Path) -> None:
139
im = Image.new("P", (1, 1))
141
im.putpalette(colors)
143
out = str(tmp_path / "temp.tga")
146
with Image.open(out) as reloaded:
147
assert reloaded.getpalette() == colors
150
def test_missing_palette() -> None:
151
with Image.open("Tests/images/dilation4.lut") as im:
152
assert im.mode == "L"
155
def test_save_wrong_mode(tmp_path: Path) -> None:
157
out = str(tmp_path / "temp.tga")
159
with pytest.raises(OSError):
163
def test_save_mapdepth() -> None:
166
test_file = "Tests/images/200x32_p_bl_raw_origin.tga"
167
with Image.open(test_file) as im:
168
assert_image_equal_tofile(im, "Tests/images/tga/common/200x32_p.png")
171
def test_save_id_section(tmp_path: Path) -> None:
172
test_file = "Tests/images/rgb32rle.tga"
173
with Image.open(test_file) as im:
174
out = str(tmp_path / "temp.tga")
178
with Image.open(out) as test_im:
179
assert "id_section" not in test_im.info
182
im.save(out, id_section=b"Test content")
183
with Image.open(out) as test_im:
184
assert test_im.info["id_section"] == b"Test content"
187
id_section = b"Test content" * 25
188
with pytest.warns(UserWarning):
189
im.save(out, id_section=id_section)
191
with Image.open(out) as test_im:
192
assert test_im.info["id_section"] == id_section[:255]
194
test_file = "Tests/images/tga_id_field.tga"
195
with Image.open(test_file) as im:
197
im.save(out, id_section="")
198
with Image.open(out) as test_im:
199
assert "id_section" not in test_im.info
202
def test_save_orientation(tmp_path: Path) -> None:
203
test_file = "Tests/images/rgb32rle.tga"
204
out = str(tmp_path / "temp.tga")
205
with Image.open(test_file) as im:
206
assert im.info["orientation"] == -1
208
im.save(out, orientation=1)
209
with Image.open(out) as test_im:
210
assert test_im.info["orientation"] == 1
213
def test_horizontal_orientations() -> None:
215
with Image.open("Tests/images/rgb32rle_top_right.tga") as im:
216
assert im.load()[90, 90][:3] == (0, 0, 0)
218
with Image.open("Tests/images/rgb32rle_bottom_right.tga") as im:
219
assert im.load()[90, 90][:3] == (0, 255, 0)
222
def test_save_rle(tmp_path: Path) -> None:
223
test_file = "Tests/images/rgb32rle.tga"
224
with Image.open(test_file) as im:
225
assert im.info["compression"] == "tga_rle"
227
out = str(tmp_path / "temp.tga")
231
with Image.open(out) as test_im:
232
assert test_im.size == (199, 199)
233
assert test_im.info["compression"] == "tga_rle"
236
im.save(out, compression=None)
237
with Image.open(out) as test_im:
238
assert "compression" not in test_im.info
241
im.convert("RGBA").save(out)
242
with Image.open(out) as test_im:
243
assert test_im.size == (199, 199)
245
test_file = "Tests/images/tga_id_field.tga"
246
with Image.open(test_file) as im:
247
assert "compression" not in im.info
250
im.save(out, compression="tga_rle")
251
with Image.open(out) as test_im:
252
assert test_im.info["compression"] == "tga_rle"
255
def test_save_l_transparency(tmp_path: Path) -> None:
257
num_transparent = 559
259
in_file = "Tests/images/la.tga"
260
with Image.open(in_file) as im:
261
assert im.mode == "LA"
262
assert im.getchannel("A").getcolors()[0][0] == num_transparent
264
out = str(tmp_path / "temp.tga")
267
with Image.open(out) as test_im:
268
assert test_im.mode == "LA"
269
assert test_im.getchannel("A").getcolors()[0][0] == num_transparent
271
assert_image_equal(im, test_im)