@@ -419,6 +419,10 @@ def _open(self) -> None:
419419 self ._mode = "RGBA"
420420 self .pixel_format = "BC1"
421421 n = 1
422+ elif dxgi_format in (DXGI_FORMAT .BC3_TYPELESS , DXGI_FORMAT .BC3_UNORM ):
423+ self ._mode = "RGBA"
424+ self .pixel_format = "BC3"
425+ n = 3
422426 elif dxgi_format in (DXGI_FORMAT .BC4_TYPELESS , DXGI_FORMAT .BC4_UNORM ):
423427 self ._mode = "L"
424428 self .pixel_format = "BC4"
@@ -521,14 +525,18 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
521525 flags = DDSD .CAPS | DDSD .HEIGHT | DDSD .WIDTH | DDSD .PIXELFORMAT
522526 bitcount = len (im .getbands ()) * 8
523527 pixel_format = im .encoderinfo .get ("pixel_format" )
524- if pixel_format in ("DXT1" , "DXT5" ):
528+ if pixel_format in ("DXT1" , "BC3" , " DXT5" ):
525529 codec_name = "bcn"
526530 flags |= DDSD .LINEARSIZE
527531 pitch = (im .width + 3 ) * 4
528532 args = pixel_format
529533 rgba_mask = [0 , 0 , 0 , 0 ]
530534 pixel_flags = DDPF .FOURCC
531- fourcc = D3DFMT .DXT1 if pixel_format == "DXT1" else D3DFMT .DXT5
535+ fourcc = {"DXT1" : D3DFMT .DXT1 , "BC3" : D3DFMT .DX10 , "DXT5" : D3DFMT .DXT5 }[
536+ pixel_format
537+ ]
538+ if fourcc == D3DFMT .DX10 :
539+ dxgi_format = DXGI_FORMAT .BC3_TYPELESS
532540 else :
533541 codec_name = "raw"
534542 flags |= DDSD .PITCH
@@ -573,6 +581,11 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
573581 + struct .pack ("<4I" , * rgba_mask ) # dwRGBABitMask
574582 + struct .pack ("<5I" , DDSCAPS .TEXTURE , 0 , 0 , 0 , 0 )
575583 )
584+ if fourcc == D3DFMT .DX10 :
585+ fp .write (
586+ # dxgi_format, 2D resource, misc, array size, straight alpha
587+ struct .pack ("<5I" , dxgi_format , 3 , 0 , 0 , 1 )
588+ )
576589 ImageFile ._save (im , fp , [ImageFile ._Tile (codec_name , (0 , 0 ) + im .size , 0 , args )])
577590
578591
0 commit comments