Source code for scfile.formats.dds.encoder

from scfile.consts import FileSignature
from scfile.core import FileEncoder, TextureContent
from scfile.enums import F, FileFormat
from scfile.formats.dds.enums import DXGIDimension, DXGIFormat
from scfile.structures.texture import TextureType

from .header import DDS
from .mask import BGRA8, RGBA8


[docs] class DdsEncoder(FileEncoder[TextureContent[TextureType]]): format = FileFormat.DDS signature = FileSignature.DDS
[docs] def serialize(self): self._add_header() self._add_pixelformat() self._add_caps() if self.data.fourcc == b"DX10": self._add_dxgi() self.write(self.data.texture.image)
def _add_header(self): self._writeb( f"{7}{F.U32}", DDS.HEADER.SIZE, # dwSize self._flags, # dwFlags self.data.height, # dwHeight self.data.width, # dwWidth self._pitch_or_linear_size, # dwPitchOrLinearSize 0, # dwDepth self.data.mipmap_count, # dwMipMapCount ) self._writenull(size=4 * 11) # dwReserved1[11] def _add_pixelformat(self): self._writeb(F.U32, DDS.PF.SIZE) # dwSize if self.data.is_compressed: self._add_pf_fourcc() else: self._add_pf_rgb() def _add_pf_fourcc(self): self._writeb(F.U32, DDS.PF.FLAG.FOURCC) # dwFlags self.write(self.data.fourcc) # dwFourCC self._writenull(size=4 * 5) # dwRGBBitCount, RGBA bit masks (unused) def _add_pf_rgb(self): self._writeb(F.U32, DDS.PF.RGB) # dwFlags self._writenull(size=4) # dwFourCC (unused) self._writeb(F.U32, DDS.PF.BIT_COUNT) # dwRGBBitCount bitmask = BGRA8 if self.data.fourcc == b"BGRA8" else RGBA8 # not best realization... self._writeb(F.U32 * 4, *bitmask) # RGBA bit masks def _add_caps(self): self._writeb( f"{2}{F.U32}", DDS.CAPS1, # dwCaps1 self._caps2, # dwCaps2 ) self._writenull(size=4 * 3) # dwCaps3, dwCaps4, Reserved def _add_dxgi(self): self._writeb( f"{5}{F.U32}", DXGIFormat.FLOAT_R32G32B32A32, # dxgiFormat DXGIDimension.TEXTURE2D, # resourceDimension 0, # miscFlag 1, # arraySize 0, # miscFlags2 ) @property def _flags(self) -> int: if self.data.is_compressed: return DDS.HEADER.FLAGS | DDS.HEADER.FLAG.LINEARSIZE return DDS.HEADER.FLAGS | DDS.HEADER.FLAG.PITCH @property def _pitch(self) -> int: bytes_per_pixel = 4 aligned_width = (self.data.width * bytes_per_pixel + 3) & ~3 return aligned_width @property def _pitch_or_linear_size(self) -> int: if self.data.is_compressed: return self.data.texture.linear_size return self._pitch @property def _caps2(self) -> int: if self.data.is_cubemap: return DDS.CUBEMAPS return 0