/* bcdec.h - v0.97 provides functions to decompress blocks of BC compressed images written by Sergii "iOrange" Kudlai in 2022 This library does not allocate memory and is trying to use as less stack as possible The library was never optimized specifically for speed but for the overall size it has zero external dependencies and is not using any runtime functions Supported BC formats: BC1 (also known as DXT1) + it's "binary alpha" variant BC1A (DXT1A) BC2 (also known as DXT3) BC3 (also known as DXT5) BC4 (also known as ATI1N) BC5 (also known as ATI2N) BC6H (HDR format) BC7 BC1/BC2/BC3/BC7 are expected to decompress into 4*4 RGBA blocks 8bit per component (32bit pixel) BC4/BC5 are expected to decompress into 4*4 R/RG blocks 8bit per component (8bit and 16bit pixel) BC6H is expected to decompress into 4*4 RGB blocks of either 32bit float or 16bit "half" per component (96bit or 48bit pixel) For more info, issues and suggestions please visit https://github.com/iOrange/bcdec CREDITS: Aras Pranckevicius (@aras-p) - BC1/BC3 decoders optimizations (up to 3x the speed) - BC6H/BC7 bits pulling routines optimizations - optimized BC6H by moving unquantize out of the loop - Split BC6H decompression function into 'half' and 'float' variants Michael Schmidt (@RunDevelopment) - Found better "magic" coefficients for integer interpolation of reference colors in BC1 color block, that match with the floating point interpolation. This also made it faster than integer division by 3! bugfixes: @linkmauve LICENSE: See end of file for license information. */ #ifndef BCDEC_HEADER_INCLUDED #define BCDEC_HEADER_INCLUDED #define BCDEC_VERSION_MAJOR … #define BCDEC_VERSION_MINOR … /* if BCDEC_STATIC causes problems, try defining BCDECDEF to 'inline' or 'static inline' */ #ifndef BCDECDEF #ifdef BCDEC_STATIC #define BCDECDEF … #else #ifdef __cplusplus #define BCDECDEF … #else #define BCDECDEF … #endif #endif #endif /* Used information sources: https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc6h-format https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format-mode-reference ! WARNING ! Khronos's BPTC partitions tables contain mistakes, do not use them! https://www.khronos.org/registry/DataFormat/specs/1.1/dataformat.1.1.html#BPTC ! Use tables from here instead ! https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt Leaving it here as it's a nice read https://fgiesen.wordpress.com/2021/10/04/gpu-bcn-decoding/ Fast half to float function from here https://gist.github.com/rygorous/2144712 */ #define BCDEC_BC1_BLOCK_SIZE … #define BCDEC_BC2_BLOCK_SIZE … #define BCDEC_BC3_BLOCK_SIZE … #define BCDEC_BC4_BLOCK_SIZE … #define BCDEC_BC5_BLOCK_SIZE … #define BCDEC_BC6H_BLOCK_SIZE … #define BCDEC_BC7_BLOCK_SIZE … #define BCDEC_BC1_COMPRESSED_SIZE(w, h) … #define BCDEC_BC2_COMPRESSED_SIZE(w, h) … #define BCDEC_BC3_COMPRESSED_SIZE(w, h) … #define BCDEC_BC4_COMPRESSED_SIZE(w, h) … #define BCDEC_BC5_COMPRESSED_SIZE(w, h) … #define BCDEC_BC6H_COMPRESSED_SIZE(w, h) … #define BCDEC_BC7_COMPRESSED_SIZE(w, h) … BCDECDEF void bcdec_bc1(const void* compressedBlock, void* decompressedBlock, int destinationPitch); BCDECDEF void bcdec_bc2(const void* compressedBlock, void* decompressedBlock, int destinationPitch); BCDECDEF void bcdec_bc3(const void* compressedBlock, void* decompressedBlock, int destinationPitch); BCDECDEF void bcdec_bc4(const void* compressedBlock, void* decompressedBlock, int destinationPitch); BCDECDEF void bcdec_bc5(const void* compressedBlock, void* decompressedBlock, int destinationPitch); BCDECDEF void bcdec_bc6h_float(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned); BCDECDEF void bcdec_bc6h_half(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned); BCDECDEF void bcdec_bc7(const void* compressedBlock, void* decompressedBlock, int destinationPitch); #endif /* BCDEC_HEADER_INCLUDED */ #ifdef BCDEC_IMPLEMENTATION static void bcdec__color_block(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int onlyOpaqueMode) { … } static void bcdec__sharp_alpha_block(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { … } static void bcdec__smooth_alpha_block(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int pixelSize) { … } bcdec__bitstream_t; static int bcdec__bitstream_read_bits(bcdec__bitstream_t* bstream, int numBits) { … } static int bcdec__bitstream_read_bit(bcdec__bitstream_t* bstream) { … } /* reversed bits pulling, used in BC6H decoding why ?? just why ??? */ static int bcdec__bitstream_read_bits_r(bcdec__bitstream_t* bstream, int numBits) { … } BCDECDEF void bcdec_bc1(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { … } BCDECDEF void bcdec_bc2(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { … } BCDECDEF void bcdec_bc3(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { … } BCDECDEF void bcdec_bc4(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { … } BCDECDEF void bcdec_bc5(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { … } /* http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend */ static int bcdec__extend_sign(int val, int bits) { … } static int bcdec__transform_inverse(int val, int a0, int bits, int isSigned) { … } /* pretty much copy-paste from documentation */ static int bcdec__unquantize(int val, int bits, int isSigned) { … } static int bcdec__interpolate(int a, int b, int* weights, int index) { … } static unsigned short bcdec__finish_unquantize(int val, int isSigned) { … } /* modified half_to_float_fast4 from https://gist.github.com/rygorous/2144712 */ static float bcdec__half_to_float_quick(unsigned short half) { … } BCDECDEF void bcdec_bc6h_half(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned) { … } BCDECDEF void bcdec_bc6h_float(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned) { … } static void bcdec__swap_values(int* a, int* b) { … } BCDECDEF void bcdec_bc7(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { … } #endif /* BCDEC_IMPLEMENTATION */ /* LICENSE: This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2022 Sergii Kudlai Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - The Unlicense This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to <https://unlicense.org> */