-
Notifications
You must be signed in to change notification settings - Fork 3
/
bti.py
87 lines (75 loc) · 3.15 KB
/
bti.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/env python
import sys, os
from struct import Struct, unpack
from texture import *
from common import *
class Image(ReadableStruct):
header = Struct('>BBHHBBBBHIBBBBBBBBBxhI')
fields = [
("format", TexFmt),
"transparency",
"width",
"height",
"wrapS",
"wrapT",
("usePalette", bool),
("paletteFormat", TlutFmt),
"paletteNumEntries",
"paletteOffset",
("isMipmap", bool),
("edgeLod", bool),
("biasClamp", bool),
"maxAniso",
"minFilter",
"magFilter",
"minLod",
"maxLod",
"mipmapCount",
"lodBias",
"dataOffset"
]
def read(self, fin, start=None, textureHeaderOffset=None, texIndex=None):
super().read(fin)
self.mipmapCount = max(self.mipmapCount, 1)
assert (self.format in (TexFmt.C4, TexFmt.C8, TexFmt.C14X2)) == self.usePalette, (self.format, self.usePalette)
if self.format in (TexFmt.C4, TexFmt.C8, TexFmt.C14X2):
self.hasAlpha = self.paletteFormat in (TlutFmt.IA8, TlutFmt.RGB5A3)
else:
self.hasAlpha = self.format in (TexFmt.IA4, TexFmt.IA8, TexFmt.RGB5A3, TexFmt.RGBA8)
if start is not None:
nextHeader = fin.tell()
self.fullDataOffset = start+textureHeaderOffset+self.dataOffset+0x20*texIndex
self.dataOffset = None
fin.seek(self.fullDataOffset)
self.data = readTextureData(fin, self.format, self.width, self.height, self.mipmapCount)
self.fullPaletteOffset = start+textureHeaderOffset+self.paletteOffset+0x20*texIndex
self.paletteOffset = None
fin.seek(self.fullPaletteOffset)
self.palette = readPaletteData(fin, self.paletteFormat, self.paletteNumEntries)
fin.seek(nextHeader)
def write(self, fout, offset=None):
if offset is None: offset=fout.tell()
self.dataOffset = offset+self.header.size
self.paletteOffset = self.dataOffset + len(self.data)*self.data.itemsize
super().write(fout)
swapArray(self.data).tofile(fout)
if self.palette is not None: swapArray(self.palette).tofile(fout)
def getDataName(self, bmd):
s = bmd.name+"@"+hex(self.fullDataOffset)
if self.format in (TexFmt.C4, TexFmt.C8, TexFmt.C14X2):
s += "p"+hex(self.fullPaletteOffset)
return s
if __name__ == "__main__":
if len(sys.argv) != 2:
sys.stderr.write("Usage: %s <bti>\n"%sys.argv[0])
exit(1)
img = Image()
fin = open(sys.argv[1], 'rb')
img.read(fin, 0, 0, 0)
fin.close()
print("%dx%d, fmt=%s, mips=%d, pfmt=%s" % (img.width, img.height, img.format, img.mipmapCount, img.paletteFormat))
images = decodeTexturePIL(img.data, img.format, img.width, img.height, img.paletteFormat, img.palette, img.mipmapCount)
images[0][0].save(os.path.splitext(sys.argv[1])[0]+'.png')
fout = open(os.path.splitext(sys.argv[1])[0]+".ktx", 'wb')
decodeTextureKTX(fout, img.data, img.format, img.width, img.height, img.paletteFormat, img.palette, img.mipmapCount)
fout.close()