diff --git a/Tests/images/dxt5-colorblock-alpha-issue-4142.dds b/Tests/images/dxt5-colorblock-alpha-issue-4142.dds new file mode 100644 index 00000000000..905527eada4 Binary files /dev/null and b/Tests/images/dxt5-colorblock-alpha-issue-4142.dds differ diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index 1cd7a1be75c..5651c2e4d58 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -190,6 +190,21 @@ def short_file(): short_file() +def test_dxt5_colorblock_alpha_issue_4142(): + """ Check that colorblocks are decoded correctly in DXT5""" + + with Image.open("Tests/images/dxt5-colorblock-alpha-issue-4142.dds") as im: + px = im.getpixel((0, 0)) + assert px[0] != 0 + assert px[1] != 0 + assert px[2] != 0 + + px = im.getpixel((1, 0)) + assert px[0] != 0 + assert px[1] != 0 + assert px[2] != 0 + + def test_unimplemented_pixel_format(): with pytest.raises(NotImplementedError): Image.open("Tests/images/unimplemented_pixel_format.dds") diff --git a/src/libImaging/BcnDecode.c b/src/libImaging/BcnDecode.c index b6a4cbadcc5..5e8b456b83e 100644 --- a/src/libImaging/BcnDecode.c +++ b/src/libImaging/BcnDecode.c @@ -69,7 +69,7 @@ decode_565(UINT16 x) { } static void -decode_bc1_color(rgba *dst, const UINT8 *src) { +decode_bc1_color(rgba *dst, const UINT8 *src, int separate_alpha) { bc1_color col; rgba p[4]; int n, cw; @@ -84,7 +84,10 @@ decode_bc1_color(rgba *dst, const UINT8 *src) { r1 = p[1].r; g1 = p[1].g; b1 = p[1].b; - if (col.c0 > col.c1) { + + + /* NOTE: BC2 and BC3 reuse BC1 color blocks but always act like c0 > c1 */ + if (col.c0 > col.c1 || separate_alpha) { p[2].r = (2 * r0 + 1 * r1) / 3; p[2].g = (2 * g0 + 1 * g1) / 3; p[2].b = (2 * b0 + 1 * b1) / 3; @@ -150,13 +153,13 @@ decode_bc3_alpha(char *dst, const UINT8 *src, int stride, int o) { static void decode_bc1_block(rgba *col, const UINT8 *src) { - decode_bc1_color(col, src); + decode_bc1_color(col, src, 0); } static void decode_bc2_block(rgba *col, const UINT8 *src) { int n, bitI, byI, av; - decode_bc1_color(col, src + 8); + decode_bc1_color(col, src + 8, 1); for (n = 0; n < 16; n++) { bitI = n * 4; byI = bitI >> 3; @@ -168,7 +171,7 @@ decode_bc2_block(rgba *col, const UINT8 *src) { static void decode_bc3_block(rgba *col, const UINT8 *src) { - decode_bc1_color(col, src + 8); + decode_bc1_color(col, src + 8, 1); decode_bc3_alpha((char *)col, src, sizeof(col[0]), 3); }