2019-06-26 15:26:19 +03:00

124 lines
3.9 KiB
Python

from bitset import bitset
from range import *
def unquantize_color(i, quant):
assert i >= 0 and i < RANGE_CARDINALITY_TABLE[quant]
assert quant >= RANGE_2 and quant <= RANGE_256
def unquant(a, b, c, d):
"""
This is the magic bit twiddling hack ARM uses in the ASTC decoder
specification to avoid full-width multipliers.
T = D * C + B;
T = T ^ A;
T = (A & 0x80) | (T >> 2);
"""
return (a & 0x80) | (((d*c + b) ^ a) >> 2)
def bit_only(lst):
return bitset.from_list(lst).number()
def trit_quint(A, B, C, D):
return unquant(
bitset.from_list(A).number(),
bitset.from_list(B).number(),
C,
bitset.from_list(D).number())
bits = bitset(8, i)
a = bits.get(0)
b = bits.get(1)
c = bits.get(2)
d = bits.get(3)
e = bits.get(4)
f = bits.get(5)
g = bits.get(6)
h = bits.get(7)
if quant == RANGE_2:
return bit_only([a,a,a,a,a,a,a,a])
elif quant == RANGE_3:
return [0, 128, 255][i]
elif quant == RANGE_4:
return bit_only([b,a,b,a,b,a,b,a])
elif quant == RANGE_5:
return [0, 64, 128, 192, 255][i]
elif quant == RANGE_6:
return trit_quint([a,a,a,a,a,a,a,a,a], [0,0,0,0,0,0,0,0,0], 204, [c,b])
elif quant == RANGE_8:
return bit_only([c,b,a,c,b,a,c,b])
elif quant == RANGE_10:
return trit_quint([a,a,a,a,a,a,a,a,a], [0,0,0,0,0,0,0,0,0], 113, [d,c,b])
elif quant == RANGE_12:
return trit_quint([a,a,a,a,a,a,a,a,a], [b,0,0,0,b,0,b,b,0], 93, [d,c])
elif quant == RANGE_16:
return bit_only([d,c,b,a,d,c,b,a])
elif quant == RANGE_20:
return trit_quint([a,a,a,a,a,a,a,a,a], [b,0,0,0,0,b,b,0,0], 54, [e,d,c])
elif quant == RANGE_24:
return trit_quint([a,a,a,a,a,a,a,a,a], [c,b,0,0,0,c,b,c,b], 44, [e,d])
elif quant == RANGE_32:
return bit_only([e,d,c,b,a,e,d,c])
elif quant == RANGE_40:
return trit_quint([a,a,a,a,a,a,a,a,a], [c,b,0,0,0,0,c,b,c], 26, [f,e,d])
elif quant == RANGE_48:
return trit_quint([a,a,a,a,a,a,a,a,a], [d,c,b,0,0,0,d,c,b], 22, [f,e])
elif quant == RANGE_64:
return bit_only([f,e,d,c,b,a,f,e])
elif quant == RANGE_80:
return trit_quint([a,a,a,a,a,a,a,a,a], [d,c,b,0,0,0,0,d,c], 13, [g,f,e])
elif quant == RANGE_96:
return trit_quint([a,a,a,a,a,a,a,a,a], [e,d,c,b,0,0,0,e,d], 11, [g,f])
elif quant == RANGE_128:
return bit_only([g,f,e,d,c,b,a,g])
elif quant == RANGE_160:
return trit_quint([a,a,a,a,a,a,a,a,a], [e,d,c,b,0,0,0,0,e], 6, [h,g,f])
elif quant == RANGE_192:
return trit_quint([a,a,a,a,a,a,a,a,a], [f,e,d,c,b,0,0,0,f], 5, [h,g])
elif quant == RANGE_256:
return bit_only([h,g,f,e,d,c,b,a])
assert False
def find_closest(unquantized, value):
assert isinstance(unquantized, list)
assert len(unquantized) > 0
assert isinstance(value, int)
class Item:
def __init__(self, index):
self.index = index
self.cost = abs(value - unquantized[self.index])
def __lt__(self, other):
return self.cost < other.cost
return min(map(Item, range(len(unquantized)))).index
def color_quantize_table(color_unquantize_table):
return \
[
[
find_closest(color_unquantize_table[quant], i)
for i in range(256)
]
for quant in range(RANGE_MAX)
]
def color_unquantize_table():
return \
[
[
unquantize_color(i, quant)
for i in range(RANGE_CARDINALITY_TABLE[quant])
]
for quant in range(RANGE_MAX)
]
if __name__ == "__main__":
unquantize_table = color_unquantize_table()
quantize_table = color_quantize_table(unquantize_table)
print(unquantize_table)
print(quantize_table)