mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-09 06:13:30 +03:00
Added BC3 loading and saving
This commit is contained in:
parent
9430bbe5a1
commit
9f619b814f
|
@ -12,6 +12,7 @@ from PIL import DdsImagePlugin, Image
|
||||||
from .helper import (
|
from .helper import (
|
||||||
assert_image_equal,
|
assert_image_equal,
|
||||||
assert_image_equal_tofile,
|
assert_image_equal_tofile,
|
||||||
|
assert_image_similar,
|
||||||
assert_image_similar_tofile,
|
assert_image_similar_tofile,
|
||||||
hopper,
|
hopper,
|
||||||
)
|
)
|
||||||
|
@ -114,6 +115,19 @@ def test_sanity_ati1_bc4u(image_path: str) -> None:
|
||||||
assert_image_equal_tofile(im, TEST_FILE_ATI1.replace(".dds", ".png"))
|
assert_image_equal_tofile(im, TEST_FILE_ATI1.replace(".dds", ".png"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_dx10_bc3(tmp_path: Path) -> None:
|
||||||
|
out = str(tmp_path / "temp.dds")
|
||||||
|
with Image.open(TEST_FILE_DXT5) as im:
|
||||||
|
im.save(out, pixel_format="BC3")
|
||||||
|
|
||||||
|
with Image.open(out) as reloaded:
|
||||||
|
assert reloaded.format == "DDS"
|
||||||
|
assert reloaded.mode == "RGBA"
|
||||||
|
assert reloaded.size == (256, 256)
|
||||||
|
|
||||||
|
assert_image_similar(im, reloaded, 3.69)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"image_path",
|
"image_path",
|
||||||
(
|
(
|
||||||
|
|
|
@ -419,6 +419,10 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
self._mode = "RGBA"
|
self._mode = "RGBA"
|
||||||
self.pixel_format = "BC1"
|
self.pixel_format = "BC1"
|
||||||
n = 1
|
n = 1
|
||||||
|
elif dxgi_format in (DXGI_FORMAT.BC3_TYPELESS, DXGI_FORMAT.BC3_UNORM):
|
||||||
|
self._mode = "RGBA"
|
||||||
|
self.pixel_format = "BC3"
|
||||||
|
n = 3
|
||||||
elif dxgi_format in (DXGI_FORMAT.BC4_TYPELESS, DXGI_FORMAT.BC4_UNORM):
|
elif dxgi_format in (DXGI_FORMAT.BC4_TYPELESS, DXGI_FORMAT.BC4_UNORM):
|
||||||
self._mode = "L"
|
self._mode = "L"
|
||||||
self.pixel_format = "BC4"
|
self.pixel_format = "BC4"
|
||||||
|
@ -521,14 +525,18 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
flags = DDSD.CAPS | DDSD.HEIGHT | DDSD.WIDTH | DDSD.PIXELFORMAT
|
flags = DDSD.CAPS | DDSD.HEIGHT | DDSD.WIDTH | DDSD.PIXELFORMAT
|
||||||
bitcount = len(im.getbands()) * 8
|
bitcount = len(im.getbands()) * 8
|
||||||
pixel_format = im.encoderinfo.get("pixel_format")
|
pixel_format = im.encoderinfo.get("pixel_format")
|
||||||
if pixel_format in ("DXT1", "DXT5"):
|
if pixel_format in ("DXT1", "BC3", "DXT5"):
|
||||||
codec_name = "bcn"
|
codec_name = "bcn"
|
||||||
flags |= DDSD.LINEARSIZE
|
flags |= DDSD.LINEARSIZE
|
||||||
pitch = (im.width + 3) * 4
|
pitch = (im.width + 3) * 4
|
||||||
args = pixel_format
|
args = pixel_format
|
||||||
rgba_mask = [0, 0, 0, 0]
|
rgba_mask = [0, 0, 0, 0]
|
||||||
pixel_flags = DDPF.FOURCC
|
pixel_flags = DDPF.FOURCC
|
||||||
fourcc = D3DFMT.DXT1 if pixel_format == "DXT1" else D3DFMT.DXT5
|
fourcc = {"DXT1": D3DFMT.DXT1, "BC3": D3DFMT.DX10, "DXT5": D3DFMT.DXT5}[
|
||||||
|
pixel_format
|
||||||
|
]
|
||||||
|
if fourcc == D3DFMT.DX10:
|
||||||
|
dxgi_format = DXGI_FORMAT.BC3_TYPELESS
|
||||||
else:
|
else:
|
||||||
codec_name = "raw"
|
codec_name = "raw"
|
||||||
flags |= DDSD.PITCH
|
flags |= DDSD.PITCH
|
||||||
|
@ -573,6 +581,11 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
||||||
+ struct.pack("<4I", *rgba_mask) # dwRGBABitMask
|
+ struct.pack("<4I", *rgba_mask) # dwRGBABitMask
|
||||||
+ struct.pack("<5I", DDSCAPS.TEXTURE, 0, 0, 0, 0)
|
+ struct.pack("<5I", DDSCAPS.TEXTURE, 0, 0, 0, 0)
|
||||||
)
|
)
|
||||||
|
if fourcc == D3DFMT.DX10:
|
||||||
|
fp.write(
|
||||||
|
# dxgi_format, 2D resource, misc, array size, straight alpha
|
||||||
|
struct.pack("<5I", dxgi_format, 3, 0, 0, 1)
|
||||||
|
)
|
||||||
ImageFile._save(im, fp, [ImageFile._Tile(codec_name, (0, 0) + im.size, 0, args)])
|
ImageFile._save(im, fp, [ImageFile._Tile(codec_name, (0, 0) + im.size, 0, args)])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,7 @@ encode_bc3_alpha(Imaging im, ImagingCodecState state, UINT8 *dst) {
|
||||||
int
|
int
|
||||||
ImagingBcnEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
ImagingBcnEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
||||||
char *pixel_format = ((BCNSTATE *)state->context)->pixel_format;
|
char *pixel_format = ((BCNSTATE *)state->context)->pixel_format;
|
||||||
int n = strcmp(pixel_format, "DXT5") == 0 ? 3 : 1;
|
int n = strcmp(pixel_format, "DXT1") == 0 ? 1 : 3;
|
||||||
int has_alpha_channel =
|
int has_alpha_channel =
|
||||||
strcmp(im->mode, "RGBA") == 0 || strcmp(im->mode, "LA") == 0;
|
strcmp(im->mode, "RGBA") == 0 || strcmp(im->mode, "LA") == 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user