unpack_bc5.cc (2457B)
1 #include "intrinsics.h" 2 #include "array.h" 3 4 #define STB_DXT_IMPLEMENTATION 5 #include "stb_dxt.h" 6 7 struct AlphaBlock { 8 union { 9 u64 block; 10 struct { 11 u8 endpoints[ 2 ]; 12 u8 selectors[ 6 ]; 13 }; 14 }; 15 }; 16 17 struct RG8 { 18 u8 r, g; 19 }; 20 21 static void get_values0( u8 * values, u8 e0, u8 e1 ) { 22 values[ 0 ] = e0; 23 values[ 1 ] = e1; 24 values[ 2 ] = ( e0 * 6 + e1 ) / 7; 25 values[ 3 ] = ( e0 * 5 + e1 * 2 ) / 7; 26 values[ 4 ] = ( e0 * 4 + e1 * 3 ) / 7; 27 values[ 5 ] = ( e0 * 3 + e1 * 4 ) / 7; 28 values[ 6 ] = ( e0 * 2 + e1 * 5 ) / 7; 29 values[ 7 ] = ( e0 + e1 * 6 ) / 7; 30 } 31 32 static void get_values1( u8 * values, u8 e0, u8 e1 ) { 33 values[ 0 ] = e0; 34 values[ 1 ] = e1; 35 values[ 2 ] = ( e0 * 4 + e1 ) / 5; 36 values[ 3 ] = ( e0 * 3 + e1 * 2 ) / 5; 37 values[ 4 ] = ( e0 * 2 + e1 * 3 ) / 5; 38 values[ 5 ] = ( e0 + e1 * 4 ) / 5; 39 values[ 6 ] = 0; 40 values[ 7 ] = 255; 41 } 42 43 template< typename T, typename Comp > 44 static void decompress_alpha_block( array2d< T > img, Comp comp, size_t img_x, size_t img_y, const AlphaBlock * block ) { 45 u8 values[ 8 ]; 46 if( block->endpoints[ 0 ] > block->endpoints[ 1 ] ) { 47 get_values0( values, block->endpoints[ 0 ], block->endpoints[ 1 ] ); 48 } 49 else { 50 get_values1( values, block->endpoints[ 0 ], block->endpoints[ 1 ] ); 51 } 52 53 for( u32 y = 0; y < 4; y++ ) { 54 for( u32 x = 0; x < 4; x++ ) { 55 u32 selector_bit = 3 * ( y * 4 + x ); 56 u64 selector = ( block->block >> ( 16 + selector_bit ) ) & 7; 57 58 comp( img( img_x + x, img_y + y ) ) = values[ selector ]; 59 } 60 } 61 } 62 63 static u8 & R( RG8 & rg ) { 64 return rg.r; 65 } 66 67 static u8 & G( RG8 & rg ) { 68 return rg.g; 69 } 70 71 void decompress_bc5( array2d< RG8 > img, const u8 * bc5 ) { 72 const AlphaBlock * blocks = ( const AlphaBlock * ) bc5; 73 74 size_t i = 0; 75 for( size_t y = 0; y < img.h; y += 4 ) { 76 for( size_t x = 0; x < img.w; x += 4 ) { 77 decompress_alpha_block( img, R, x, y, &blocks[ i ] ); 78 i++; 79 decompress_alpha_block( img, G, x, y, &blocks[ i ] ); 80 i++; 81 } 82 } 83 } 84 85 int main() { 86 u8 img[ 32 ]; 87 for( int i = 0; i < 32; i += 2 ) { 88 img[ i ] = i / 2; 89 img[ i + 1 ] = ( 32 - i ) / 2; 90 } 91 92 for( int i = 0; i < 32; i++ ) { 93 printf( "%2hhu ", img[ i ] ); 94 if( i % 8 == 7 ) printf( "\n" ); 95 } 96 printf( "\n" ); 97 98 u64 bc5; 99 stb_compress_bc5_block( ( u8 * ) &bc5, img ); 100 101 u8 D[ 32 ]; 102 array2d< RG8 > d( ( RG8 * ) D, 4, 4 ); 103 104 decompress_bc5( d, ( const u8 * ) &bc5 ); 105 106 for( int i = 0; i < 32; i++ ) { 107 printf( "%2hhu ", D[ i ] ); 108 if( i % 8 == 7 ) printf( "\n" ); 109 } 110 111 return 0; 112 }