WebAssembly library for BCN (BC1-BC7, BC6H) texture compression and decompression
npm install bcn-encdec-wasmbash
npm install bcn-encdec-wasm
`
Quick Start
`javascript
import BCNModule from 'bcn-encdec-wasm';
// Initialize the module
const Module = await BCNModule();
// Initialize encoders
const idealMode = Module._get_bc1_ideal_mode();
Module._init(idealMode);
Module._init_bc7(); // Required for BC7 encoding
// Example: Compress image to BC7
const width = 512; // Must be multiple of 4
const height = 512; // Must be multiple of 4
// Prepare source RGBA data (Uint8Array)
const sourcePixels = new Uint8Array(width height 4);
// ... fill with your image data ...
// Calculate compressed size
const blocksX = width / 4;
const blocksY = height / 4;
const compressedSize = blocksX blocksY 16; // BC7 uses 16 bytes per block
// Allocate memory
const srcPtr = Module._malloc(sourcePixels.length);
const dstPtr = Module._malloc(compressedSize);
// Copy source data to WASM memory
Module.HEAPU8.set(sourcePixels, srcPtr);
// Compress to BC7 (quality 0-4)
Module._encode_bc7_image(dstPtr, srcPtr, width, height, 4);
// Get compressed data
const compressed = new Uint8Array(
Module.HEAPU8.buffer,
dstPtr,
compressedSize
);
const result = new Uint8Array(compressed); // Copy before freeing
// Free memory
Module._free(srcPtr);
Module._free(dstPtr);
console.log('Compressed!', result);
`
API Reference
$3
`javascript
Module._init(mode) // Initialize rgbcx for BC1-BC5
Module._init_bc7() // Initialize BC7 encoder (call once)
`
$3
#### BC1 (DXT1)
`javascript
Module._encode_bc1_image(level, pDst, pSrc, width, height, allow_3color, use_transparent)
// level: 0-18 (quality)
// Block size: 8 bytes
`
#### BC2 (DXT3)
`javascript
Module._encode_bc2_image(level, pDst, pSrc, width, height)
// Block size: 16 bytes
`
#### BC3 (DXT5)
`javascript
Module._encode_bc3_image(level, pDst, pSrc, width, height)
// Block size: 16 bytes
`
#### BC4 (Single Channel)
`javascript
Module._encode_bc4_image(pDst, pSrc, width, height, channel)
// channel: 0=R, 1=G, 2=B (converts RGB to grayscale)
// Block size: 8 bytes
`
#### BC5 (Dual Channel)
`javascript
Module._encode_bc5_image(pDst, pSrc, width, height, chan0, chan1)
// chan0, chan1: 0=R, 1=G, 2=B
// Block size: 16 bytes
`
#### BC6H (HDR)
`javascript
Module._encode_bc6h_image(pDst, pSrc, width, height)
// pSrc: Float32Array (RGB, 3 floats per pixel)
// Block size: 16 bytes
`
#### BC7 (High Quality)
`javascript
Module._encode_bc7_image(pDst, pSrc, width, height, quality)
// quality: 0-4 (0=fastest, 4=best quality)
// Block size: 16 bytes
`
$3
`javascript
Module._decode_bc1_image(pSrc, pDst, width, height, set_alpha, mode)
Module._decode_bc4_image(pSrc, pDst, width, height)
Module._decode_bc6h_image(pSrc, pDst, width, height) // Output: Float32Array RGB
Module._decode_bc7_image(pSrc, pDst, width, height)
`
$3
`javascript
const ptr = Module._malloc(size) // Allocate memory
Module._free(ptr) // Free memory
// Access memory
Module.HEAPU8 // Uint8Array view
Module.HEAPF32 // Float32Array view
`
Compressed Size Calculation
`javascript
function getCompressedSize(width, height, format) {
const blocksX = width / 4;
const blocksY = height / 4;
const totalBlocks = blocksX * blocksY;
const blockSizes = {
'BC1': 8, // BC1, BC4
'BC2': 16, // BC2, BC3, BC5, BC6H, BC7
};
return totalBlocks * blockSizes[format];
}
`
Complete Example: BC7 Encoding & Decoding
`javascript
import BCNModule from 'bcn-encdec-wasm';
async function compressImage(imageData, width, height) {
const Module = await BCNModule();
Module._init(Module._get_bc1_ideal_mode());
Module._init_bc7();
// Encode
const compressedSize = (width / 4) (height / 4) 16;
const srcPtr = Module._malloc(imageData.length);
const dstPtr = Module._malloc(compressedSize);
Module.HEAPU8.set(imageData, srcPtr);
Module._encode_bc7_image(dstPtr, srcPtr, width, height, 4);
const compressed = new Uint8Array(
Module.HEAPU8.buffer,
dstPtr,
compressedSize
);
const compressedCopy = new Uint8Array(compressed);
// Decode
const decodedPtr = Module._malloc(width height 4);
Module.HEAPU8.set(compressedCopy, dstPtr);
Module._decode_bc7_image(dstPtr, decodedPtr, width, height);
const decoded = new Uint8Array(
Module.HEAPU8.buffer,
decodedPtr,
width height 4
);
const decodedCopy = new Uint8Array(decoded);
// Cleanup
Module._free(srcPtr);
Module._free(dstPtr);
Module._free(decodedPtr);
return {
compressed: compressedCopy,
decoded: decodedCopy
};
}
`
Browser Usage
`html
`
DDS Export
The compressed data can be exported as DDS files:
`javascript
function createDDSFile(compressed, width, height, format) {
// DDS header is 128 bytes (or 148 for DX10 extended)
// For BC7, use DX10 extended header with DXGI_FORMAT_BC7_UNORM (98)
// See examples/index.html for complete DDS export implementation
}
`
Performance Tips
1. Batch Processing: Use _encode_*_image()` functions instead of per-block encoding