v 0. Pasted by Anonymous as python at 2008-10-05 15:45:41 MSK and set expiration to never.
v 1. Edited by _W as python at 2008-10-05 16:34:04 MSK and set expiration to never.

Paste will expire never.

  1. import zlib
  2. import struct
  3. import sys
  4.  
  5. try:
  6.     input_dds_filename = sys.argv[1]
  7. except IndexError:
  8.     print "usage: python zdxt.py input_dxt1.dds"
  9.     exit(1)
  10.    
  11. data = open(input_dds_filename, 'rb').read()
  12.  
  13. def cm(d):
  14.     return zlib.compress(d, 9)
  15.    
  16. def cml(d):
  17.     return len(cm(d))
  18.  
  19. def interleave(a0, a1):
  20.     return ''.join((aa0 + aa1 for aa0, aa1 in zip(a0, a1)))   
  21. def unleave(data):
  22.     return data[0::2], data[1::2]
  23.    
  24.    
  25. def UNPACK5(x): return ((x) & 0x1f) * 255 / 31
  26. def UNPACK6(x): return ((x) & 0x3f) * 255 / 63
  27. def PACK5(x): return (x / 8)
  28. def PACK6(x): return (x / 4)
  29.  
  30.    
  31. def word_to_rgb_bytes(cw):
  32.     return map(chr, (UNPACK5(cw >> 11), UNPACK6(cw >>  5), UNPACK5(cw)))
  33. def rgb_bytes_to_word(rgb):
  34.     r, g, b = map(ord, rgb)
  35.     return (PACK5(r)<<11) | (PACK6(g) << 5) | PACK5(b)
  36.  
  37. def w2c(cw):
  38.     return ''.join(word_to_rgb_bytes(cw))   
  39.        
  40. def decompose_colors_indices(img_data, w, h):
  41.     blocks = [img_data[i*8:i*8 + 8] for i in range(w*h/16)]
  42.  
  43.     colors = ''.join([b[0:4] for b in blocks])
  44.     indices = ''.join([b[4:8] for b in blocks])
  45.  
  46.     c01s = [[struct.unpack('H', b[i*2:i*2 + 2])[0] for b in blocks] for i in range(2)]
  47.    
  48.     colors2 = ''.join([ struct.pack("HH", swap_bits_tbl[c0], swap_bits_tbl[c1]) for c0, c1 in zip(*c01s) ])
  49.    
  50.     return colors2, indices
  51.  
  52. def prepare_and_check(data):   
  53.     header, img_data = data[:128], data[128:]
  54.  
  55.     assert header[0:4] == "DDS "
  56.     assert header[0x54:0x58] == "DXT1", ("only DXT1 compression test is implemented (got %s)" % header[0x54:0x58])
  57.     h, w = struct.unpack("<II", header[12:20])
  58.    
  59.     if struct.unpack("<I", header[0x6c:0x70])[0] & 0x00000008:
  60.         print "warning, mipmaps and non-main surfaces are ignored."
  61.         img_data = img_data[:w*h / 2]
  62.    
  63.     assert w%4 == 0 and h%4 == 0
  64.     print "size:", w, h
  65.    
  66.     return header, img_data, w, h
  67.    
  68.  
  69. def compress_dxt1(header, img_data, w, h):
  70.  
  71.    
  72.     colors2, indices = decompose_colors_indices(img_data, w, h)
  73.     return cm(header), cm(indices), cm(colors2)
  74.  
  75. #rrrrrggggggbbbbb -> g0 r0 g1 b0 r1 g2 b1 r2 g3 b2 r3 g4 b3 r4 g5 b4
  76. def swap_bits(cw):
  77.     result = 0
  78.     for b_index in range(16):
  79.         if b_index == 0:
  80.             bit = (cw >> 5) & 1
  81.         else:
  82.             tmp = (cw & 0x1f) | ((cw >> 1) & ~0x1f)
  83.             comp = (b_index - 1) % 3
  84.             shift = (b_index - 1) / 3
  85.             bit = (tmp >> (5 * comp + shift)) & 1
  86.        
  87.         result = result | (bit << b_index)
  88.        
  89.     return result
  90.    
  91. swap_bits_tbl = map(swap_bits, range(2**16))
  92. unswap_bits_tbl = range(2**16)
  93. for i, x in enumerate(swap_bits_tbl):
  94.     unswap_bits_tbl[x] = i
  95.            
  96.    
  97. def decompress(header, indices, colors2):
  98.     header, indices, colors2 = map(zlib.decompress, (header, indices, colors2))
  99.    
  100.     c0s = [unswap_bits_tbl[ struct.unpack("H", colors2[i:i+2])[0] ] for i in range(0, len(colors2), 4)]
  101.     c1s = [unswap_bits_tbl[ struct.unpack("H", colors2[i:i+2])[0] ] for i in range(2, len(colors2), 4)]
  102.  
  103.     block_indices = [indices[i:i+4] for i in range(0, len(indices), 4) ]
  104.     block_colors = [ struct.pack("HH", c0, c1) for c0, c1 in zip(c0s, c1s) ]
  105.    
  106.     assert len(block_indices) == len(block_colors)
  107.     blocks = [c + i for c, i in zip(block_colors, block_indices)]
  108.    
  109.     img_data = ''.join(blocks)
  110.     return header + img_data
  111.    
  112.  
  113. header, img_data, w, h = prepare_and_check(data)
  114. data = header + img_data
  115. tmp = compress_dxt1(header, img_data, w, h)
  116. print "decomposed compression:", sum(map(len, tmp))
  117. data2 = decompress(*tmp)
  118.  
  119. assert data == data2
  120. print "simple compression:    ", cml(data)
  121. print "original:              ", len(data)
  122.  
  123. open('img_dxtex.test.dds', 'wb').write(data2)