import png

This commit is contained in:
Benjamin Collins 2020-08-14 08:05:30 +09:00
parent 77d7089d67
commit aa655a0bca

View File

@ -25,9 +25,14 @@
import os
import sys
import png
import math
import struct
class NinjaTexture: # {
# Cache Positions
LOOKUP_TABLE = {}
# Color Formats
ARGB_1555 = 0x00
@ -73,15 +78,23 @@ class NinjaTexture: # {
def parse(self):
print("Parsing the texture file")
bytes = self.file.read(4)
print(bytes)
if bytes == 'PVMH':
if bytes == b'PVMH':
self.readPvm()
elif bytes == 'PVRT':
elif bytes == b'PVRT':
bytes = self.file.read(4)
p = struct.unpack('I', bytes)
pvrt_len = p[0]
self.readPvr()
for tex in self.tex_list:
if tex['bitmap'] is None:
continue
imgName = "output/" + tex['name'] + '.png'
print(tex['bitmap'])
png.from_array(tex['bitmap'], 'RGBA').save(imgName)
return None
def readPvm(self):
@ -96,7 +109,7 @@ class NinjaTexture: # {
flags = p[0]
tex_count = p[1]
local_list = []
self.tex_list = []
for i in range(tex_count):
bytes = self.file.read(2)
p = struct.unpack('H', bytes)
@ -104,7 +117,8 @@ class NinjaTexture: # {
if flags & 0x08:
bytes = self.file.read(0x1c)
tex['name'] = bytes.replace('\x00', '')
name = str(bytes)
tex['name'] = name.replace('\\x00', '')
if flags & 0x04:
bytes = self.file.read(2)
p = struct.unpack('H', bytes)
@ -122,13 +136,13 @@ class NinjaTexture: # {
p = struct.unpack('I', bytes)
tex['guid'] = p[0]
local_list.append(tex)
self.tex_list.append(tex)
self.file.seek(pvmh_len + save_pos, 0)
for tex in local_list:
for tex in self.tex_list:
while self.file.tell() < self.length:
bytes = self.file.read(4)
if bytes != 'PVRT':
if bytes != b'PVRT':
continue
break
bytes = self.file.read(4)
@ -136,7 +150,7 @@ class NinjaTexture: # {
save_pos = self.file.tell()
pvrt_len = p[0]
print("Reading Texture: %d" % tex['id'])
self.readPvr(tex)
tex['bitmap'] = self.readPvr(tex)
self.file.seek(pvrt_len + save_pos, 0)
return None
@ -241,12 +255,32 @@ class NinjaTexture: # {
seek_ofs = self.get_mipmap_size()
self.file.read(seek_ofs)
self.startOfs = self.file.tell()
if self.isTwiddled:
print("Reading twiddled texture")
sys.exit()
self.dst_array = self.detwiddle(self.mipWidth, self.mipHeight)
else:
return None
return None
tmp_bitmap = []
for i in range(len(self.dst_array)):
if self.color_format == 0:
color = self.dst_array[i]
bitmap = self.ARGB_1555(color)
tmp_bitmap.extend(bitmap)
elif self.color_format == 1:
color = self.dst_array[i]
bitmap = self.ARGB_565(color)
tmp_bitmap.extend(bitmap)
elif self.color_format == 2:
color = self.dst_array[i]
bitmap = self.ARGB_4444(color)
tmp_bitmap.extend(bitmap)
else:
print("Color format: ", self.color_format)
noesis.doException("Non supported pvr color format")
return struct.pack('B'*len(tmp_bitmap), *tmp_bitmap)
def get_mipmap_size(self):
mipCount = 0
@ -275,3 +309,57 @@ class NinjaTexture: # {
else:
seek_ofs = seek_ofs + 2
return seek_ofs
def detwiddle(self, w, h):
arr = [None] * (w * h)
for y in range(h):
for x in range(w):
i = self.untwiddle(x, y)
idx = y * h + x
if self.isCompressed:
self.file.seek(self.startOfs + i, 0)
b = self.file.read(1)
arr[idx] = struct.unpack('B', b)[0]
else:
self.file.seek(self.startOfs + (i * 2), 0)
b = self.file.read(2)
arr[idx] = struct.unpack('H', b)[0]
return arr
def untwiddle(self, x, y):
key = "{0}_{1}".format(x,y)
if key in NinjaTexture.LOOKUP_TABLE:
return NinjaTexture.LOOKUP_TABLE[key]
def UntwiddleValue(val):
untwiddled = 0
for i in range(10):
shift = int(math.pow(2, i))
if val & shift :
untwiddled = untwiddled | (shift << i)
return untwiddled
pos = UntwiddleValue(y) | UntwiddleValue(x) << 1
NinjaTexture.LOOKUP_TABLE[key] = pos
return pos
def ARGB_1555 (self, v):
a = 0xFF if (v & (1<<15)) else 0
r = (v >> (10-3)) & 0xf8
g = (v >> (5-3)) & 0xf8
b = (v << 3) & 0xf8
return [r,g,b,a]
def ARGB_4444 (self, v):
a = (v >> (12-4)) & 0xf0
r = (v >> (8-4)) & 0xf0
g = (v >> (4-4)) & 0xf0
b = (v << 4) & 0xf0
return [r,g,b,a]
def ARGB_565(self, v):
a = 0xff
r = (v >> (11-3)) & (0x1f<<3)
g = (v >> (5-2)) & (0x3f<<2)
b = (v << 3) & (0x1f<<3)
return [r,g,b,a]