Advertisement
AboodXD

DXT decompressor

Aug 1st, 2017
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.27 KB | None | 0 0
  1. import sys, time
  2.  
  3. # ----------\/-Start of libtxc_dxtn section-\/---------- #
  4. def EXP5TO8R(packedcol):
  5.     return int((((packedcol) >> 8) & 0xf8) | (((packedcol) >> 13) & 0x07))
  6.  
  7. def EXP6TO8G(packedcol):
  8.     return int((((packedcol) >> 3) & 0xfc) | (((packedcol) >>  9) & 0x03))
  9.  
  10. def EXP5TO8B(packedcol):
  11.     return int((((packedcol) << 3) & 0xf8) | (((packedcol) >>  2) & 0x07))
  12.  
  13. def EXP4TO8(col):
  14.     return int((col) | ((col) << 4))
  15.  
  16. # inefficient. To be efficient, it would be necessary to decode 16 pixels at once
  17.  
  18. def dxt135_decode_imageblock(pixdata, img_block_src, i, j, dxt_type):
  19.     color0 = pixdata[img_block_src] | (pixdata[img_block_src + 1] << 8)
  20.     color1 = pixdata[img_block_src + 2] | (pixdata[img_block_src + 3] << 8)
  21.     bits = pixdata[img_block_src + 4] | (pixdata[img_block_src + 5] << 8) | (pixdata[img_block_src + 6] << 16) | (pixdata[img_block_src + 7] << 24)
  22.     # What about big/little endian?
  23.     bit_pos = 2 * (j * 4 + i)
  24.     code = (bits >> bit_pos) & 3
  25.  
  26.     ACOMP = 255
  27.     if code == 0:
  28.         RCOMP = EXP5TO8R(color0)
  29.         GCOMP = EXP6TO8G(color0)
  30.         BCOMP = EXP5TO8B(color0)
  31.     elif code == 1:
  32.         RCOMP = EXP5TO8R(color1)
  33.         GCOMP = EXP6TO8G(color1)
  34.         BCOMP = EXP5TO8B(color1)
  35.     elif code == 2:
  36.         if (dxt_type > 1) or (color0 > color1):
  37.             RCOMP = ((EXP5TO8R(color0) * 2 + EXP5TO8R(color1)) // 3)
  38.             GCOMP = ((EXP6TO8G(color0) * 2 + EXP6TO8G(color1)) // 3)
  39.             BCOMP = ((EXP5TO8B(color0) * 2 + EXP5TO8B(color1)) // 3)
  40.         else:
  41.             RCOMP = ((EXP5TO8R(color0) + EXP5TO8R(color1)) // 2)
  42.             GCOMP = ((EXP6TO8G(color0) + EXP6TO8G(color1)) // 2)
  43.             BCOMP = ((EXP5TO8B(color0) + EXP5TO8B(color1)) // 2)
  44.     elif code == 3:
  45.         if (dxt_type > 1) or (color0 > color1):
  46.             RCOMP = ((EXP5TO8R(color0) + EXP5TO8R(color1) * 2) // 3)
  47.             GCOMP = ((EXP6TO8G(color0) + EXP6TO8G(color1) * 2) // 3)
  48.             BCOMP = ((EXP5TO8B(color0) + EXP5TO8B(color1) * 2) // 3)
  49.         else:
  50.             RCOMP = 0
  51.             GCOMP = 0
  52.             BCOMP = 0
  53.             if dxt_type == 1: ACOMP = 0
  54.     else:
  55.         # CANNOT happen (I hope)
  56.         print("")
  57.         print("Whoops, something went wrong while decompressing...")
  58.         print("")
  59.         print("Exiting in 5 seconds...")
  60.         time.sleep(5)
  61.         sys.exit(1)
  62.  
  63.     return ACOMP, RCOMP, GCOMP, BCOMP
  64.  
  65. def fetch_2d_texel_rgba_dxt1(srcRowStride, pixdata, i, j):
  66.  
  67.     """
  68.    Extract the (i,j) pixel from pixdata and return it
  69.    in RCOMP, GCOMP, BCOMP, ACOMP.
  70.    """
  71.  
  72.     blksrc = ((srcRowStride + 3) // 4 * (j // 4) + (i // 4)) * 8
  73.     test = pixdata[blksrc]
  74.     ACOMP, RCOMP, GCOMP, BCOMP = dxt135_decode_imageblock(pixdata, blksrc, i & 3, j & 3, 1)
  75.  
  76.     return bytes([RCOMP, GCOMP, BCOMP, ACOMP])
  77.  
  78. def fetch_2d_texel_rgba_dxt3(srcRowStride, pixdata, i, j):
  79.  
  80.     """
  81.    Extract the (i,j) pixel from pixdata and return it
  82.    in RCOMP, GCOMP, BCOMP, ACOMP.
  83.    """
  84.  
  85.     blksrc = ((srcRowStride + 3) // 4 * (j // 4) + (i // 4)) * 16
  86.     anibble = (pixdata[blksrc + ((j & 3) * 4 + (i & 3)) // 2] >> (4 * (i & 1))) & 0x0f
  87.     ACOMP, RCOMP, GCOMP, BCOMP = dxt135_decode_imageblock(pixdata, blksrc + 8, i & 3, j & 3, 2)
  88.     ACOMP = EXP4TO8(anibble)
  89.  
  90.     return bytes([RCOMP, GCOMP, BCOMP, ACOMP])
  91.  
  92. def fetch_2d_texel_rgba_dxt5(srcRowStride, pixdata, i, j):
  93.  
  94.     """
  95.    Extract the (i,j) pixel from pixdata and return it
  96.    in RCOMP, GCOMP, BCOMP, ACOMP.
  97.    """
  98.  
  99.     blksrc = ((srcRowStride + 3) // 4 * (j // 4) + (i // 4)) * 16
  100.     alpha0 = pixdata[blksrc]
  101.     alpha1 = pixdata[blksrc + 1]
  102.     # TODO test this!
  103.     bit_pos = ((j & 3) * 4 + (i & 3)) * 3
  104.     acodelow = pixdata[blksrc + 2 + bit_pos // 8]
  105.     acodehigh = pixdata[blksrc + 3 + bit_pos // 8]
  106.     code = (acodelow >> (bit_pos & 0x07) |
  107.         (acodehigh << (8 - (bit_pos & 0x07)))) & 0x07
  108.     ACOMP, RCOMP, GCOMP, BCOMP = dxt135_decode_imageblock(pixdata, blksrc + 8, i & 3, j & 3, 2)
  109.  
  110.     if code == 0:
  111.         ACOMP = alpha0
  112.     elif code == 1:
  113.         ACOMP = alpha1
  114.     elif alpha0 > alpha1:
  115.         ACOMP = (alpha0 * (8 - code) + (alpha1 * (code - 1))) // 7
  116.     elif code < 6:
  117.         ACOMP = (alpha0 * (6 - code) + (alpha1 * (code - 1))) // 5
  118.     elif code == 6:
  119.         ACOMP = 0
  120.     else:
  121.         ACOMP = 255
  122.  
  123.     return bytes([RCOMP, GCOMP, BCOMP, ACOMP])
  124.  
  125. def decompress(data, width, height, format_):
  126.  
  127.     """
  128.    Does the decompression for DXT compressed images.
  129.    """
  130.  
  131.     output = bytearray(width * height * 4)
  132.  
  133.     for y in range(height):
  134.         for x in range(width):
  135.             if (format_ == 0x31 or format_ == 0x431):
  136.                 outValue = fetch_2d_texel_rgba_dxt1(width, data, x, y)
  137.                 pos__ = (y * width + x) * 4
  138.                 output[pos__:pos__ + 4] = outValue
  139.             elif (format_ == 0x32 or format_ == 0x432):
  140.                 outValue = fetch_2d_texel_rgba_dxt3(width, data, x, y)
  141.                 pos__ = (y * width + x) * 4
  142.                 output[pos__:pos__ + 4] = outValue
  143.             elif (format_ == 0x33 or format_ == 0x433):
  144.                 outValue = fetch_2d_texel_rgba_dxt5(width, data, x, y)
  145.                 pos__ = (y * width + x) * 4
  146.                 output[pos__:pos__ + 4] = outValue
  147.  
  148.     return output # Output is a RGBA8_UNORM image
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement