mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-26 17:24:31 +03:00
blp: Simplify dxt1/dxt3/dxt5 decoding
This commit is contained in:
parent
adaa703576
commit
fcba3583c3
|
@ -46,28 +46,29 @@ BLP_ALPHA_ENCODING_DXT3 = 1
|
|||
BLP_ALPHA_ENCODING_DXT5 = 7
|
||||
|
||||
|
||||
def unpack_565(i):
|
||||
return (
|
||||
((i >> 11) & 0x1f) << 3,
|
||||
((i >> 5) & 0x3f) << 2,
|
||||
(i & 0x1f) << 3
|
||||
)
|
||||
|
||||
|
||||
def decode_dxt1(data, alpha=False):
|
||||
"""
|
||||
input: one "row" of data (i.e. will produce 4*width pixels)
|
||||
"""
|
||||
|
||||
blocks = len(data) // 8 # number of blocks in row
|
||||
final = (bytearray(), bytearray(), bytearray(), bytearray())
|
||||
ret = (bytearray(), bytearray(), bytearray(), bytearray())
|
||||
|
||||
for block in range(blocks):
|
||||
# Decode next 8-byte block.
|
||||
idx = block * 8
|
||||
color0, color1, bits = struct.unpack("<HHI", data[idx:idx + 8])
|
||||
|
||||
# color 0, packed 5-6-5
|
||||
r0 = ((color0 >> 11) & 0x1f) << 3
|
||||
g0 = ((color0 >> 5) & 0x3f) << 2
|
||||
b0 = (color0 & 0x1f) << 3
|
||||
|
||||
# color 1, packed 5-6-5
|
||||
r1 = ((color1 >> 11) & 0x1f) << 3
|
||||
g1 = ((color1 >> 5) & 0x3f) << 2
|
||||
b1 = (color1 & 0x1f) << 3
|
||||
r0, g0, b0 = unpack_565(color0)
|
||||
r1, g1, b1 = unpack_565(color1)
|
||||
|
||||
# Decode this block into 4x4 pixels
|
||||
# Accumulate the results onto our 4 row accumulators
|
||||
|
@ -77,39 +78,35 @@ def decode_dxt1(data, alpha=False):
|
|||
|
||||
control = bits & 3
|
||||
bits = bits >> 2
|
||||
|
||||
a = 0xFF
|
||||
if control == 0:
|
||||
final[j].append(r0)
|
||||
final[j].append(g0)
|
||||
final[j].append(b0)
|
||||
r, g, b = r0, g0, b0
|
||||
elif control == 1:
|
||||
final[j].append(r1)
|
||||
final[j].append(g1)
|
||||
final[j].append(b1)
|
||||
r, g, b = r1, g1, b1
|
||||
elif control == 2:
|
||||
if color0 > color1:
|
||||
final[j].append((2 * r0 + r1) // 3)
|
||||
final[j].append((2 * g0 + g1) // 3)
|
||||
final[j].append((2 * b0 + b1) // 3)
|
||||
r = (2 * r0 + r1) // 3
|
||||
g = (2 * g0 + g1) // 3
|
||||
b = (2 * b0 + b1) // 3
|
||||
else:
|
||||
final[j].append((r0 + r1) // 2)
|
||||
final[j].append((g0 + g1) // 2)
|
||||
final[j].append((b0 + b1) // 2)
|
||||
r = (r0 + r1) // 2
|
||||
g = (g0 + g1) // 2
|
||||
b = (b0 + b1) // 2
|
||||
elif control == 3:
|
||||
if color0 > color1:
|
||||
final[j].append((2 * r1 + r0) // 3)
|
||||
final[j].append((2 * g1 + g0) // 3)
|
||||
final[j].append((2 * b1 + b0) // 3)
|
||||
r = (2 * r1 + r0) // 3
|
||||
g = (2 * g1 + g0) // 3
|
||||
b = (2 * b1 + b0) // 3
|
||||
else:
|
||||
final[j].append(0)
|
||||
final[j].append(0)
|
||||
final[j].append(0)
|
||||
if alpha:
|
||||
final[j].append(0)
|
||||
r, g, b, a = 0, 0, 0, 0
|
||||
|
||||
if alpha:
|
||||
final[j].append(0xFF)
|
||||
ret[j].extend([r, g, b, a])
|
||||
else:
|
||||
ret[j].extend([r, g, b])
|
||||
|
||||
return final
|
||||
return ret
|
||||
|
||||
|
||||
def decode_dxt3(data):
|
||||
|
@ -118,7 +115,7 @@ def decode_dxt3(data):
|
|||
"""
|
||||
|
||||
blocks = len(data) // 16 # number of blocks in row
|
||||
final = (bytearray(), bytearray(), bytearray(), bytearray())
|
||||
ret = (bytearray(), bytearray(), bytearray(), bytearray())
|
||||
|
||||
for block in range(blocks):
|
||||
idx = block * 16
|
||||
|
@ -129,15 +126,8 @@ def decode_dxt3(data):
|
|||
|
||||
code, = struct.unpack("<I", block[12:])
|
||||
|
||||
# color 0, packed 5-6-5
|
||||
r0 = ((color0 >> 11) & 0x1f) << 3
|
||||
g0 = ((color0 >> 5) & 0x3f) << 2
|
||||
b0 = (color0 & 0x1f) << 3
|
||||
|
||||
# color 1, packed 5-6-5
|
||||
r1 = ((color1 >> 11) & 0x1f) << 3
|
||||
g1 = ((color1 >> 5) & 0x3f) << 2
|
||||
b1 = (color1 & 0x1f) << 3
|
||||
r0, g0, b0 = unpack_565(color0)
|
||||
r1, g1, b1 = unpack_565(color1)
|
||||
|
||||
for j in range(4):
|
||||
high = False # Do we want the higher bits?
|
||||
|
@ -155,27 +145,21 @@ def decode_dxt3(data):
|
|||
color_code = (code >> 2 * (4 * j + i)) & 0x03
|
||||
|
||||
if color_code == 0:
|
||||
final[j].append(r0)
|
||||
final[j].append(g0)
|
||||
final[j].append(b0)
|
||||
final[j].append(a)
|
||||
r, g, b = r0, g0, b0
|
||||
elif color_code == 1:
|
||||
final[j].append(r1)
|
||||
final[j].append(g1)
|
||||
final[j].append(b1)
|
||||
final[j].append(a)
|
||||
r, g, b = r1, g1, b1
|
||||
elif color_code == 2:
|
||||
final[j].append((2 * r0 + r1) // 3)
|
||||
final[j].append((2 * g0 + g1) // 3)
|
||||
final[j].append((2 * b0 + b1) // 3)
|
||||
final[j].append(a)
|
||||
r = (2 * r0 + r1) // 3
|
||||
g = (2 * g0 + g1) // 3
|
||||
b = (2 * b0 + b1) // 3
|
||||
elif color_code == 3:
|
||||
final[j].append((2 * r1 + r0) // 3)
|
||||
final[j].append((2 * g1 + g0) // 3)
|
||||
final[j].append((2 * b1 + b0) // 3)
|
||||
final[j].append(a)
|
||||
r = (2 * r1 + r0) // 3
|
||||
g = (2 * g1 + g0) // 3
|
||||
b = (2 * b1 + b0) // 3
|
||||
|
||||
return final
|
||||
ret[j].extend([r, g, b, a])
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def decode_dxt5(data):
|
||||
|
@ -184,7 +168,7 @@ def decode_dxt5(data):
|
|||
"""
|
||||
|
||||
blocks = len(data) // 16 # number of blocks in row
|
||||
final = (bytearray(), bytearray(), bytearray(), bytearray())
|
||||
ret = (bytearray(), bytearray(), bytearray(), bytearray())
|
||||
|
||||
for block in range(blocks):
|
||||
idx = block * 16
|
||||
|
@ -202,15 +186,8 @@ def decode_dxt5(data):
|
|||
|
||||
code, = struct.unpack("<I", block[12:])
|
||||
|
||||
# color 0, packed 5-6-5
|
||||
r0 = ((color0 >> 11) & 0x1f) << 3
|
||||
g0 = ((color0 >> 5) & 0x3f) << 2
|
||||
b0 = (color0 & 0x1f) << 3
|
||||
|
||||
# color 1, packed 5-6-5
|
||||
r1 = ((color1 >> 11) & 0x1f) << 3
|
||||
g1 = ((color1 >> 5) & 0x3f) << 2
|
||||
b1 = (color1 & 0x1f) << 3
|
||||
r0, g0, b0 = unpack_565(color0)
|
||||
r1, g1, b1 = unpack_565(color1)
|
||||
|
||||
for j in range(4):
|
||||
for i in range(4):
|
||||
|
@ -230,38 +207,31 @@ def decode_dxt5(data):
|
|||
a = a1
|
||||
elif a0 > a1:
|
||||
a = ((8 - alphacode) * a0 + (alphacode - 1) * a1) // 7
|
||||
elif alphacode == 6:
|
||||
a = 0
|
||||
elif alphacode == 7:
|
||||
a = 255
|
||||
else:
|
||||
if alphacode == 6:
|
||||
a = 0
|
||||
elif alphacode == 7:
|
||||
a = 255
|
||||
else:
|
||||
a = ((6 - alphacode) * a0 + (alphacode - 1) * a1) // 5
|
||||
a = ((6 - alphacode) * a0 + (alphacode - 1) * a1) // 5
|
||||
|
||||
color_code = (code >> 2 * (4 * j + i)) & 0x03
|
||||
|
||||
if color_code == 0:
|
||||
final[j].append(r0)
|
||||
final[j].append(g0)
|
||||
final[j].append(b0)
|
||||
final[j].append(a)
|
||||
r, g, b = r0, g0, b0
|
||||
elif color_code == 1:
|
||||
final[j].append(r1)
|
||||
final[j].append(g1)
|
||||
final[j].append(b1)
|
||||
final[j].append(a)
|
||||
r, g, b = r1, g1, b1
|
||||
elif color_code == 2:
|
||||
final[j].append((2 * r0 + r1) // 3)
|
||||
final[j].append((2 * g0 + g1) // 3)
|
||||
final[j].append((2 * b0 + b1) // 3)
|
||||
final[j].append(a)
|
||||
r = (2 * r0 + r1) // 3
|
||||
g = (2 * g0 + g1) // 3
|
||||
b = (2 * b0 + b1) // 3
|
||||
elif color_code == 3:
|
||||
final[j].append((2 * r1 + r0) // 3)
|
||||
final[j].append((2 * g1 + g0) // 3)
|
||||
final[j].append((2 * b1 + b0) // 3)
|
||||
final[j].append(a)
|
||||
r = (2 * r1 + r0) // 3
|
||||
g = (2 * g1 + g0) // 3
|
||||
b = (2 * b1 + b0) // 3
|
||||
|
||||
return tuple(final)
|
||||
ret[j].extend([r, g, b, a])
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def getpalette(data):
|
||||
|
|
Loading…
Reference in New Issue
Block a user