第七史詩文件spine解密相關

from pathlib import Path
from io import BytesIO, BufferedReader
from lz4.block import decompress as decLz4Block
from PIL.Image import Image, frombuffer as imgfb
from numpy import frombuffer as npfb, stack as npst, uint8, uint16

class SctToPng:
    Sign: bytes = b'SCT\x01'
    SignLen: int = len(Sign)

    @classmethod
    def Cov(cls, stream: BytesIO|BufferedReader) -> Image:
        if stream.read(cls.SignLen) != cls.Sign:
            raise ValueError('Sign 错误')
        texType = stream.read(1)[0]
        width = int.from_bytes(stream.read(2), 'little')
        height = int.from_bytes(stream.read(2), 'little')
        decLen = int.from_bytes(stream.read(4), 'little')
        comLen = int.from_bytes(stream.read(4), 'little')
        data = decLz4Block(stream.read(comLen), uncompressed_size=decLen)
        if texType == 2:
            return imgfb('RGBA', (width, height), data[:width*height*4], 'raw')
        elif texType == 4:
            start = width * height * 2
            rgb = npfb(data[:start], dtype=uint16).reshape((height, width))
            a = npfb(data[start:start+(width*height)], dtype=uint8).reshape((height, width))
            r = (((((rgb >> 11) & 0x1F) * 527) + 23) >> 6).astype(uint8)
            g = (((((rgb >> 5) & 0x3F) * 259) + 33) >> 6).astype(uint8)
            b = ((((rgb & 0x1F) * 527) + 23) >> 6).astype(uint8)
            return imgfb('RGBA', (width, height), npst([r, g, b, a], axis=-1).tobytes(), 'raw')
        else:
            raise ValueError('贴图格式 错误')

    @classmethod
    def Read(cls, file: bytes|bytearray|str|Path|BytesIO|BufferedReader) -> Image:
        if isinstance(file, str|Path):
            with open(file, 'rb') as f:
                return cls.Cov(f)
        elif isinstance(file, (bytes, bytearray)):
            return cls.Cov(BytesIO(file))
        else:
            return cls.Cov(file)

def batch(datPath: str = '', subfolder: bool = False):
    path = Path(datPath) if datPath else Path.cwd()
    need = [i for i in (path.rglob('*.sct') if subfolder else path.glob('*.sct')) if i.is_file()]
    for i in need:
        try:
            img = SctToPng.Read(i)
        except Exception as e:
            print(f'转换错误 --- {i.as_posix()} --- {e}')
            continue
        img.save(f'{i.as_posix()[:-3]}png')

if __name__ == '__main__':
    path = r'' # sct文件所在的路径
    subfolder = False # 是否查找字文件夹内的文件
    batch(path, subfolder)
3 个赞