mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-06-03 20:53:08 +03:00
Added support for uncompressed L images
This commit is contained in:
parent
edcfe09f12
commit
9e6a7d9740
BIN
Tests/images/uncompressed_l.dds
Normal file
BIN
Tests/images/uncompressed_l.dds
Normal file
Binary file not shown.
BIN
Tests/images/uncompressed_l.png
Normal file
BIN
Tests/images/uncompressed_l.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 861 B |
|
@ -22,6 +22,7 @@ TEST_FILE_DX10_BC7 = "Tests/images/bc7-argb-8bpp_MipMaps-1.dds"
|
||||||
TEST_FILE_DX10_BC7_UNORM_SRGB = "Tests/images/DXGI_FORMAT_BC7_UNORM_SRGB.dds"
|
TEST_FILE_DX10_BC7_UNORM_SRGB = "Tests/images/DXGI_FORMAT_BC7_UNORM_SRGB.dds"
|
||||||
TEST_FILE_DX10_R8G8B8A8 = "Tests/images/argb-32bpp_MipMaps-1.dds"
|
TEST_FILE_DX10_R8G8B8A8 = "Tests/images/argb-32bpp_MipMaps-1.dds"
|
||||||
TEST_FILE_DX10_R8G8B8A8_UNORM_SRGB = "Tests/images/DXGI_FORMAT_R8G8B8A8_UNORM_SRGB.dds"
|
TEST_FILE_DX10_R8G8B8A8_UNORM_SRGB = "Tests/images/DXGI_FORMAT_R8G8B8A8_UNORM_SRGB.dds"
|
||||||
|
TEST_FILE_UNCOMPRESSED_L = "Tests/images/uncompressed_l.dds"
|
||||||
TEST_FILE_UNCOMPRESSED_RGB = "Tests/images/hopper.dds"
|
TEST_FILE_UNCOMPRESSED_RGB = "Tests/images/hopper.dds"
|
||||||
TEST_FILE_UNCOMPRESSED_RGB_WITH_ALPHA = "Tests/images/uncompressed_rgb.dds"
|
TEST_FILE_UNCOMPRESSED_RGB_WITH_ALPHA = "Tests/images/uncompressed_rgb.dds"
|
||||||
|
|
||||||
|
@ -194,8 +195,14 @@ def test_unimplemented_dxgi_format():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_uncompressed_rgb():
|
def test_uncompressed():
|
||||||
"""Check uncompressed RGB images can be opened"""
|
"""Check uncompressed images can be opened"""
|
||||||
|
with Image.open(TEST_FILE_UNCOMPRESSED_L) as im:
|
||||||
|
assert im.format == "DDS"
|
||||||
|
assert im.mode == "L"
|
||||||
|
assert im.size == (128, 128)
|
||||||
|
|
||||||
|
assert_image_equal_tofile(im, "Tests/images/uncompressed_l.png")
|
||||||
|
|
||||||
# convert -format dds -define dds:compression=none hopper.jpg hopper.dds
|
# convert -format dds -define dds:compression=none hopper.jpg hopper.dds
|
||||||
with Image.open(TEST_FILE_UNCOMPRESSED_RGB) as im:
|
with Image.open(TEST_FILE_UNCOMPRESSED_RGB) as im:
|
||||||
|
@ -305,6 +312,7 @@ def test_save_unsupported_mode(tmp_path):
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("mode", "test_file"),
|
("mode", "test_file"),
|
||||||
[
|
[
|
||||||
|
("L", "Tests/images/linear_gradient.png"),
|
||||||
("RGB", "Tests/images/hopper.png"),
|
("RGB", "Tests/images/hopper.png"),
|
||||||
("RGBA", "Tests/images/pil123rgba.png"),
|
("RGBA", "Tests/images/pil123rgba.png"),
|
||||||
],
|
],
|
||||||
|
|
|
@ -135,7 +135,12 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
fourcc = header.read(4)
|
fourcc = header.read(4)
|
||||||
(bitcount,) = struct.unpack("<I", header.read(4))
|
(bitcount,) = struct.unpack("<I", header.read(4))
|
||||||
masks = struct.unpack("<4I", header.read(16))
|
masks = struct.unpack("<4I", header.read(16))
|
||||||
if pfflags & DDPF_RGB:
|
if pfflags & DDPF_LUMINANCE:
|
||||||
|
# Texture contains uncompressed L data
|
||||||
|
self.mode = "L"
|
||||||
|
|
||||||
|
self.tile = [("raw", (0, 0) + self.size, 0, ("L", 0, 1))]
|
||||||
|
elif pfflags & DDPF_RGB:
|
||||||
# Texture contains uncompressed RGB data
|
# Texture contains uncompressed RGB data
|
||||||
masks = {mask: ["R", "G", "B", "A"][i] for i, mask in enumerate(masks)}
|
masks = {mask: ["R", "G", "B", "A"][i] for i, mask in enumerate(masks)}
|
||||||
rawmode = ""
|
rawmode = ""
|
||||||
|
@ -223,9 +228,24 @@ class DdsImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
if im.mode not in ("RGB", "RGBA"):
|
if im.mode not in ("RGB", "RGBA", "L"):
|
||||||
raise OSError(f"cannot write mode {im.mode} as DDS")
|
raise OSError(f"cannot write mode {im.mode} as DDS")
|
||||||
|
|
||||||
|
if im.mode == "L":
|
||||||
|
masks = [0xFF000000]
|
||||||
|
pixel_flags = DDPF_LUMINANCE
|
||||||
|
else:
|
||||||
|
masks = [0xFF0000, 0xFF00, 0xFF]
|
||||||
|
if im.mode == "RGBA":
|
||||||
|
pixel_flags = DDS_RGBA
|
||||||
|
masks.append(0xFF000000)
|
||||||
|
else:
|
||||||
|
pixel_flags = DDPF_RGB
|
||||||
|
|
||||||
|
bitcount = len(masks) * 8
|
||||||
|
while len(masks) < 4:
|
||||||
|
masks.append(0)
|
||||||
|
|
||||||
fp.write(
|
fp.write(
|
||||||
o32(DDS_MAGIC)
|
o32(DDS_MAGIC)
|
||||||
+ o32(124) # header size
|
+ o32(124) # header size
|
||||||
|
@ -234,18 +254,15 @@ def _save(im, fp, filename):
|
||||||
) # flags
|
) # flags
|
||||||
+ o32(im.height)
|
+ o32(im.height)
|
||||||
+ o32(im.width)
|
+ o32(im.width)
|
||||||
+ o32((im.width * (32 if im.mode == "RGBA" else 24) + 7) // 8) # pitch
|
+ o32((im.width * bitcount + 7) // 8) # pitch
|
||||||
+ o32(0) # depth
|
+ o32(0) # depth
|
||||||
+ o32(0) # mipmaps
|
+ o32(0) # mipmaps
|
||||||
+ o32(0) * 11 # reserved
|
+ o32(0) * 11 # reserved
|
||||||
+ o32(32) # pfsize
|
+ o32(32) # pfsize
|
||||||
+ o32(DDS_RGBA if im.mode == "RGBA" else DDPF_RGB) # pfflags
|
+ o32(pixel_flags) # pfflags
|
||||||
+ o32(0) # fourcc
|
+ o32(0) # fourcc
|
||||||
+ o32(32 if im.mode == "RGBA" else 24) # bitcount
|
+ o32(bitcount) # bitcount
|
||||||
+ o32(0xFF0000) # rbitmask
|
+ b"".join(o32(mask) for mask in masks) # rgbabitmask
|
||||||
+ o32(0xFF00) # gbitmask
|
|
||||||
+ o32(0xFF) # bbitmask
|
|
||||||
+ o32(0xFF000000 if im.mode == "RGBA" else 0) # abitmask
|
|
||||||
+ o32(DDSCAPS_TEXTURE) # dwCaps
|
+ o32(DDSCAPS_TEXTURE) # dwCaps
|
||||||
+ o32(0) # dwCaps2
|
+ o32(0) # dwCaps2
|
||||||
+ o32(0) # dwCaps3
|
+ o32(0) # dwCaps3
|
||||||
|
|
Loading…
Reference in New Issue
Block a user