diff --git a/Tests/images/palette.dds b/Tests/images/palette.dds new file mode 100644 index 00000000000..7171cb1f242 Binary files /dev/null and b/Tests/images/palette.dds differ diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index ae4831d4848..bb9af7967b7 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -298,6 +298,11 @@ def test_dxt5_colorblock_alpha_issue_4142(): assert px[2] != 0 +def test_palette(): + with Image.open("Tests/images/palette.dds") as im: + assert_image_equal_tofile(im, "Tests/images/transparent.gif") + + def test_unimplemented_pixel_format(): with pytest.raises(NotImplementedError): with Image.open("Tests/images/unimplemented_pixel_format.dds"): diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index 2a42bdacba7..1f785bc21a3 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -63,8 +63,35 @@ DDS ^^^ DDS is a popular container texture format used in video games and natively supported -by DirectX. Uncompressed RGB and RGBA can be read, and (since 8.3.0) written. DXT1, -DXT3 (since 3.4.0) and DXT5 pixel formats can be read, only in ``RGBA`` mode. +by DirectX. + +DXT1 and DXT5 pixel formats can be read, only in ``RGBA`` mode. + +.. versionadded:: 3.4.0 + DXT3 images can be read in ``RGB`` mode and DX10 images can be read in + ``RGB`` and ``RGBA`` mode. + +.. versionadded:: 6.0.0 + Uncompressed ``RGBA`` images can be read. + + +.. versionadded:: 8.3.0 + BC5S images can be opened in ``RGB`` mode, and uncompressed ``RGB`` images + can be read. Uncompressed data can also be saved to image files. + + +.. versionadded:: 9.3.0 + ATI1 images can be opened in ``L`` mode and ATI2 images can be opened in + ``RGB`` mode. + +.. versionadded:: 9.4.0 + Uncompressed ``L`` ("luminance") and ``LA`` images can be opened and saved. + + +.. versionadded:: 10.1.0 + BC5U can be read in ``RGB`` mode, and 8-bit color indexed images can be read + in ``P`` mode. + DIB ^^^ diff --git a/docs/releasenotes/10.1.0.rst b/docs/releasenotes/10.1.0.rst index da5153cceef..087062dfd38 100644 --- a/docs/releasenotes/10.1.0.rst +++ b/docs/releasenotes/10.1.0.rst @@ -48,7 +48,7 @@ TODO Other Changes ============= -TODO -^^^^ +Added support for DDS 8-bit color indexed images +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -TODO +Support has been added to read PALETTEINDEXED8 DDS files as P mode images. diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 4da33332edf..54f358c7f9a 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -13,7 +13,7 @@ import struct from io import BytesIO -from . import Image, ImageFile +from . import Image, ImageFile, ImagePalette from ._binary import o32le as o32 # Magic ("DDS ") @@ -157,6 +157,10 @@ def _open(self): rawmode += masks[0xFF0000] + masks[0xFF00] + masks[0xFF] self.tile = [("raw", (0, 0) + self.size, 0, (rawmode[::-1], 0, 1))] + elif pfflags & DDPF_PALETTEINDEXED8: + self._mode = "P" + self.palette = ImagePalette.raw("RGBA", self.fp.read(1024)) + self.tile = [("raw", (0, 0) + self.size, 0, "L")] else: data_start = header_size + 4 n = 0