mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-10 19:56:47 +03:00
Add support for BC7 to DdsImagePlugin
This commit is contained in:
parent
b46804ea27
commit
2be760ca79
|
@ -93,6 +93,13 @@ DXT3_FOURCC = 0x33545844
|
||||||
DXT5_FOURCC = 0x35545844
|
DXT5_FOURCC = 0x35545844
|
||||||
|
|
||||||
|
|
||||||
|
# dxgiformat.h
|
||||||
|
|
||||||
|
DXGI_FORMAT_BC7_TYPELESS = 97
|
||||||
|
DXGI_FORMAT_BC7_UNORM = 98
|
||||||
|
DXGI_FORMAT_BC7_UNORM_SRGB = 99
|
||||||
|
|
||||||
|
|
||||||
class DdsImageFile(ImageFile.ImageFile):
|
class DdsImageFile(ImageFile.ImageFile):
|
||||||
format = "DDS"
|
format = "DDS"
|
||||||
format_description = "DirectDraw Surface"
|
format_description = "DirectDraw Surface"
|
||||||
|
@ -119,6 +126,8 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
bitcount, rmask, gmask, bmask, amask = struct.unpack("<5I",
|
bitcount, rmask, gmask, bmask, amask = struct.unpack("<5I",
|
||||||
header.read(20))
|
header.read(20))
|
||||||
|
|
||||||
|
data_start = header_size + 4
|
||||||
|
n = 0
|
||||||
if fourcc == b"DXT1":
|
if fourcc == b"DXT1":
|
||||||
self.pixel_format = "DXT1"
|
self.pixel_format = "DXT1"
|
||||||
n = 1
|
n = 1
|
||||||
|
@ -128,12 +137,27 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
elif fourcc == b"DXT5":
|
elif fourcc == b"DXT5":
|
||||||
self.pixel_format = "DXT5"
|
self.pixel_format = "DXT5"
|
||||||
n = 3
|
n = 3
|
||||||
|
elif fourcc == b"DX10":
|
||||||
|
data_start += 20
|
||||||
|
# ignoring flags which pertain to volume textures and cubemaps
|
||||||
|
dxt10 = BytesIO(self.fp.read(20))
|
||||||
|
dxgi_format, dimension = struct.unpack("<II", dxt10.read(8))
|
||||||
|
if dxgi_format in (DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM):
|
||||||
|
self.pixel_format = "BC7"
|
||||||
|
n = 7
|
||||||
|
elif dxgi_format == DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||||
|
self.pixel_format = "BC7"
|
||||||
|
self.im_info["gamma"] = 1/2.2
|
||||||
|
n = 7
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("Unimplemented DXGI format %d" %
|
||||||
|
(dxgi_format))
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("Unimplemented pixel format %r" %
|
raise NotImplementedError("Unimplemented pixel format %r" %
|
||||||
(fourcc))
|
(fourcc))
|
||||||
|
|
||||||
self.tile = [
|
self.tile = [
|
||||||
("bcn", (0, 0) + self.size, 4 + header_size, (n))
|
("bcn", (0, 0) + self.size, data_start, (n))
|
||||||
]
|
]
|
||||||
|
|
||||||
def load_seek(self, pos):
|
def load_seek(self, pos):
|
||||||
|
|
BIN
Tests/images/bc7-argb-8bpp_MipMaps-1.dds
Normal file
BIN
Tests/images/bc7-argb-8bpp_MipMaps-1.dds
Normal file
Binary file not shown.
BIN
Tests/images/bc7-argb-8bpp_MipMaps-1.png
Normal file
BIN
Tests/images/bc7-argb-8bpp_MipMaps-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 122 KiB |
|
@ -6,6 +6,7 @@ from PIL import Image, DdsImagePlugin
|
||||||
TEST_FILE_DXT1 = "Tests/images/dxt1-rgb-4bbp-noalpha_MipMaps-1.dds"
|
TEST_FILE_DXT1 = "Tests/images/dxt1-rgb-4bbp-noalpha_MipMaps-1.dds"
|
||||||
TEST_FILE_DXT3 = "Tests/images/dxt3-argb-8bbp-explicitalpha_MipMaps-1.dds"
|
TEST_FILE_DXT3 = "Tests/images/dxt3-argb-8bbp-explicitalpha_MipMaps-1.dds"
|
||||||
TEST_FILE_DXT5 = "Tests/images/dxt5-argb-8bbp-interpolatedalpha_MipMaps-1.dds"
|
TEST_FILE_DXT5 = "Tests/images/dxt5-argb-8bbp-interpolatedalpha_MipMaps-1.dds"
|
||||||
|
TEST_FILE_DX10_BC7 = "Tests/images/bc7-argb-8bpp_MipMaps-1.dds"
|
||||||
|
|
||||||
|
|
||||||
class TestFileDds(PillowTestCase):
|
class TestFileDds(PillowTestCase):
|
||||||
|
@ -52,6 +53,20 @@ class TestFileDds(PillowTestCase):
|
||||||
|
|
||||||
self.assert_image_equal(target, im)
|
self.assert_image_equal(target, im)
|
||||||
|
|
||||||
|
def test_dx10_bc7(self):
|
||||||
|
"""Check DX10 images can be opened"""
|
||||||
|
|
||||||
|
target = Image.open(TEST_FILE_DX10_BC7.replace('.dds', '.png'))
|
||||||
|
|
||||||
|
im = Image.open(TEST_FILE_DX10_BC7)
|
||||||
|
im.load()
|
||||||
|
|
||||||
|
self.assertEqual(im.format, "DDS")
|
||||||
|
self.assertEqual(im.mode, "RGBA")
|
||||||
|
self.assertEqual(im.size, (256, 256))
|
||||||
|
|
||||||
|
self.assert_image_equal(target, im)
|
||||||
|
|
||||||
def test__validate_true(self):
|
def test__validate_true(self):
|
||||||
"""Check valid prefix"""
|
"""Check valid prefix"""
|
||||||
# Arrange
|
# Arrange
|
||||||
|
|
|
@ -327,10 +327,10 @@ static UINT8 expand_quantized(UINT8 v, int bits) {
|
||||||
static void bc7_lerp(rgba *dst, const rgba *e, int s0, int s1) {
|
static void bc7_lerp(rgba *dst, const rgba *e, int s0, int s1) {
|
||||||
int t0 = 64 - s0;
|
int t0 = 64 - s0;
|
||||||
int t1 = 64 - s1;
|
int t1 = 64 - s1;
|
||||||
dst->r = (UINT8)((t0 * e[0].r + s0 * e[1].r) >> 6);
|
dst->r = (UINT8)((t0 * e[0].r + s0 * e[1].r + 32) >> 6);
|
||||||
dst->g = (UINT8)((t0 * e[0].g + s0 * e[1].g) >> 6);
|
dst->g = (UINT8)((t0 * e[0].g + s0 * e[1].g + 32) >> 6);
|
||||||
dst->b = (UINT8)((t0 * e[0].b + s0 * e[1].b) >> 6);
|
dst->b = (UINT8)((t0 * e[0].b + s0 * e[1].b + 32) >> 6);
|
||||||
dst->a = (UINT8)((t1 * e[0].a + s1 * e[1].a) >> 6);
|
dst->a = (UINT8)((t1 * e[0].a + s1 * e[1].a + 32) >> 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_bc7_block(rgba *col, const UINT8* src) {
|
static void decode_bc7_block(rgba *col, const UINT8* src) {
|
||||||
|
@ -359,7 +359,7 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
|
||||||
cb = info->cb;
|
cb = info->cb;
|
||||||
ab = info->ab;
|
ab = info->ab;
|
||||||
cw = bc7_get_weights(info->ib);
|
cw = bc7_get_weights(info->ib);
|
||||||
aw = bc7_get_weights(ab ? info->ib2 : info->ib);
|
aw = bc7_get_weights((ab && info->ib2) ? info->ib2 : info->ib);
|
||||||
|
|
||||||
#define LOAD(DST, N) \
|
#define LOAD(DST, N) \
|
||||||
DST = get_bits(src, bit, N); \
|
DST = get_bits(src, bit, N); \
|
||||||
|
@ -401,29 +401,33 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
|
||||||
#define ASSIGN_P(x) x = (x << 1) | val
|
#define ASSIGN_P(x) x = (x << 1) | val
|
||||||
if (info->epb) {
|
if (info->epb) {
|
||||||
/* per endpoint */
|
/* per endpoint */
|
||||||
|
cb++;
|
||||||
|
if (ab) {
|
||||||
|
ab++;
|
||||||
|
}
|
||||||
for (i = 0; i < numep; i++) {
|
for (i = 0; i < numep; i++) {
|
||||||
LOAD(val, 1);
|
LOAD(val, 1);
|
||||||
cb++;
|
|
||||||
ASSIGN_P(endpoints[i].r);
|
ASSIGN_P(endpoints[i].r);
|
||||||
ASSIGN_P(endpoints[i].g);
|
ASSIGN_P(endpoints[i].g);
|
||||||
ASSIGN_P(endpoints[i].b);
|
ASSIGN_P(endpoints[i].b);
|
||||||
if (ab) {
|
if (ab) {
|
||||||
ab++;
|
|
||||||
ASSIGN_P(endpoints[i].a);
|
ASSIGN_P(endpoints[i].a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info->spb) {
|
if (info->spb) {
|
||||||
/* per subset */
|
/* per subset */
|
||||||
|
cb++;
|
||||||
|
if (ab) {
|
||||||
|
ab++;
|
||||||
|
}
|
||||||
for (i = 0; i < numep; i+=2) {
|
for (i = 0; i < numep; i+=2) {
|
||||||
LOAD(val, 1);
|
LOAD(val, 1);
|
||||||
cb++;
|
|
||||||
for (j = 0; j < 2; j++) {
|
for (j = 0; j < 2; j++) {
|
||||||
ASSIGN_P(endpoints[i+j].r);
|
ASSIGN_P(endpoints[i+j].r);
|
||||||
ASSIGN_P(endpoints[i+j].g);
|
ASSIGN_P(endpoints[i+j].g);
|
||||||
ASSIGN_P(endpoints[i+j].b);
|
ASSIGN_P(endpoints[i+j].b);
|
||||||
if (ab) {
|
if (ab) {
|
||||||
ab++;
|
|
||||||
ASSIGN_P(endpoints[i+j].a);
|
ASSIGN_P(endpoints[i+j].a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,7 +466,7 @@ static void decode_bc7_block(rgba *col, const UINT8* src) {
|
||||||
i0 = get_bits(src, cibit, ib);
|
i0 = get_bits(src, cibit, ib);
|
||||||
cibit += ib;
|
cibit += ib;
|
||||||
|
|
||||||
if (ab) {
|
if (ab && info->ib2) {
|
||||||
ib2 = info->ib2;
|
ib2 = info->ib2;
|
||||||
if (ib2 && i == 0) {
|
if (ib2 && i == 0) {
|
||||||
ib2--;
|
ib2--;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user