From 8c5d5c7e6b597cef2b5a39417ddc457f91015f9f Mon Sep 17 00:00:00 2001 From: Sam Bourne Date: Mon, 4 Dec 2023 09:54:10 -0800 Subject: [PATCH 1/3] Add support for BC4 dds files --- Tests/images/bc4_unorm.dds | Bin 0 -> 2892 bytes Tests/test_file_dds.py | 12 ++++++++++++ src/PIL/DdsImagePlugin.py | 8 +++++++- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 Tests/images/bc4_unorm.dds diff --git a/Tests/images/bc4_unorm.dds b/Tests/images/bc4_unorm.dds new file mode 100644 index 0000000000000000000000000000000000000000..13da711bd13d456406188b445a9668c40fc8604e GIT binary patch literal 2892 zcmc(gZA@EL7{?E7DSct|);cnZYs~zUyX*C#EPkVe!y>w3I2X3C5 z-#P#Dod0u9@42@ILxrXZA(Tc*kRCI3BN0L=7-_Ngf4H95Us)K-*Wg=#Z$q_Ci?Qqy zQTk=tUaau{Qez&_UY3|3r1y<}^SsQ#C_msiJ~`UEQ4!pGnN6jPnS(Ow!swPq<#R~y zta7t!Lw;8U(ijy#TCa8?x?dK+y1(-&ibbZa)~g5Zj}#vnz~hi7pT^^j;emuwNt?<+ zleA=?=b?1AG8eU0!ikjpAwxdr#QV zSr7Argy-^o{+ty2X48k_ez!y&EBxM5++)?;X9Lp(aIprhG*OVEHO`5wQm5;PbTM_a-l9MCM@SqBq!@pR8d$v9+L^9^ znAx*$$TAxe^MyXFXDwJKx{#o|Jc!5rE(PQ*ibl^g;_)aF-6y~S^m@rMfJqm%0ug+H z;0pvD2s&^DrIMzCFA#izpabo8VgpQSx&je=f#3@S9SAyb1*MXvf-ew!fow!}i^4H8 z*3n#y!_!vXyd8(>Sk41uIFgzsh^Ax0gIXM(wxA;e$IMvVPR2&e87z*w`QL3kp;Xf5 z|E(YOk$n%h657fMb%-!&(F9S4$bN0*gu|_bQ6KQ%{a3rbcZjU-!#?ud-7eB^ZzcVf zquu<6an#oky{wu%=iI`R>nCx*dvwoS<@)x+WPgV&gik+7_PIw-Sh9uan^dH)Ttg^E zukiA5z*d7RKKh3^)DN)|E&GOCzyVGF<4l%pPrAn>F;i|yj}2y>Do5c zaGraK3FB-*Mq@q%f;Ij zot9~}DlFZ+k>;Kot{=D0&4)hx{@i?SpPRolPR@D1mg4JhaP#}MZ&4B)OXK9+bMwPa zavm57A$L9_A>V2R zZ|3%yB|5nRbdS*?tP59^H3{**3}$?u(MbbOjuh1%Ze2fl%A0+Wv02h4k$FSD(qCHs e{bMbe%m`z8@8#@A>UYxbG}I{tI8L7?mHq^9EXXbZ literal 0 HcmV?d00001 diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index bb9af7967b7..85a3ae172b9 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -12,6 +12,7 @@ TEST_FILE_DXT5 = "Tests/images/dxt5-argb-8bbp-interpolatedalpha_MipMaps-1.dds" TEST_FILE_ATI1 = "Tests/images/ati1.dds" TEST_FILE_ATI2 = "Tests/images/ati2.dds" +TEST_FILE_DX10_BC4_UNORM = "Tests/images/bc4_unorm.dds" TEST_FILE_DX10_BC5_TYPELESS = "Tests/images/bc5_typeless.dds" TEST_FILE_DX10_BC5_UNORM = "Tests/images/bc5_unorm.dds" TEST_FILE_DX10_BC5_SNORM = "Tests/images/bc5_snorm.dds" @@ -82,6 +83,17 @@ def test_sanity_ati1(): assert_image_equal_tofile(im, TEST_FILE_ATI1.replace(".dds", ".png")) +def test_dx10_bc4(): + """Check DX10 BC4 images can be opened""" + + with Image.open(TEST_FILE_DX10_BC4_UNORM) as im: + im.load() + + assert im.format == "DDS" + assert im.mode == "L" + assert im.size == (64, 64) + + @pytest.mark.parametrize( "image_path", ( diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 54f358c7f9a..faf6a4e436c 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -98,6 +98,8 @@ DXGI_FORMAT_R8G8B8A8_TYPELESS = 27 DXGI_FORMAT_R8G8B8A8_UNORM = 28 DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29 +DXGI_FORMAT_BC4_TYPELESS = 79 +DXGI_FORMAT_BC4_UNORM = 80 DXGI_FORMAT_BC5_TYPELESS = 82 DXGI_FORMAT_BC5_UNORM = 83 DXGI_FORMAT_BC5_SNORM = 84 @@ -190,7 +192,11 @@ def _open(self): # ignoring flags which pertain to volume textures and cubemaps (dxgi_format,) = struct.unpack(" Date: Tue, 5 Dec 2023 07:18:07 +1100 Subject: [PATCH 2/3] Added expected test image --- Tests/images/bc4_unorm.png | Bin 0 -> 982 bytes Tests/test_file_dds.py | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 Tests/images/bc4_unorm.png diff --git a/Tests/images/bc4_unorm.png b/Tests/images/bc4_unorm.png new file mode 100644 index 0000000000000000000000000000000000000000..71d536c8453b16874c3ce777555fbbfb55667b60 GIT binary patch literal 982 zcmV;{11bE8P)Nkl{&&0I4LMzU^Z`fk+h$&Ba&uZxQX24%V_Mos1e zp@dH8U8jqbF~ejnGe*|<=z|YFXkw-*E^KpaI|}Vx|30)V+EX_Z%ofw{KbPFY_xHK) z_xDc@s1v134Z2(|q4&~NmUK9Hp64@pHrc!UtI*!w-fpwmQtK?*m&vn9p67W}J>Ueq zv;9|qCcob?|JETe0EcNbG3bBfR0%*c@S-%Op77IX;$ZzS05FwO7n=)S5(L5FU~K8> zrJqGn6a_)(UHpkHK9$Pa>~_0d6h-j|c7AVjJs>gLiyO&z-tcz=MPUBD;cj;TfCh~0 z@?MCH`K9jGns?XdZ@+1%5IlMX`X^%n=>xz7&-hRuzWf#d2fQqO{LzPA_ZQ!lYTidj zk3DOs;Bv8KkW$*V=VF$9*3lsdf{&2)VGzlu%}sDWWKfh6+0|e{yUH zV8;W}-1ttE0mx1@cDzRlu&O2CRAUj@sm8q3rT$qSoIDx`04yM-#*dsq1%OkHMSRl5 zK(SiIU7L@*|5t#$cqL@^14T)Rk9)rd04VX{4oh-sUlBknkW>eHpu~qe_82b_cp=Gg zEeGdsGmFL2))s#*v&s}oDdjls7K?{g^7%P4A%sv$Y5bYxTZROOLozC_?T6w47-k1$ zryBDBU;vcUBQjDGojYpY$z!{X6+-AlWj|7JFTgP9b*iyQ1b`V>K0PA4k`u2_v;fcn z9NCTY1^``n2z=Yw>F^A&1CQgJI?&?=U;-uv9>cj);jVPKmMDmH!T?x!_a&^KoqpBl z12`Zx)xQtE>cF8VupA9{xw`TIDgcm<_8XSy@i6u&$8lWzz}JOBOA8@{gf3^<%z>{6 zA%sYh)c4I*mIz(WGLGXoLjnK`(>{RB4Ed1iL=%8fSyJO+ucryXZ$MafoS7b#B~=Ds zVzraLv&4T^z2Ce=xXauf)%(p`#CrwQ`x^MMx05GL>t)lC?rt9U3rs-w9q-mSwO|4j7UoYJJ5$U@C z?tg^_U_1T?D Date: Tue, 5 Dec 2023 07:39:15 +1100 Subject: [PATCH 3/3] Added test BC4 TYPELESS image --- Tests/images/bc4_typeless.dds | Bin 0 -> 2892 bytes Tests/test_file_dds.py | 13 +++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 Tests/images/bc4_typeless.dds diff --git a/Tests/images/bc4_typeless.dds b/Tests/images/bc4_typeless.dds new file mode 100644 index 0000000000000000000000000000000000000000..27f87889f43d5b5054f3971c412a594dc4dc161e GIT binary patch literal 2892 zcmc(gZA@EL7{?E7DSct|);cnZYs~zUyX*C#EPkVe!y>w3I2X3C5 z-#P#Dod0u9@42@ILxrXZA(Tc*kRCI3BN0L=7-_Ngf4CmoS6LX#*Wg=#Z$q_Ci?Qqy zQTk=t<5=PUrN%s;BHCC>EKvTCeQCH&T3f0FOhSd>W58h6fT#C2cAP zP12IRo(Iy|%3RcbmXWae;_cSYyxH$Fi|9=6OA!VC934G4Ww<&u(N$dEBW7v0(BIx5 zA0Ol)r-u>GHHy2PA797g=M?#-ZIBmQ`@17HFKN*PF(jG~lN8h{vNybdLZB(Ca13048133PkV) zf-ewsAn3pqluDWkzCiE=f)2FXi48ER=?X;f1%fXSbRg)!6_iSv3cf(_1+o#@O$x`% zSVwa)4o_Qk^L8AjqdE7D;YezlAexQ}4`^|C+JcS@95Z8aI~f}>XRtW#E^s;L5oO26Lte?aI@6lazmFwFNk^LRC5I+4R+2C*S~DI_Otd2pJ4jY#b9C4K6*alroX%1@^--+rmNdj z!+Gu{CaCLpv%6D#i#z|Cnto08)4Cmj4O_o`=Ea(v1r1Izbc$H@{BQESUH1pGEf;Q8 zbXum>s<3qPMw)wWxPII|Hy`@&`*ZWTeQy5JI63G2T8gj3!Oid2zC}rJERB}z z$$4NTgxvXzgnS3WPT)WDN8UB_i*WRuCg-gA09ntbD)Rk>_1=!hpCx`f_s>!pICiMX z{B?-hTKa3i;H@04qhHYMu4=znJGVRMn7-d@#~FGa4S7J&Z{$*IzQ(0M zzmeN#mgwXP&^<G9!%Xy_d5es^3Y!(@>`r;5c=PRQeNTV8|^1 literal 0 HcmV?d00001 diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index 337f541f6a6..e9fb045887b 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -12,6 +12,7 @@ TEST_FILE_DXT5 = "Tests/images/dxt5-argb-8bbp-interpolatedalpha_MipMaps-1.dds" TEST_FILE_ATI1 = "Tests/images/ati1.dds" TEST_FILE_ATI2 = "Tests/images/ati2.dds" +TEST_FILE_DX10_BC4_TYPELESS = "Tests/images/bc4_typeless.dds" TEST_FILE_DX10_BC4_UNORM = "Tests/images/bc4_unorm.dds" TEST_FILE_DX10_BC5_TYPELESS = "Tests/images/bc5_typeless.dds" TEST_FILE_DX10_BC5_UNORM = "Tests/images/bc5_unorm.dds" @@ -83,10 +84,18 @@ def test_sanity_ati1(): assert_image_equal_tofile(im, TEST_FILE_ATI1.replace(".dds", ".png")) -def test_dx10_bc4(): +@pytest.mark.parametrize( + "image_path", + ( + TEST_FILE_DX10_BC4_UNORM, + # hexeditted to be typeless + TEST_FILE_DX10_BC4_TYPELESS, + ), +) +def test_dx10_bc4(image_path): """Check DX10 BC4 images can be opened""" - with Image.open(TEST_FILE_DX10_BC4_UNORM) as im: + with Image.open(image_path) as im: im.load() assert im.format == "DDS"