99
1010from PIL import DdsImagePlugin , Image
1111
12- from .helper import assert_image_equal , assert_image_equal_tofile , hopper
12+ from .helper import (
13+ assert_image_equal ,
14+ assert_image_equal_tofile ,
15+ assert_image_similar ,
16+ assert_image_similar_tofile ,
17+ hopper ,
18+ )
1319
1420TEST_FILE_DXT1 = "Tests/images/dxt1-rgb-4bbp-noalpha_MipMaps-1.dds"
1521TEST_FILE_DXT3 = "Tests/images/dxt3-argb-8bbp-explicitalpha_MipMaps-1.dds"
@@ -109,6 +115,32 @@ def test_sanity_ati1_bc4u(image_path: str) -> None:
109115 assert_image_equal_tofile (im , TEST_FILE_ATI1 .replace (".dds" , ".png" ))
110116
111117
118+ def test_dx10_bc2 (tmp_path : Path ) -> None :
119+ out = str (tmp_path / "temp.dds" )
120+ with Image .open (TEST_FILE_DXT3 ) as im :
121+ im .save (out , pixel_format = "BC2" )
122+
123+ with Image .open (out ) as reloaded :
124+ assert reloaded .format == "DDS"
125+ assert reloaded .mode == "RGBA"
126+ assert reloaded .size == (256 , 256 )
127+
128+ assert_image_similar (im , reloaded , 3.81 )
129+
130+
131+ def test_dx10_bc3 (tmp_path : Path ) -> None :
132+ out = str (tmp_path / "temp.dds" )
133+ with Image .open (TEST_FILE_DXT5 ) as im :
134+ im .save (out , pixel_format = "BC3" )
135+
136+ with Image .open (out ) as reloaded :
137+ assert reloaded .format == "DDS"
138+ assert reloaded .mode == "RGBA"
139+ assert reloaded .size == (256 , 256 )
140+
141+ assert_image_similar (im , reloaded , 3.69 )
142+
143+
112144@pytest .mark .parametrize (
113145 "image_path" ,
114146 (
@@ -370,7 +402,7 @@ def test_not_implemented(test_file: str) -> None:
370402def test_save_unsupported_mode (tmp_path : Path ) -> None :
371403 out = str (tmp_path / "temp.dds" )
372404 im = hopper ("HSV" )
373- with pytest .raises (OSError ):
405+ with pytest .raises (OSError , match = "cannot write mode HSV as DDS" ):
374406 im .save (out )
375407
376408
@@ -389,5 +421,93 @@ def test_save(mode: str, test_file: str, tmp_path: Path) -> None:
389421 assert im .mode == mode
390422 im .save (out )
391423
392- with Image .open (out ) as reloaded :
393- assert_image_equal (im , reloaded )
424+ assert_image_equal_tofile (im , out )
425+
426+
427+ def test_save_unsupported_pixel_format (tmp_path : Path ) -> None :
428+ out = str (tmp_path / "temp.dds" )
429+ im = hopper ()
430+ with pytest .raises (OSError , match = "cannot write pixel format UNKNOWN" ):
431+ im .save (out , pixel_format = "UNKNOWN" )
432+
433+
434+ def test_save_dxt1 (tmp_path : Path ) -> None :
435+ # RGB
436+ out = str (tmp_path / "temp.dds" )
437+ with Image .open (TEST_FILE_DXT1 ) as im :
438+ im .convert ("RGB" ).save (out , pixel_format = "DXT1" )
439+ assert_image_similar_tofile (im , out , 1.84 )
440+
441+ # RGBA
442+ im_alpha = im .copy ()
443+ im_alpha .putpixel ((0 , 0 ), (0 , 0 , 0 , 0 ))
444+ im_alpha .save (out , pixel_format = "DXT1" )
445+ with Image .open (out ) as reloaded :
446+ assert reloaded .getpixel ((0 , 0 )) == (0 , 0 , 0 , 0 )
447+
448+ # L
449+ im_l = im .convert ("L" )
450+ im_l .save (out , pixel_format = "DXT1" )
451+ assert_image_similar_tofile (im_l .convert ("RGBA" ), out , 6.07 )
452+
453+ # LA
454+ im_alpha .convert ("LA" ).save (out , pixel_format = "DXT1" )
455+ with Image .open (out ) as reloaded :
456+ assert reloaded .getpixel ((0 , 0 )) == (0 , 0 , 0 , 0 )
457+
458+
459+ def test_save_dxt3 (tmp_path : Path ) -> None :
460+ # RGB
461+ out = str (tmp_path / "temp.dds" )
462+ with Image .open (TEST_FILE_DXT3 ) as im :
463+ im_rgb = im .convert ("RGB" )
464+ im_rgb .save (out , pixel_format = "DXT3" )
465+ assert_image_similar_tofile (im_rgb .convert ("RGBA" ), out , 1.26 )
466+
467+ # RGBA
468+ im .save (out , pixel_format = "DXT3" )
469+ assert_image_similar_tofile (im , out , 3.81 )
470+
471+ # L
472+ im_l = im .convert ("L" )
473+ im_l .save (out , pixel_format = "DXT3" )
474+ assert_image_similar_tofile (im_l .convert ("RGBA" ), out , 5.89 )
475+
476+ # LA
477+ im_la = im .convert ("LA" )
478+ im_la .save (out , pixel_format = "DXT3" )
479+ assert_image_similar_tofile (im_la .convert ("RGBA" ), out , 8.44 )
480+
481+
482+ def test_save_dxt5 (tmp_path : Path ) -> None :
483+ # RGB
484+ out = str (tmp_path / "temp.dds" )
485+ with Image .open (TEST_FILE_DXT1 ) as im :
486+ im .convert ("RGB" ).save (out , pixel_format = "DXT5" )
487+ assert_image_similar_tofile (im , out , 1.84 )
488+
489+ # RGBA
490+ with Image .open (TEST_FILE_DXT5 ) as im_rgba :
491+ im_rgba .save (out , pixel_format = "DXT5" )
492+ assert_image_similar_tofile (im_rgba , out , 3.69 )
493+
494+ # L
495+ im_l = im .convert ("L" )
496+ im_l .save (out , pixel_format = "DXT5" )
497+ assert_image_similar_tofile (im_l .convert ("RGBA" ), out , 6.07 )
498+
499+ # LA
500+ im_la = im_rgba .convert ("LA" )
501+ im_la .save (out , pixel_format = "DXT5" )
502+ assert_image_similar_tofile (im_la .convert ("RGBA" ), out , 8.32 )
503+
504+
505+ def test_save_dx10_bc5 (tmp_path : Path ) -> None :
506+ out = str (tmp_path / "temp.dds" )
507+ with Image .open (TEST_FILE_DX10_BC5_TYPELESS ) as im :
508+ im .save (out , pixel_format = "BC5" )
509+ assert_image_similar_tofile (im , out , 9.56 )
510+
511+ im = hopper ("L" )
512+ with pytest .raises (OSError , match = "only RGB mode can be written as BC5" ):
513+ im .save (out , pixel_format = "BC5" )
0 commit comments