commit e878ae9c8dbe6ab0ba45c2c44cbc18d272991ead
parent e71b8e1b60965f0805bc71e9279014823a52ff32
Author: Michael Savage <mikejsavage@gmail.com>
Date: Sat, 4 Nov 2017 15:38:31 +0200
Clean up BC5 decoder
Diffstat:
3 files changed, 79 insertions(+), 112 deletions(-)
diff --git a/decompress_bc.cc b/decompress_bc.cc
@@ -0,0 +1,72 @@
+#include "intrinsics.h"
+#include "linear_algebra.h"
+#include "array.h"
+
+struct AlphaBlock {
+ union {
+ u64 block;
+ struct {
+ u8 endpoints[ 2 ];
+ u8 selectors[ 6 ];
+ };
+ };
+};
+
+static void get_values( float ( &values )[ 8 ], u8 e0, u8 e1 ) {
+ values[ 0 ] = e0 / 255.0f;
+ values[ 1 ] = e1 / 255.0f;
+
+ if( e0 > e1 ) {
+ values[ 2 ] = ( values[ 0 ] * 6 + values[ 1 ] * 1 ) / 7;
+ values[ 3 ] = ( values[ 0 ] * 5 + values[ 1 ] * 2 ) / 7;
+ values[ 4 ] = ( values[ 0 ] * 4 + values[ 1 ] * 3 ) / 7;
+ values[ 5 ] = ( values[ 0 ] * 3 + values[ 1 ] * 4 ) / 7;
+ values[ 6 ] = ( values[ 0 ] * 2 + values[ 1 ] * 5 ) / 7;
+ values[ 7 ] = ( values[ 0 ] * 1 + values[ 1 ] * 6 ) / 7;
+ }
+ else {
+ values[ 2 ] = ( values[ 0 ] * 4 + values[ 1 ] * 1 ) / 5;
+ values[ 3 ] = ( values[ 0 ] * 3 + values[ 1 ] * 2 ) / 5;
+ values[ 4 ] = ( values[ 0 ] * 2 + values[ 1 ] * 3 ) / 5;
+ values[ 5 ] = ( values[ 0 ] * 1 + values[ 1 ] * 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 ) {
+ float values[ 8 ];
+ get_values( 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 float & R( v2 & rg ) {
+ return rg.x;
+}
+
+static float & G( v2 & rg ) {
+ return rg.y;
+}
+
+void decompress_bc5( array2d< v2 > 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++;
+ }
+ }
+}
diff --git a/decompress_bc.h b/decompress_bc.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "intrinsics.h"
+#include "linear_algebra.h"
+#include "array.h"
+
+void decompress_bc5( array2d< v2 > img, const u8 * bc5 );
diff --git a/unpack_bc5.cc b/unpack_bc5.cc
@@ -1,112 +0,0 @@
-#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;
-}