In modern graphics application development, texture resources often consume a significant amount of memory and bandwidth. To optimize performance, reduce loading times, and save storage space, developers typically use GPU-supported compressed formats (such as DXT1/DXT5) to store textures. However, standard DXT compression, while directly decompressible by the GPU, has limited compression ratios, making it unsuitable for network transmission or disk storage.
Crunch (also known as CCI, or “Crunch Compression Interface”) was created to address this issue. Developed by Richard Geldreich (a former ATI/AMD engineer and author of the LZHAM compression algorithm), it aims to provide a more efficient DXT texture compression solution than traditional ZIP, while supporting fast runtime decompression back to standard DXT format.
1. What is Crunch?
Crunch is a lossy + lossless hybrid compression library designed for block-compressed textures like DXT1/DXT5 (also known as BC1/BC3). Its workflow is as follows:
-
Preprocessing Stage (Offline):
Encode the original image to DXT format.
Perform “semantic-aware” lossy compression on the DXT data (by clustering similar encoded blocks).
Then apply a custom entropy encoder (similar to LZ77 + Huffman) for lossless compression, generating a .crn file. -
Runtime Stage (Online):
Load the .crn file.
Quickly decompress to standard DXT data (no CPU decoding to RGBA required).
Directly upload to the GPU for use.
This design typically results in .crn files being 2–4 times smaller than DXT files compressed with ZIP, while decompression speeds are extremely fast (hundreds of MB per second), making it ideal for games and mobile applications.
Note: cci.20190615 is a stable version of the Crunch library released on June 15, 2019 (commonly found in GitHub archives or third-party builds).
2. Core Advantages
✅ High Compression Ratio: Significantly smaller size compared to ZIP + DXT.
✅ GPU Compatible: The decompressed result is standard DXT, requiring no additional conversion.
✅ Fast Decompression: Pure CPU decompression, independent of GPU.
✅ Open Source and Free: MIT License, usable for commercial projects.
✅ Supports Mipmaps, Cubemaps, and multiple mip levels.
3. Basic Usage Process
- Install Crunch
You can obtain the source code from the official GitHub (although the original repository has been archived):
bash
git clone https://github.com/DaemonEngine/crunch.git
or use a community-maintained version.
After compilation, it will generate the crunch command-line tool and the static library libcrnlib.a (or .lib).
- Command Line Compression Example
Convert PNG to .crn:
bash
crunch -file input.png -out output.crn -dxt1
Or retain the Alpha channel (using DXT5):
bash
crunch -file input.png -out output.crn -dxt5
- C++ Integration Example: Runtime Decompression of .crn to DXT
Below is a simplified C++ example demonstrating how to load a .crn file and decompress it to DXT data:
cpp
#include “crnlib.h”
#include
#include
#include
bool loadCRNAndDecompress(const char* filename, std::vector& dxtData,
uint32_t& width, uint32_t& height, crn_format& fmt) {
// Read .crn file into memory
std::ifstream file(filename, std::ios::binary);
if (!file) return false;
file.seekg(0, std::ios::end);
size_t fileSize = file.tellg();
file.seekg(0, std::ios::beg);
std::vector crnData(fileSize);
file.read(reinterpret_cast(crnData.data()), fileSize);
file.close();
// Get CRN header information
crn_uint32 actualDataSize = static_cast(fileSize);
crn_texture_info texInfo;
if (!crn_get_texture_info(crnData.data(), actualDataSize, &texInfo)) {
std::cerr << “Failed to get CRN texture info!” << std::endl;
return false;
}
width = texInfo.m_width;
height = texInfo.m_height;
fmt = texInfo.m_format;
// Calculate decompressed DXT data size
crn_uint32 dxtSize = crn_get_bytes_per_dxt_block(fmt) * ((width + 3) / 4) * ((height + 3) / 4);
dxtData.resize(dxtSize);
// Decompress to DXT
if (!crn_decompress_crn_to_dxt(
crnData.data(), actualDataSize,
dxtData.data(), static_cast(dxtData.size()),
fmt)) {
std::cerr << “Failed to decompress CRN to DXT!” << std::endl;
return false;
}
return true;
}
// Usage Example
int main() {
std::vector dxtBuffer;
uint32_t w, h;
crn_format fmt;
if (loadCRNAndDecompress(“texture.crn”, dxtBuffer, w, h, fmt)) {
std::cout << “Successfully decompressed CRN: ” << w << “x” << h
” , Format: ” << (fmt == cCRNFmtDXT1 ? “DXT1” : “DXT5”) << std::endl;
// At this point, dxtBuffer can be directly passed to OpenGL/DirectX
// For example, OpenGL:
// glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
w, h, 0, dxtBuffer.size(), dxtBuffer.data());
}
return 0;
}
Note: In actual projects, you need to link crnlib and include the header file path.
4. Applicable Scenarios
Mobile Games: Reduce APK/IPA size.
PC/Console Games: Speed up texture loading and reduce disk usage.
WebGL Applications: Reduce download size through pre-compression (requires a JS unpacker, such as crunch.js).
Remote Rendering/Cloud Gaming: Efficiently transmit texture assets.
5. Limitations
❌ Only supports DXT1/DXT5 (BC1/BC3), does not support modern formats like ASTC, ETC2, etc.
❌ Compression process is relatively slow, suitable for offline processing, not for real-time compression.
❌ Lossy compression: While visual quality is high, it is not completely lossless.
6. Alternatives
Basis Universal: Developed by Google, supports cross-platform (including Vulkan/Metal), can transcode to various GPU formats, and is the spiritual successor to Crunch.
ETC2/EAC + Zstandard: Suitable for mobile platforms.
ASTC + Oodle Texture: High-end console/PC solution.
Conclusion
Crunch (cci.20190615) is a classic tool in the field of DXT texture compression, widely used in engines like Unity and Unreal Engine during the 2010s. Although there are more advanced solutions today (like Basis), Crunch remains worth understanding due to its simplicity, efficiency, and maturity. For projects requiring extreme compression of DXT textures, it is still a reliable choice.
📚 Official Resources (Archived):
GitHub: https://github.com/DaemonEngine/crunch
Documentation: PDFs and README in the docs/ directory.