commit bf2264e5a5f916e0cf3880dfb475890a377e10dd
parent c1f80da0f6691535129dd5d7dca561a29f250493
Author: Michael Savage <mikejsavage@gmail.com>
Date: Fri, 3 Nov 2017 00:06:27 +0200
Not yet functional BC5 decoder
Diffstat:
unpack_bc5.cc | | | 112 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 112 insertions(+), 0 deletions(-)
diff --git a/unpack_bc5.cc b/unpack_bc5.cc
@@ -0,0 +1,112 @@
+#include "intrinsics.h"
+#include "array.h"
+
+#define STB_DXT_IMPLEMENTATION
+#include "stb_dxt.h"
+
+struct AlphaBlock {
+ union {
+ u64 block;
+ struct {
+ u8 endpoints[ 2 ];
+ u8 selectors[ 6 ];
+ };
+ };
+};
+
+struct RG8 {
+ u8 r, g;
+};
+
+static void get_values0( u8 * values, u8 e0, u8 e1 ) {
+ values[ 0 ] = e0;
+ values[ 1 ] = e1;
+ values[ 2 ] = ( e0 * 6 + e1 ) / 7;
+ values[ 3 ] = ( e0 * 5 + e1 * 2 ) / 7;
+ values[ 4 ] = ( e0 * 4 + e1 * 3 ) / 7;
+ values[ 5 ] = ( e0 * 3 + e1 * 4 ) / 7;
+ values[ 6 ] = ( e0 * 2 + e1 * 5 ) / 7;
+ values[ 7 ] = ( e0 + e1 * 6 ) / 7;
+}
+
+static void get_values1( u8 * values, u8 e0, u8 e1 ) {
+ values[ 0 ] = e0;
+ values[ 1 ] = e1;
+ values[ 2 ] = ( e0 * 4 + e1 ) / 5;
+ values[ 3 ] = ( e0 * 3 + e1 * 2 ) / 5;
+ values[ 4 ] = ( e0 * 2 + e1 * 3 ) / 5;
+ values[ 5 ] = ( e0 + e1 * 4 ) / 5;
+ values[ 6 ] = 0;
+ values[ 7 ] = 255;
+}
+
+template< typename T, typename Comp >
+static void decompress_alpha_block( array2d< T > img, Comp comp, size_t img_x, size_t img_y, const AlphaBlock * block ) {
+ u8 values[ 8 ];
+ if( block->endpoints[ 0 ] > block->endpoints[ 1 ] ) {
+ get_values0( values, block->endpoints[ 0 ], block->endpoints[ 1 ] );
+ }
+ else {
+ get_values1( values, block->endpoints[ 0 ], block->endpoints[ 1 ] );
+ }
+
+ for( u32 y = 0; y < 4; y++ ) {
+ for( u32 x = 0; x < 4; x++ ) {
+ u32 selector_bit = 3 * ( y * 4 + x );
+ u64 selector = ( block->block >> ( 16 + selector_bit ) ) & 7;
+
+ comp( img( img_x + x, img_y + y ) ) = values[ selector ];
+ }
+ }
+}
+
+static u8 & R( RG8 & rg ) {
+ return rg.r;
+}
+
+static u8 & G( RG8 & rg ) {
+ return rg.g;
+}
+
+void decompress_bc5( array2d< RG8 > img, const u8 * bc5 ) {
+ const AlphaBlock * blocks = ( const AlphaBlock * ) bc5;
+
+ size_t i = 0;
+ for( size_t y = 0; y < img.h; y += 4 ) {
+ for( size_t x = 0; x < img.w; x += 4 ) {
+ decompress_alpha_block( img, R, x, y, &blocks[ i ] );
+ i++;
+ decompress_alpha_block( img, G, x, y, &blocks[ i ] );
+ i++;
+ }
+ }
+}
+
+int main() {
+ u8 img[ 32 ];
+ for( int i = 0; i < 32; i += 2 ) {
+ img[ i ] = i / 2;
+ img[ i + 1 ] = ( 32 - i ) / 2;
+ }
+
+ for( int i = 0; i < 32; i++ ) {
+ printf( "%2hhu ", img[ i ] );
+ if( i % 8 == 7 ) printf( "\n" );
+ }
+ printf( "\n" );
+
+ u64 bc5;
+ stb_compress_bc5_block( ( u8 * ) &bc5, img );
+
+ u8 D[ 32 ];
+ array2d< RG8 > d( ( RG8 * ) D, 4, 4 );
+
+ decompress_bc5( d, ( const u8 * ) &bc5 );
+
+ for( int i = 0; i < 32; i++ ) {
+ printf( "%2hhu ", D[ i ] );
+ if( i % 8 == 7 ) printf( "\n" );
+ }
+
+ return 0;
+}