Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial VTF support #6487

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
df3c025
Initial VTF read support
REDxEYE Aug 7, 2022
9223c06
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 7, 2022
59c2d19
Adjusted formatting regions
REDxEYE Aug 7, 2022
719a3ba
Initial implementation of Bcn encoder
REDxEYE Aug 10, 2022
b883b64
Update copyright
REDxEYE Aug 10, 2022
0d9ac2a
Update copyright
REDxEYE Aug 10, 2022
43592dd
Add Bcn BC1 encoder
REDxEYE Aug 12, 2022
8e11a61
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 12, 2022
1c3a1df
Add back accidentally removed static from decode_565
REDxEYE Aug 12, 2022
1ce95d1
Fix variable type
REDxEYE Aug 12, 2022
affaa62
Made loops compatible with old C standart
REDxEYE Aug 12, 2022
a9364f3
Fix flake errors
REDxEYE Aug 12, 2022
2cc5893
Restored black formatting
radarhere Aug 12, 2022
a05be82
Minor changes
radarhere Aug 12, 2022
c6c0749
Remove pointer casts as they may lead to UB and refactor code to not …
REDxEYE Aug 12, 2022
7285b74
Add support for other common pixel formats
REDxEYE Aug 13, 2022
afc0e8e
Fix mipmap calculation
REDxEYE Aug 13, 2022
59a4375
Refactor vtf saving
REDxEYE Aug 13, 2022
b7a5894
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2022
ed70519
Add better check for DXT1 with alpha
REDxEYE Aug 13, 2022
3e78437
Add support for few more formats
REDxEYE Aug 13, 2022
f368f30
Add basic read tests for VTF
REDxEYE Aug 13, 2022
53e1831
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2022
6b781a6
Add raw encoders/decoders for 2 channel RG format
REDxEYE Aug 14, 2022
9ff852f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 14, 2022
a634a44
Add missing images
REDxEYE Aug 14, 2022
c3457f1
Add switch to DXT1 encoder to select block mode (With alpha/Without a…
REDxEYE Aug 14, 2022
906890b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 14, 2022
a2729c0
Merge branch 'main' into vtf-support
radarhere Dec 24, 2023
d5e330e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 24, 2023
f73325f
mode is read-only
radarhere Dec 24, 2023
0ed7d5c
Assign exception string to variable first
radarhere Dec 24, 2023
1b567c5
Merge branch 'main' into vtf-support
radarhere May 22, 2024
44d70b8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 22, 2024
72c3420
Merge branch 'main' into vtf-support
radarhere Jul 19, 2024
f41910c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Tests/images/vtf_a8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/vtf_a8.vtf
Binary file not shown.
Binary file added Tests/images/vtf_bgr888.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/vtf_bgr888.vtf
Binary file not shown.
Binary file added Tests/images/vtf_dxt1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/vtf_dxt1.vtf
Binary file not shown.
Binary file added Tests/images/vtf_dxt1A.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/vtf_dxt1A.vtf
Binary file not shown.
Binary file added Tests/images/vtf_i8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/vtf_i8.vtf
Binary file not shown.
Binary file added Tests/images/vtf_ia88.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/vtf_ia88.vtf
Binary file not shown.
Binary file added Tests/images/vtf_rgb888.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/vtf_rgb888.vtf
Binary file not shown.
Binary file added Tests/images/vtf_rgba8888.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/vtf_rgba8888.vtf
Binary file not shown.
Binary file added Tests/images/vtf_uv88.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/vtf_uv88.vtf
Binary file not shown.
123 changes: 123 additions & 0 deletions Tests/test_file_vtf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
from __future__ import annotations

import pytest

from PIL import Image
from PIL.VtfImagePlugin import (
VtfPF,
_closest_power,
_get_mipmap_count,
_get_texture_size,
)

from .helper import assert_image_equal, assert_image_similar


@pytest.mark.parametrize(
("size", "expected_size"),
[
(8, 8),
(7, 8),
(9, 8),
(192, 256),
(1, 1),
(2000, 2048),
],
)
def test_closest_power(size: int, expected_size: int):
assert _closest_power(size) == expected_size


@pytest.mark.parametrize(
("size", "expected_count"),
[
((1, 1), 1),
((2, 2), 2),
((4, 4), 3),
((8, 8), 4),
((128, 128), 8),
((256, 256), 9),
((512, 512), 10),
((1024, 1024), 11),
((1024, 1), 11),
],
)
def test_get_mipmap_count(size: tuple[int, int], expected_count: int):
assert _get_mipmap_count(*size) == expected_count


@pytest.mark.parametrize(
("pixel_format", "size", "expected_size"),
[
(VtfPF.DXT1, (16, 16), (16 * 16) // 2),
(VtfPF.DXT1_ONEBITALPHA, (16, 16), (16 * 16) // 2),
(VtfPF.DXT3, (16, 16), 16 * 16),
(VtfPF.DXT5, (16, 16), 16 * 16),
(VtfPF.BGR888, (16, 16), 16 * 16 * 3),
(VtfPF.RGB888, (16, 16), 16 * 16 * 3),
(VtfPF.RGBA8888, (16, 16), 16 * 16 * 4),
(VtfPF.UV88, (16, 16), 16 * 16 * 2),
(VtfPF.A8, (16, 16), 16 * 16),
(VtfPF.I8, (16, 16), 16 * 16),
(VtfPF.IA88, (16, 16), 16 * 16 * 2),
],
)
def test_get_texture_size(
pixel_format: VtfPF, size: tuple[int, int], expected_size: int
):
assert _get_texture_size(pixel_format, *size) == expected_size


@pytest.mark.parametrize(
("etalon_path", "file_path", "expected_mode", "epsilon"),
[
("Tests/images/vtf_i8.png", "Tests/images/vtf_i8.vtf", "L", 0.0),
("Tests/images/vtf_a8.png", "Tests/images/vtf_a8.vtf", "RGBA", 0.0),
("Tests/images/vtf_ia88.png", "Tests/images/vtf_ia88.vtf", "LA", 0.0),
("Tests/images/vtf_uv88.png", "Tests/images/vtf_uv88.vtf", "RGB", 0.0),
("Tests/images/vtf_rgb888.png", "Tests/images/vtf_rgb888.vtf", "RGB", 0.0),
("Tests/images/vtf_bgr888.png", "Tests/images/vtf_bgr888.vtf", "RGB", 0.0),
("Tests/images/vtf_dxt1.png", "Tests/images/vtf_dxt1.vtf", "RGBA", 3.0),
("Tests/images/vtf_dxt1A.png", "Tests/images/vtf_dxt1A.vtf", "RGBA", 8.0),
("Tests/images/vtf_rgba8888.png", "Tests/images/vtf_rgba8888.vtf", "RGBA", 0),
],
)
def test_vtf_read(etalon_path: str, file_path: str, expected_mode: str, epsilon: float):
e = Image.open(etalon_path)
f = Image.open(file_path)
assert f.mode == expected_mode
e = e.convert(expected_mode)
if epsilon == 0:
assert_image_equal(e, f)
else:
assert_image_similar(e, f, epsilon)


@pytest.mark.parametrize(
("pixel_format", "file_path", "expected_mode", "epsilon"),
[
(VtfPF.I8, "Tests/images/vtf_i8.png", "L", 0.0),
(VtfPF.A8, "Tests/images/vtf_a8.png", "RGBA", 0.0),
(VtfPF.IA88, "Tests/images/vtf_ia88.png", "LA", 0.0),
(VtfPF.UV88, "Tests/images/vtf_uv88.png", "RGB", 0.0),
(VtfPF.RGB888, "Tests/images/vtf_rgb888.png", "RGB", 0.0),
(VtfPF.BGR888, "Tests/images/vtf_bgr888.png", "RGB", 0.0),
(VtfPF.DXT1, "Tests/images/vtf_dxt1.png", "RGBA", 3.0),
(VtfPF.DXT1_ONEBITALPHA, "Tests/images/vtf_dxt1A.png", "RGBA", 8.0),
(VtfPF.RGBA8888, "Tests/images/vtf_rgba8888.png", "RGBA", 0),
],
)
def test_vtf_save(
pixel_format: VtfPF, file_path: str, expected_mode: str, epsilon: float, tmp_path
):
f: Image.Image = Image.open(file_path)
out = (tmp_path / "tmp.vtf").as_posix()
f.save(out, pixel_format=pixel_format)
if pixel_format == VtfPF.DXT1:
f = f.convert("RGBA")
e = Image.open(out)
assert e.mode == expected_mode
if epsilon == 0:
assert_image_equal(e, f)
else:
assert_image_similar(e, f, epsilon)
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def get_version():
"Reduce",
"Bands",
"BcnDecode",
"BcnEncode",
"BitDecode",
"Blend",
"Chops",
Expand Down
Loading
Loading