Skip to content

Commit

Permalink
Added RGB saving
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed Apr 12, 2021
1 parent 8e293ca commit afc3e2d
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
18 changes: 17 additions & 1 deletion Tests/test_file_dds.py
Expand Up @@ -5,7 +5,7 @@

from PIL import DdsImagePlugin, Image

from .helper import assert_image_equal, assert_image_equal_tofile
from .helper import assert_image_equal, assert_image_equal_tofile, hopper

TEST_FILE_DXT1 = "Tests/images/dxt1-rgb-4bbp-noalpha_MipMaps-1.dds"
TEST_FILE_DXT3 = "Tests/images/dxt3-argb-8bbp-explicitalpha_MipMaps-1.dds"
Expand Down Expand Up @@ -199,3 +199,19 @@ def test_unimplemented_pixel_format():
with pytest.raises(NotImplementedError):
with Image.open("Tests/images/unimplemented_pixel_format.dds"):
pass


def test_save_unsupported_mode(tmp_path):
out = str(tmp_path / "temp.dds")
im = hopper("HSV")
with pytest.raises(OSError):
im.save(out)


def test_save(tmp_path):
out = str(tmp_path / "temp.dds")
im = hopper()
im.save(out)

with Image.open(out) as reloaded:
assert_image_equal(im, reloaded)
35 changes: 35 additions & 0 deletions src/PIL/DdsImagePlugin.py
Expand Up @@ -14,6 +14,7 @@
from io import BytesIO

from . import Image, ImageFile
from ._binary import o32le as o32

# Magic ("DDS ")
DDS_MAGIC = 0x20534444
Expand Down Expand Up @@ -184,9 +185,43 @@ def load_seek(self, pos):
pass


def _save(im, fp, filename):
if im.mode != "RGB":
raise OSError(f"cannot write mode {im.mode} as DDS")

fp.write(
o32(DDS_MAGIC)
+ o32(124) # header size
+ o32(
DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH | DDSD_PIXELFORMAT
) # flags
+ o32(im.height)
+ o32(im.width)
+ o32((im.width * 24 + 7) // 8) # pitch
+ o32(0) # depth
+ o32(0) # mipmaps
+ o32(0) * 11 # reserved
+ o32(32) # pfsize
+ o32(DDPF_RGB) # pfflags
+ o32(0) # fourcc
+ o32(24) # bitcount
+ o32(0xFF0000) # rbitmask
+ o32(0xFF00) # gbitmask
+ o32(0xFF) # bbitmask
+ o32(0) # abitmask
+ o32(0) # dwCaps
+ o32(0) # dwCaps2
+ o32(0) # dwCaps3
+ o32(0) # dwCaps4
+ o32(0) # dwReserved2
)
ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (im.mode[::-1], 0, 1))])


def _accept(prefix):
return prefix[:4] == b"DDS "


Image.register_open(DdsImageFile.format, DdsImageFile, _accept)
Image.register_save(DdsImageFile.format, _save)
Image.register_extension(DdsImageFile.format, ".dds")

0 comments on commit afc3e2d

Please sign in to comment.