mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-04-16 07:12:00 +03:00
Added BC5 saving
This commit is contained in:
parent
b0315cc603
commit
cd11792c15
|
@ -402,7 +402,7 @@ def test_not_implemented(test_file: str) -> None:
|
|||
def test_save_unsupported_mode(tmp_path: Path) -> None:
|
||||
out = str(tmp_path / "temp.dds")
|
||||
im = hopper("HSV")
|
||||
with pytest.raises(OSError):
|
||||
with pytest.raises(OSError, match="cannot write mode HSV as DDS"):
|
||||
im.save(out)
|
||||
|
||||
|
||||
|
@ -424,6 +424,13 @@ def test_save(mode: str, test_file: str, tmp_path: Path) -> None:
|
|||
assert_image_equal_tofile(im, out)
|
||||
|
||||
|
||||
def test_save_unsupported_pixel_format(tmp_path: Path) -> None:
|
||||
out = str(tmp_path / "temp.dds")
|
||||
im = hopper()
|
||||
with pytest.raises(OSError, match="cannot write pixel format UNKNOWN"):
|
||||
im.save(out, pixel_format="UNKNOWN")
|
||||
|
||||
|
||||
def test_save_dxt1(tmp_path: Path) -> None:
|
||||
# RGB
|
||||
out = str(tmp_path / "temp.dds")
|
||||
|
@ -493,3 +500,14 @@ def test_save_dxt5(tmp_path: Path) -> None:
|
|||
im_la = im_rgba.convert("LA")
|
||||
im_la.save(out, pixel_format="DXT5")
|
||||
assert_image_similar_tofile(im_la.convert("RGBA"), out, 8.32)
|
||||
|
||||
|
||||
def test_save_dx10_bc5(tmp_path: Path) -> None:
|
||||
out = str(tmp_path / "temp.dds")
|
||||
with Image.open(TEST_FILE_DX10_BC5_TYPELESS) as im:
|
||||
im.save(out, pixel_format="BC5")
|
||||
assert_image_similar_tofile(im, out, 9.56)
|
||||
|
||||
im = hopper("L")
|
||||
with pytest.raises(OSError, match="only RGB mode can be written as BC5"):
|
||||
im.save(out, pixel_format="BC5")
|
||||
|
|
|
@ -530,7 +530,7 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
|||
bitcount = len(im.getbands()) * 8
|
||||
pixel_format = im.encoderinfo.get("pixel_format")
|
||||
args: tuple[int] | str
|
||||
if pixel_format in ("DXT1", "BC2", "DXT3", "BC3", "DXT5"):
|
||||
if pixel_format:
|
||||
codec_name = "bcn"
|
||||
flags |= DDSD.LINEARSIZE
|
||||
pitch = (im.width + 3) * 4
|
||||
|
@ -550,9 +550,18 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
|
|||
if pixel_format == "BC2":
|
||||
args = (2,)
|
||||
dxgi_format = DXGI_FORMAT.BC2_TYPELESS
|
||||
else:
|
||||
elif pixel_format == "BC3":
|
||||
args = (3,)
|
||||
dxgi_format = DXGI_FORMAT.BC3_TYPELESS
|
||||
elif pixel_format == "BC5":
|
||||
args = (5,)
|
||||
dxgi_format = DXGI_FORMAT.BC5_TYPELESS
|
||||
if im.mode != "RGB":
|
||||
msg = "only RGB mode can be written as BC5"
|
||||
raise OSError(msg)
|
||||
else:
|
||||
msg = f"cannot write pixel format {pixel_format}"
|
||||
raise OSError(msg)
|
||||
else:
|
||||
codec_name = "raw"
|
||||
flags |= DDSD.PITCH
|
||||
|
|
|
@ -185,7 +185,7 @@ encode_bc2_block(Imaging im, ImagingCodecState state, UINT8 *dst) {
|
|||
}
|
||||
|
||||
static void
|
||||
encode_bc3_alpha(Imaging im, ImagingCodecState state, UINT8 *dst) {
|
||||
encode_bc3_alpha(Imaging im, ImagingCodecState state, UINT8 *dst, int o) {
|
||||
int i, j;
|
||||
UINT8 alpha_min = 0, alpha_max = 0;
|
||||
UINT8 block[16], current_alpha;
|
||||
|
@ -202,7 +202,7 @@ encode_bc3_alpha(Imaging im, ImagingCodecState state, UINT8 *dst) {
|
|||
continue;
|
||||
}
|
||||
|
||||
current_alpha = (UINT8)im->image[y][x + 3];
|
||||
current_alpha = (UINT8)im->image[y][x + o];
|
||||
block[i + j * 4] = current_alpha;
|
||||
|
||||
if (first || current_alpha < alpha_min) {
|
||||
|
@ -226,12 +226,13 @@ encode_bc3_alpha(Imaging im, ImagingCodecState state, UINT8 *dst) {
|
|||
if (!current_alpha) {
|
||||
l |= 6 << (j * 3);
|
||||
continue;
|
||||
} else if (current_alpha == 255 || denom == 0) {
|
||||
} else if (current_alpha == 255) {
|
||||
l |= 7 << (j * 3);
|
||||
continue;
|
||||
}
|
||||
|
||||
float distance = abs(current_alpha - alpha_min) / denom * 10;
|
||||
float distance =
|
||||
denom == 0 ? 0 : abs(current_alpha - alpha_min) / denom * 10;
|
||||
if (distance < 3) {
|
||||
l |= 2 << (j * 3); // 4/5 * alpha_min + 1/5 * alpha_max
|
||||
} else if (distance < 5) {
|
||||
|
@ -257,21 +258,28 @@ ImagingBcnEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
|
|||
UINT8 *dst = buf;
|
||||
|
||||
for (;;) {
|
||||
if (n == 2 || n == 3) {
|
||||
if (has_alpha_channel) {
|
||||
if (n == 2) {
|
||||
encode_bc2_block(im, state, dst);
|
||||
if (n == 5) {
|
||||
encode_bc3_alpha(im, state, dst, 0);
|
||||
dst += 8;
|
||||
|
||||
encode_bc3_alpha(im, state, dst, 1);
|
||||
} else {
|
||||
if (n == 2 || n == 3) {
|
||||
if (has_alpha_channel) {
|
||||
if (n == 2) {
|
||||
encode_bc2_block(im, state, dst);
|
||||
} else {
|
||||
encode_bc3_alpha(im, state, dst, 3);
|
||||
}
|
||||
dst += 8;
|
||||
} else {
|
||||
encode_bc3_alpha(im, state, dst);
|
||||
}
|
||||
dst += 8;
|
||||
} else {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
*dst++ = 0xff;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
*dst++ = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
encode_bc1_color(im, state, dst, n == 1 && has_alpha_channel);
|
||||
}
|
||||
encode_bc1_color(im, state, dst, n == 1 && has_alpha_channel);
|
||||
dst += 8;
|
||||
|
||||
state->x += im->pixelsize * 4;
|
||||
|
|
Loading…
Reference in New Issue
Block a user