DXT1 image parsing
parent
1c0de5b963
commit
c89d94717d
@ -0,0 +1,72 @@
|
||||
class Color:
|
||||
def __init__(self, r = 0, g = 0, b = 0, a = 1):
|
||||
self.r = r
|
||||
self.g = g
|
||||
self.b = b
|
||||
self.a = a
|
||||
|
||||
def __add__(self, a):
|
||||
return Color(self.r + a.r, self.g + a.g, self.b + a.b, self.a + a.a)
|
||||
def __mul__(self, c):
|
||||
return Color(self.r * c, self.g * c, self.b * c, self.a * c)
|
||||
def __rmul__(self, c):
|
||||
return Color(self.r * c, self.g * c, self.b * c, self.a * c)
|
||||
def __iter__(self):
|
||||
return iter([self.r,self.g,self.b,self.a])
|
||||
def __repr__(self):
|
||||
return f'r: {self.r} g: {self.g} b: {self.b} a: {self.a}'
|
||||
def __str__(self):
|
||||
return self.to_hex()
|
||||
|
||||
@classmethod
|
||||
def from_565(cls, int_value):
|
||||
r = float((int_value & 0xF800) >> 11) / 0x1F
|
||||
g = float((int_value & 0x07E0) >> 5) / 0x3F
|
||||
b = float(int_value & 0x001F) / 0x1F
|
||||
|
||||
return cls(r,g,b)
|
||||
|
||||
def to_565(self):
|
||||
r = int(self.r * 0x1F)
|
||||
g = int(self.g * 0x3F)
|
||||
b = int(self.b * 0x1F)
|
||||
|
||||
return (r << 11) | (g << 5) | b
|
||||
|
||||
@classmethod
|
||||
def from_rgb24(cls, int_value):
|
||||
r = float((int_value & 0xFF0000) >> 16) / 0xFF
|
||||
g = float((int_value & 0x00FF00) >> 8) / 0xFF
|
||||
b = float(int_value & 0x0000FF) / 0xFF
|
||||
|
||||
return cls(r,g,b)
|
||||
|
||||
def to_rgb24(self):
|
||||
r = int(self.r * 0xFF)
|
||||
g = int(self.g * 0xFF)
|
||||
b = int(self.b * 0xFF)
|
||||
|
||||
return (r << 16) | (g << 8) | b
|
||||
|
||||
@classmethod
|
||||
def from_rgba32(cls, int_value):
|
||||
r = float((int_value & 0xFF000000) >> 24) / 0xFF
|
||||
g = float((int_value & 0x00FF0000) >> 16) / 0xFF
|
||||
b = float((int_value & 0x0000FF00) >> 8) / 0xFF
|
||||
a = float(int_value & 0x000000FF) / 0xFF
|
||||
|
||||
return cls(r,g,b,a)
|
||||
|
||||
def to_rgba32(self):
|
||||
r = int(self.r * 0xFF)
|
||||
g = int(self.g * 0xFF)
|
||||
b = int(self.b * 0xFF)
|
||||
a = int(self.a * 0xFF)
|
||||
|
||||
return (r << 24) | (g << 16) | (b << 8) | a
|
||||
|
||||
def to_hex(self):
|
||||
if self.a < 1:
|
||||
return hex(self.to_rgba32())
|
||||
else:
|
||||
return hex(self.to_rgb24())
|
@ -0,0 +1,62 @@
|
||||
import struct
|
||||
import math
|
||||
from color import Color
|
||||
|
||||
def byte_slice(byte):
|
||||
return [byte & 0x03,
|
||||
(byte & 0x0C) >> 2,
|
||||
(byte & 0x30) >> 4,
|
||||
(byte & 0xC0) >> 6]
|
||||
|
||||
def byte_unslice(indices):
|
||||
return indices[0] | (indices[1] << 2) | (indices[2] << 4) | (indices[3] << 6)
|
||||
|
||||
class DXT1Texture:
|
||||
def __init__(self, width = 4, height = 4, file = None):
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.block_width = math.ceil(width / 4)
|
||||
self.block_height = math.ceil(height / 4)
|
||||
self.block_count = self.block_width * self.block_height
|
||||
self.blocks = []
|
||||
|
||||
if file:
|
||||
self.read(file)
|
||||
|
||||
def __repr__(self):
|
||||
return f'{self.block_count} blocks: {self.blocks}'
|
||||
|
||||
def read(self, file):
|
||||
for x in range(self.block_count):
|
||||
self.blocks.append(DXT1Block(file))
|
||||
|
||||
def write(self, file):
|
||||
for block in self.blocks:
|
||||
block.write(file)
|
||||
|
||||
class DXT1Block:
|
||||
size = 8
|
||||
|
||||
def __init__(self, file = None):
|
||||
self.color0 = Color()
|
||||
self.color1 = Color()
|
||||
self.indices = [[0] * 4] * 4
|
||||
|
||||
if file:
|
||||
self.read(file)
|
||||
|
||||
def __repr__(self):
|
||||
return f'color0: ({repr(self.color0)}) color1: ({repr(self.color1)}), indices:{self.indices}'
|
||||
|
||||
def __str__(self):
|
||||
return f'color0: {str(self.color0)} color1: {str(self.color1)}, indices:{self.indices}'
|
||||
|
||||
def read(self, file):
|
||||
block = struct.unpack_from('<HHBBBB', file.read(self.size))
|
||||
|
||||
self.color0 = Color.from_565(block[0])
|
||||
self.color1 = Color.from_565(block[1])
|
||||
self.indices = list(map(byte_slice, block[2:6]))
|
||||
|
||||
def write(self, file):
|
||||
file.write(struct.pack('<HHBBBB', self.color0.to_565(), self.color1.to_565(), *map(byte_unslice, self.indices)))
|
Loading…
Reference in New Issue