Apply suggestion for PR

This commit is contained in:
REDxEYE 2023-10-12 19:09:28 +03:00
parent 777c54a4d1
commit a5dde8b1c4
15 changed files with 123 additions and 37 deletions

View File

Before

Width:  |  Height:  |  Size: 969 B

After

Width:  |  Height:  |  Size: 969 B

View File

Before

Width:  |  Height:  |  Size: 861 B

After

Width:  |  Height:  |  Size: 861 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 862 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -10,8 +10,8 @@ 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"
TEST_FILE_DXT5 = "Tests/images/dxt5-argb-8bbp-interpolatedalpha_MipMaps-1.dds"
TEST_FILE_ATI1 = "Tests/images/ati1.dds"
TEST_FILE_ATI2 = "Tests/images/ati2.dds"
TEST_FILE_ATI1 = "Tests/images/mode-ati1.dds"
TEST_FILE_ATI2 = "Tests/images/mode-ati2.dds"
TEST_FILE_DX10_BC5_TYPELESS = "Tests/images/bc5_typeless.dds"
TEST_FILE_DX10_BC5_UNORM = "Tests/images/bc5_unorm.dds"
TEST_FILE_DX10_BC5_SNORM = "Tests/images/bc5_snorm.dds"
@ -314,10 +314,10 @@ def test_save_unsupported_mode(tmp_path):
@pytest.mark.parametrize(
("mode", "test_file"),
(
("L", "Tests/images/l.dds"),
("LA", "Tests/images/la.dds"),
("RGB", "Tests/images/rgb.dds"),
("RGBA", "Tests/images/rgba.dds"),
("L", "Tests/images/mode-l.dds"),
("LA", "Tests/images/mode-la.dds"),
("RGB", "Tests/images/mode-rgb.dds"),
("RGBA", "Tests/images/mode-rgba.dds"),
),
)
def test_open(mode, test_file):
@ -333,7 +333,7 @@ def test_open(mode, test_file):
("LA", "Tests/images/uncompressed_la.png"),
("RGB", "Tests/images/hopper.png"),
("RGBA", "Tests/images/pil123rgba.png"),
("L", "Tests/images/ati1.dds"),
("L", "Tests/images/mode-ati1.dds"),
],
)
def test_save(mode, test_file, tmp_path):

View File

@ -253,6 +253,8 @@ class D3DFMT(IntEnum):
DXT4 = i32(b"DXT4")
DXT5 = i32(b"DXT5")
DX10 = i32(b"DX10")
BC4S = i32(b"BC4S")
BC4U = i32(b"BC4U")
BC5S = i32(b"BC5S")
BC5U = i32(b"BC5U")
ATI1 = i32(b"ATI1")
@ -260,6 +262,81 @@ class D3DFMT(IntEnum):
MULTI2_ARGB8 = i32(b"MET1")
# Backward compat layer
DDSD_CAPS = DDSD.CAPS
DDSD_HEIGHT = DDSD.HEIGHT
DDSD_WIDTH = DDSD.WIDTH
DDSD_PITCH = DDSD.PITCH
DDSD_PIXELFORMAT = DDSD.PIXELFORMAT
DDSD_MIPMAPCOUNT = DDSD.MIPMAPCOUNT
DDSD_LINEARSIZE = DDSD.LINEARSIZE
DDSD_DEPTH = DDSD.DEPTH
DDSCAPS_COMPLEX = DDSCAPS.COMPLEX
DDSCAPS_TEXTURE = DDSCAPS.TEXTURE
DDSCAPS_MIPMAP = DDSCAPS.MIPMAP
DDSCAPS2_CUBEMAP = DDSCAPS2.CUBEMAP
DDSCAPS2_CUBEMAP_POSITIVEX = DDSCAPS2.CUBEMAP_POSITIVEX
DDSCAPS2_CUBEMAP_NEGATIVEX = DDSCAPS2.CUBEMAP_NEGATIVEX
DDSCAPS2_CUBEMAP_POSITIVEY = DDSCAPS2.CUBEMAP_POSITIVEY
DDSCAPS2_CUBEMAP_NEGATIVEY = DDSCAPS2.CUBEMAP_NEGATIVEY
DDSCAPS2_CUBEMAP_POSITIVEZ = DDSCAPS2.CUBEMAP_POSITIVEZ
DDSCAPS2_CUBEMAP_NEGATIVEZ = DDSCAPS2.CUBEMAP_NEGATIVEZ
DDSCAPS2_VOLUME = DDSCAPS2.VOLUME
DDPF_ALPHAPIXELS = DDPF.ALPHAPIXELS
DDPF_ALPHA = DDPF.ALPHA
DDPF_FOURCC = DDPF.FOURCC
DDPF_PALETTEINDEXED8 = DDPF.PALETTEINDEXED8
DDPF_RGB = DDPF.RGB
DDPF_LUMINANCE = DDPF.LUMINANCE
DDS_FOURCC = DDPF_FOURCC
DDS_RGB = DDPF_RGB
DDS_RGBA = DDPF_RGB | DDPF_ALPHAPIXELS
DDS_LUMINANCE = DDPF_LUMINANCE
DDS_LUMINANCEA = DDPF_LUMINANCE | DDPF_ALPHAPIXELS
DDS_ALPHA = DDPF_ALPHA
DDS_PAL8 = DDPF_PALETTEINDEXED8
DDS_HEADER_FLAGS_TEXTURE = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT
DDS_HEADER_FLAGS_MIPMAP = DDSD_MIPMAPCOUNT
DDS_HEADER_FLAGS_VOLUME = DDSD_DEPTH
DDS_HEADER_FLAGS_PITCH = DDSD_PITCH
DDS_HEADER_FLAGS_LINEARSIZE = DDSD_LINEARSIZE
DDS_HEIGHT = DDSD_HEIGHT
DDS_WIDTH = DDSD_WIDTH
DDS_SURFACE_FLAGS_TEXTURE = DDSCAPS_TEXTURE
DDS_SURFACE_FLAGS_MIPMAP = DDSCAPS_COMPLEX | DDSCAPS_MIPMAP
DDS_SURFACE_FLAGS_CUBEMAP = DDSCAPS_COMPLEX
DDS_CUBEMAP_POSITIVEX = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX
DDS_CUBEMAP_NEGATIVEX = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX
DDS_CUBEMAP_POSITIVEY = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY
DDS_CUBEMAP_NEGATIVEY = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY
DDS_CUBEMAP_POSITIVEZ = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ
DDS_CUBEMAP_NEGATIVEZ = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ
DXT1_FOURCC = D3DFMT.DXT1
DXT3_FOURCC = D3DFMT.DXT3
DXT5_FOURCC = D3DFMT.DXT5
DXGI_FORMAT_R8G8B8A8_TYPELESS = DXGI_FORMAT.R8G8B8A8_TYPELESS
DXGI_FORMAT_R8G8B8A8_UNORM = DXGI_FORMAT.R8G8B8A8_UNORM
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = DXGI_FORMAT.R8G8B8A8_UNORM_SRGB
DXGI_FORMAT_BC5_TYPELESS = DXGI_FORMAT.BC5_TYPELESS
DXGI_FORMAT_BC5_UNORM = DXGI_FORMAT.BC5_UNORM
DXGI_FORMAT_BC5_SNORM = DXGI_FORMAT.BC5_SNORM
DXGI_FORMAT_BC6H_UF16 = DXGI_FORMAT.BC6H_UF16
DXGI_FORMAT_BC6H_SF16 = DXGI_FORMAT.BC6H_SF16
DXGI_FORMAT_BC7_TYPELESS = DXGI_FORMAT.BC7_TYPELESS
DXGI_FORMAT_BC7_UNORM = DXGI_FORMAT.BC7_UNORM
DXGI_FORMAT_BC7_UNORM_SRGB = DXGI_FORMAT.BC7_UNORM_SRGB
class DdsImageFile(ImageFile.ImageFile):
format = "DDS"
format_description = "DirectDraw Surface"
@ -311,6 +388,13 @@ class DdsImageFile(ImageFile.ImageFile):
else:
msg = f"Unsupported bitcount {bitcount} for {pfflags_}"
raise OSError(msg)
elif pfflags & DDPF.ALPHA:
if bitcount == 8:
self.mode = "L"
self.tile = [("raw", extents, 0, ("L", 0, 1))]
else:
msg = f"Unsupported bitcount {bitcount} for {pfflags_}"
raise OSError(msg)
elif pfflags & DDPF.LUMINANCE:
if bitcount == 8:
self.mode = "L"
@ -331,68 +415,72 @@ class DdsImageFile(ImageFile.ImageFile):
if fourcc == D3DFMT.DXT1:
self.mode = "RGBA"
self.pixel_format = "DXT1"
tile = Image.Tile("bcn", extents, data_offs, (1, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (1, self.pixel_format))
elif fourcc == D3DFMT.DXT3:
self.mode = "RGBA"
self.pixel_format = "DXT3"
tile = Image.Tile("bcn", extents, data_offs, (2, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (2, self.pixel_format))
elif fourcc == D3DFMT.DXT5:
self.mode = "RGBA"
self.pixel_format = "DXT5"
tile = Image.Tile("bcn", extents, data_offs, (3, self.pixel_format))
elif fourcc == D3DFMT.ATI1:
tile = Image._Tile("bcn", extents, data_offs, (3, self.pixel_format))
elif fourcc == D3DFMT.ATI1 or fourcc == D3DFMT.BC4U:
self.mode = "L"
self.pixel_format = "BC4"
tile = Image.Tile("bcn", extents, data_offs, (4, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (4, self.pixel_format))
elif fourcc == D3DFMT.BC5S:
self.mode = "RGB"
self.pixel_format = "BC5S"
tile = Image.Tile("bcn", extents, data_offs, (5, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (5, self.pixel_format))
elif fourcc == D3DFMT.BC5U:
self.mode = "RGB"
self.pixel_format = "BC5U"
tile = Image.Tile("bcn", extents, data_offs, (5, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (5, self.pixel_format))
elif fourcc == D3DFMT.ATI2:
self.mode = "RGB"
self.pixel_format = "BC5"
tile = Image.Tile("bcn", extents, data_offs, (5, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (5, self.pixel_format))
elif fourcc == D3DFMT.DX10:
data_offs += 20
# ignoring flags which pertain to volume textures and cubemaps
(dxgi_format,) = struct.unpack("<I", self.fp.read(4))
self.fp.read(16)
if dxgi_format in (DXGI_FORMAT.BC5_TYPELESS, DXGI_FORMAT.BC5_UNORM):
if dxgi_format in (DXGI_FORMAT.BC1_UNORM, DXGI_FORMAT.BC1_UNORM_SRGB, DXGI_FORMAT.BC1_TYPELESS):
self.mode = "RGBA"
self.pixel_format = "BC1"
tile = Image._Tile("bcn", extents, data_offs, (1, self.pixel_format))
elif dxgi_format in (DXGI_FORMAT.BC5_TYPELESS, DXGI_FORMAT.BC5_UNORM):
self.mode = "RGB"
self.pixel_format = "BC5"
tile = Image.Tile("bcn", extents, data_offs, (5, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (5, self.pixel_format))
elif dxgi_format == DXGI_FORMAT.BC5_SNORM:
self.mode = "RGB"
self.pixel_format = "BC5S"
tile = Image.Tile("bcn", extents, data_offs, (5, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (5, self.pixel_format))
elif dxgi_format == DXGI_FORMAT.BC6H_UF16:
self.mode = "RGB"
self.pixel_format = "BC6H"
tile = Image.Tile("bcn", extents, data_offs, (6, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (6, self.pixel_format))
elif dxgi_format == DXGI_FORMAT.BC6H_SF16:
self.mode = "RGB"
self.pixel_format = "BC6HS"
tile = Image.Tile("bcn", extents, data_offs, (6, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (6, self.pixel_format))
elif dxgi_format in (DXGI_FORMAT.BC7_TYPELESS, DXGI_FORMAT.BC7_UNORM):
self.mode = "RGBA"
self.pixel_format = "BC7"
tile = Image.Tile("bcn", extents, data_offs, (7, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (7, self.pixel_format))
elif dxgi_format == DXGI_FORMAT.BC7_UNORM_SRGB:
self.mode = "RGBA"
self.pixel_format = "BC7"
self.info["gamma"] = 1 / 2.2
tile = Image.Tile("bcn", extents, data_offs, (7, self.pixel_format))
tile = Image._Tile("bcn", extents, data_offs, (7, self.pixel_format))
elif dxgi_format in (
DXGI_FORMAT.R8G8B8A8_TYPELESS,
DXGI_FORMAT.R8G8B8A8_UNORM,
DXGI_FORMAT.R8G8B8A8_UNORM_SRGB,
):
self.mode = "RGBA"
tile = Image.Tile("raw", extents, 0, ("RGBA", 0, 1))
tile = Image._Tile("raw", extents, 0, ("RGBA", 0, 1))
if dxgi_format == DXGI_FORMAT.R8G8B8A8_UNORM_SRGB:
self.info["gamma"] = 1 / 2.2
else:
@ -457,7 +545,7 @@ def _save(im, fp, filename):
+ struct.pack("<IIIII", DDSCAPS.TEXTURE, 0, 0, 0, 0)
)
mode = "LA" if im.mode == "LA" else im.mode[::-1]
ImageFile._save(im, fp, [Image.Tile("raw", (0, 0) + im.size, 0, (mode, 0, 1))])
ImageFile._save(im, fp, [Image._Tile("raw", (0, 0) + im.size, 0, (mode, 0, 1))])
def _accept(prefix):

View File

@ -38,7 +38,7 @@ import warnings
from collections.abc import Callable, MutableMapping
from enum import IntEnum
from pathlib import Path
from typing import List, NamedTuple, Tuple
from typing import NamedTuple
try:
import defusedxml.ElementTree as ElementTree
@ -207,15 +207,13 @@ if hasattr(core, "DEFAULT_STRATEGY"):
RLE = core.RLE
FIXED = core.FIXED
Tile = NamedTuple(
"Tile",
[
("encoder_name", str),
("extents", Tuple[int, int, int, int]),
("offset", int),
("tile_args", Tuple),
],
)
class _Tile(NamedTuple):
encoder_name: str
extents: tuple[int, int, int, int]
offset: int
tile_args: tuple
# --------------------------------------------------------------------
# Registries
@ -702,7 +700,7 @@ class Image:
def __setstate__(self, state):
Image.__init__(self)
self.tile: List[Tile] = []
self.tile: list[_Tile] = []
info, mode, size, palette, data = state
self.info = info
self.mode = mode

View File

@ -26,12 +26,12 @@
#
# See the README file for information on usage and redistribution.
#
from __future__ import annotations
import io
import itertools
import struct
import sys
from typing import List
from . import Image
from ._util import is_path
@ -522,7 +522,7 @@ def _save(im, fp, tile, bufsize=0):
fp.flush()
def _encode_tile(im, fp, tile: List[Image.Tile], bufsize, fh, exc=None):
def _encode_tile(im, fp, tile: list[Image._Tile], bufsize, fh, exc=None):
for encoder_name, extents, offset, tile_args in tile:
if offset > 0:
fp.seek(offset)