Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from PIL import Image
- from struct import unpack
- from math import ceil
- import sys
- class I4_Texture:
- def __init__(self, height, width, color):
- self.image = Image.new("RGB", (width, height))
- self.img = self.image.load()
- self.width = width
- self.height = height
- self.color = color
- def DecodeImage(self, f): #8x8 block size
- for y in range(int(ceil(self.height / 8.0))):
- for x in range(int(ceil(self.width / 8.0))):
- self.DecodeBlock(f, x * 8, y * 8)
- def DecodeBlock(self, f, x, y):
- for ty in range(8): #8 pixel block height
- for tx in range(4): #cuz we read 2 pixels worth
- data = ord(f.read(1))
- color1, color2 = self.color.I4ToColor(data)
- try:
- self.img[x + (tx * 2), y + ty] = color1
- self.img[x + (tx * 2) + 1, y + ty] = color2
- except: pass
- class I8_Texture:
- def __init__(self, height, width, color):
- self.image = Image.new("RGB", (width, height))
- self.img = self.image.load()
- self.width = width
- self.height = height
- self.color = color
- def DecodeImage(self, f): #8x4 block size
- for y in range(int(ceil(self.height / 4.0))):
- for x in range(int(ceil(self.width / 8.0))):
- self.DecodeBlock(f, x * 8, y * 4)
- def DecodeBlock(self, f, x, y):
- for ty in range(4): #4 pixel block height
- for tx in range(8): #8 pixel block width
- i = ord(f.read(1))
- try: self.img[x + tx, y + ty] = (i, i, i)
- except: pass
- class IA4_Texture:
- def __init__(self, height, width, color):
- self.image = Image.new("RGBA", (width, height))
- self.img = self.image.load()
- self.height = height
- self.width = width
- self.color = color
- def DecodeImage(self, f): #8x4 block size
- for y in range(int(ceil(self.height / 4.0))):
- for x in range(int(ceil(self.width / 8.0))):
- self.DecodeBlock(f, x * 8, y * 4)
- def DecodeBlock(self, f, x, y):
- for ty in range(4): #4 pixel block height
- for tx in range(8): #8 pixel block width
- color = self.color.IA4ToColor(ord(f.read(1)))
- try: self.img[x + tx, y + ty] = color
- except: pass
- class RGB565_Texture:
- def __init__(self, height, width, color):
- self.image = Image.new("RGB", (width, height))
- self.img = self.image.load()
- self.width = width
- self.height = height
- self.color = color
- def DecodeImage(self, f): #4x4 block size
- for y in range(int(ceil(self.height / 4.0))):
- for x in range(int(ceil(self.width / 4.0))):
- self.DecodeBlock(f, x * 4, y * 4)
- def DecodeBlock(self, f, x, y):
- for ty in range(4): #4 pixel block height
- for tx in range(4): #4 pixel block width
- pixel = unpack(">H", f.read(2))[0]
- color = self.color.RGB565ToColor(pixel)
- try: self.img[x + tx, y + ty] = color
- except: pass
- class RGB5A3_Texture:
- def __init__(self, height, width, color):
- self.image = Image.new("RGBA", (width, height))
- self.img = self.image.load()
- self.width = width
- self.height = height
- self.color = color
- def DecodeImage(self, f): #4x4 block size
- for y in range(int(ceil(self.height / 4.0))):
- for x in range(int(ceil(self.width / 4.0))):
- self.DecodeBlock(f, x * 4, y * 4)
- def DecodeBlock(self, f, x, y):
- for ty in range(4): #4 pixel block height
- for tx in range(4): #4 pixel block width
- pixel = unpack(">H", f.read(2))[0]
- color = self.color.RGB5A3ToColor(pixel)
- try: self.img[x + tx, y + ty] = color
- except: pass
- class CI8_Texture:
- def __init__(self, height, width, color):
- self.image = Image.new("RGBA", (width, height))
- self.img = self.image.load()
- self.height = height
- self.width = width
- self.color = color
- def DecodePalette(self, f):
- info = unpack(">HBBII", f.read(12))
- f.seek(info[4]) #data addr
- palette = []
- if info[3] == 0:
- pass
- elif info[3] == 1:
- pass
- elif info[3] == 2: #RGB5A3
- for i in range(info[0]): #num_entries
- pixel = unpack(">H", f.read(2))[0]
- color = self.color.RGB5A3ToColor(pixel)
- palette.append(color)
- return palette
- def DecodeImage(self, f, palette):
- for y in range(int(ceil(self.height / 4.0))):
- for x in range(int(ceil(self.width / 8.0))):
- self.DecodeBlock(f, palette, x * 8, y * 4)
- def DecodeBlock(self, f, palette, x, y):
- for ty in range(4):
- for tx in range(8):
- index = ord(f.read(1))
- try: self.img[x + tx, y + ty] = palette[index]
- except: pass
- class RGBA32_Texture:
- def __init__(self, height, width, color):
- self.image = Image.new("RGBA", (width, height))
- self.img = self.image.load()
- self.width = width
- self.height = height
- self.color = color #we don't need it but add anyways
- def DecodeImage(self, f):
- for y in range(int(ceil(self.height / 4.0))):
- for x in range(int(ceil(self.width / 4.0))):
- self.DecodeBlock(f, x * 4, y * 4)
- def DecodeBlock(self, f, x, y):
- r = [];g = [];b = [];a = []
- for i in range(16):
- a.append(ord(f.read(1)))
- r.append(ord(f.read(1)))
- for i in range(16):
- g.append(ord(f.read(1)))
- b.append(ord(f.read(1)))
- for ty in range(4):
- for tx in range(4):
- i = tx + (ty * 4)
- try: self.img[x + tx, y + ty] = (r[i], g[i], b[i], a[i])
- except: pass
- class CMPR_Texture:
- def __init__(self, height, width, color):
- self.image = Image.new("RGBA", (width, height))
- self.img = self.image.load()
- self.width = width
- self.height = height
- self.color = color
- def DecodeImage(self, f):
- for y in range(int(ceil(self.height / 8.0))):
- for x in range(int(ceil(self.width / 8.0))):
- self.DecodeBlock(f, x * 8, y * 8)
- def DecodeBlock(self, f, x, y):
- self.DecodeTile(f.read(8), x + 0, y + 0)
- self.DecodeTile(f.read(8), x + 4, y + 0)
- self.DecodeTile(f.read(8), x + 0, y + 4)
- self.DecodeTile(f.read(8), x + 4, y + 4)
- def DecodeTile(self, data, x, y):
- c1, c2 = unpack(">2H", data[0:4])
- r1, g1, b1 = self.color.RGB565ToColor(c1)
- r2, g2, b2 = self.color.RGB565ToColor(c2)
- colors = [(), (), (), ()]
- colors[0] = (r1, g1, b1, 0xFF)
- colors[1] = (r2, g2, b2, 0xFF)
- if c1 > c2:
- r3 = ((r2 - r1) >> 1) - ((r2 - r1) >> 3)
- g3 = ((g2 - g1) >> 1) - ((g2 - g1) >> 3)
- b3 = ((b2 - b1) >> 1) - ((b2 - b1) >> 3)
- colors[2] = (r1 + r3, g1 + g3, b1 + b3, 0xFF)
- colors[3] = (r2 - r3, g2 - g3, b2 - b3, 0xFF)
- else:
- colors[2] = (int((r1 + r2 + 1) / 2.0),
- int((g1 + g2 + 1) / 2.0),
- int((b1 + b2 + 1) / 2.0),
- 0xFF)
- colors[3] = (r2, g2, b2, 0x00)
- index = unpack(">4B", data[4:])
- for ty in range(4):
- val = index[ty]
- for tx in range(4):
- color = colors[(val >> 6) & 3]
- try:
- self.img[x + tx, y + ty] = color
- val <<= 2
- except: pass
- class ColorConversion:
- def __init__(self):
- self.Bits3To8 = self.MakeDepthConversionTable(3, 8)
- self.Bits8To3 = self.MakeDepthConversionTable(8, 3)
- self.Bits4To8 = self.MakeDepthConversionTable(4, 8)
- self.Bits8To4 = self.MakeDepthConversionTable(8, 4)
- self.Bits5To8 = self.MakeDepthConversionTable(5, 8)
- self.Bits8To5 = self.MakeDepthConversionTable(8, 5)
- self.Bits6To8 = self.MakeDepthConversionTable(6, 8)
- self.Bits8To6 = self.MakeDepthConversionTable(8, 6)
- def MakeDepthConversionTable(self, a, b):
- a = 1 << a
- b = 1 << b
- result = []
- for i in range(a):
- result.append(int(float(i) / (a - 1) * (b - 1)) & 0xFF)
- return result
- def I4ToColor(self, v):
- i1 = self.Bits4To8[v >> 4]
- i2 = self.Bits4To8[v & 15]
- return [(i1, i1, i1), (i2, i2, i2)]
- def IA4ToColor(self, v):
- i = self.Bits4To8[v & 15]
- a = self.Bits4To8[v >> 4]
- return (i, i, i, a)
- def RGB565ToColor(self, v):
- return (self.Bits5To8[(v >> 11) & 31],
- self.Bits6To8[(v >> 5) & 63],
- self.Bits5To8[(v >> 0) & 31])
- def RGB5A3ToColor(self, v):
- if v & 0x8000: #RGB555
- return (self.Bits5To8[(v >> 10) & 31],
- self.Bits5To8[(v >> 5) & 31],
- self.Bits5To8[(v >> 0) & 31],
- 0xFF)
- else: #RGB4A3
- return (self.Bits4To8[(v >> 8) & 15],
- self.Bits4To8[(v >> 4) & 15],
- self.Bits4To8[(v >> 0) & 15],
- self.Bits3To8[(v >> 12) & 7])
- if __name__ == "__main__":
- with open(sys.argv[1], "rb") as f:
- name = sys.argv[1].split(".")[:-1]
- name = ".".join(name)
- imginfo = unpack(">2B2H2B2H2I2BH2BHI", f.read(0x20))
- #we're now at 0x20 aka start of raw data
- color = ColorConversion()
- if imginfo[0] == 0:
- tex = I4_Texture(imginfo[3], imginfo[2], color)
- tex.DecodeImage(f)
- tex.image.save("%s.png" % name)
- elif imginfo[0] == 1:
- tex = I8_Texture(imginfo[3], imginfo[2], color)
- tex.DecodeImage(f)
- tex.image.save("%s.png" % name)
- elif imginfo[0] == 2:
- tex = IA4_Texture(imginfo[3], imginfo[2], color)
- tex.DecodeImage(f)
- tex.image.save("%s.png" % name)
- elif imginfo[0] == 4:
- tex = RGB565_Texture(imginfo[3], imginfo[2], color)
- tex.DecodeImage(f)
- tex.image.save("%s.png" % name)
- elif imginfo[0] == 5:
- tex = RGB5A3_Texture(imginfo[3], imginfo[2], color)
- tex.DecodeImage(f)
- tex.image.save("%s.png" % name)
- elif imginfo[0] == 6:
- tex = RGBA32_Texture(imginfo[3], imginfo[2], color)
- tex.DecodeImage(f)
- tex.image.save("%s.png" % name)
- elif imginfo[0] == 7:
- tex = RGB565_Texture(imginfo[3], imginfo[2], color)
- tex.DecodeImage(f)
- tex.image.save("%s.png" % name)
- #TODO: double check these:
- elif imginfo[0] == 9:
- tex = CI8_Texture(imginfo[3], imginfo[2], color)
- assert imginfo[8] != 0 #palette
- f.seek(imginfo[8])
- palette = tex.DecodePalette(f)
- tex.DecodeImage(f, palette)
- tex.image.save("%s.png" % name)
- elif imginfo[0] == 14:
- tex = CMPR_Texture(imginfo[3], imginfo[2], color)
- tex.DecodeImage(f)
- tex.image.save("%s.png" % name)
Add Comment
Please, Sign In to add comment