Ultra-lightweight PNG steganography with native Rust acceleration. Encode binary data into PNG images with zstd compression.
npm install roxify> Encode binary data into PNG images and decode them back. Fast, efficient, with optional encryption and native Rust acceleration.


- ā” Blazing Fast: Native Rust acceleration via N-API ā 1GB/s throughput on modern hardware
- š Optimized Compression: Multi-threaded Zstd compression (level 19) with parallel processing
- š Secure: AES-256-GCM encryption support with PBKDF2 key derivation
- šØ Multiple modes: Compact, chunk, pixel, and screenshot modes
- š¦ CLI & API: Use as command-line tool or JavaScript library
- š Lossless: Perfect roundtrip encoding/decoding
- š Full TSDoc: Complete TypeScript documentation
- š¦ Rust Powered: Optional native module for extreme performance (falls back to pure JS)
Highlights
- Practical benchmarks on large codebase datasets showing significant compression and high throughput while handling many small files efficiently.
Results
| Dataset | Files | Original | Compressed | Ratio | Time | Throughput | Notes |
| -------- | ------: | -------: | ---------: | --------: | -----: | ---------: | ------------------------------------------- |
| 4,000 MB | 731,340 | 3.93 GB | 111.42 MB | 2.8% | 26.9 s | 149.4 MB/s | gzip: 2.26 GB (57.5%); 7z: 1.87 GB (47.6%) |
| 1,000 MB | 141,522 | 1.03 GB | 205 MB | 19.4% | ~6.2 s | ā170 MB/s | shows benefits for many-small-file datasets |
- Compression: multithreaded Zstd (level 19) and Brotli (configurable).
- Setup: parallel I/O and multithreaded compression on modern SSD-backed systems.
- Measurements: wall-clock time; throughput = original size / time; comparisons against gzip and 7z with typical defaults.
- Reproducibility: full benchmark details, commands and raw data are available in docs/BENCHMARK_FINAL_REPORT.md.
These results demonstrate Roxify's strength for packaging large codebases and many-small-file archives where speed and a good compression/throughput trade-off matter.
- š CLI Documentation - Complete command-line usage guide
- š JavaScript SDK - Programmatic API reference with examples
- š Quick Start - Get started in 2 minutes
No installation needed! Use directly with npx:
``bash`
npx rox encode input.zip output.png
npx rox decode output.png original.zip
`bash`
npm install roxify
`bashEncode a file
npx rox encode document.pdf document.png
$3
####
encode - Encode file to PNG`bash
npx rox encode [output] [options]
`Options:
-
-p, --passphrase - Encrypt with passphrase (AES-256-GCM)
- -m, --mode - Encoding mode: compact|chunk|pixel|screenshot (default: screenshot)
- -q, --quality <0-11> - Brotli compression quality (default: 1)
- 0 = fastest, largest
- 11 = slowest, smallest
- -e, --encrypt - Encryption: auto|aes|xor|none (default: aes if passphrase)
- --no-compress - Disable compression
- -o, --output - Output file pathExamples:
`bash
Basic encoding
npx rox encode data.bin output.pngFast compression for large files
npx rox encode large-video.mp4 output.png -q 0High compression for small files
npx rox encode config.json output.png -q 11With encryption
npx rox encode secret.pdf secure.png -p "my secure password"Compact mode (smallest PNG)
npx rox encode data.bin tiny.png -m compactScreenshot mode (recommended, looks like a real image)
npx rox encode archive.tar.gz screenshot.png -m screenshot
`####
decode - Decode PNG to file`bash
npx rox decode [output] [options]
`Options:
-
-p, --passphrase - Decryption passphrase
- -o, --output - Output file path (auto-detected from metadata if not provided)Examples:
`bash
Basic decoding
npx rox decode encoded.png output.binAuto-detect filename from metadata
npx rox decode encoded.pngWith decryption
npx rox decode encrypted.png output.pdf -p "my secure password"
`JavaScript API
$3
`typescript
import { encodeBinaryToPng, decodePngToBinary } from 'roxify';
import { readFileSync, writeFileSync } from 'fs';const input = readFileSync('input.zip');
const png = await encodeBinaryToPng(input, {
mode: 'screenshot',
name: 'input.zip',
});
writeFileSync('output.png', png);
const encoded = readFileSync('output.png');
const result = await decodePngToBinary(encoded);
writeFileSync(result.meta?.name || 'output.bin', result.buf);
`$3
`typescript
const png = await encodeBinaryToPng(input, {
mode: 'screenshot',
passphrase: 'my-secret-password',
encrypt: 'aes',
name: 'secret.zip',
});const result = await decodePngToBinary(encoded, {
passphrase: 'my-secret-password',
});
`$3
`typescript
const png = await encodeBinaryToPng(largeBuffer, {
mode: 'screenshot',
brQuality: 0,
name: 'large-file.bin',
});const png = await encodeBinaryToPng(smallBuffer, {
mode: 'compact',
brQuality: 11,
name: 'config.json',
});
`$3
####
screenshot (Recommended)Encodes data as RGB pixel values, optimized for screenshot-like appearance. Best balance of size and compatibility.
`typescript
const png = await encodeBinaryToPng(data, { mode: 'screenshot' });
`####
compact (Smallest)Minimal 1x1 PNG with data in custom chunk. Fastest and smallest.
`typescript
const png = await encodeBinaryToPng(data, { mode: 'compact' });
`####
pixelEncodes data as RGB pixel values without screenshot optimization.
`typescript
const png = await encodeBinaryToPng(data, { mode: 'pixel' });
`####
chunkStandard PNG with data in custom rXDT chunk.
`typescript
const png = await encodeBinaryToPng(data, { mode: 'chunk' });
`API Reference
$3
Encodes binary data into a PNG image.
Parameters:
-
input: Buffer - The binary data to encode
- options?: EncodeOptions - Encoding optionsReturns:
Promise - The encoded PNGOptions:
`typescript
interface EncodeOptions {
compression?: 'br' | 'none'; passphrase?: string;
name?: string;
mode?: 'compact' | 'chunk' | 'pixel' | 'screenshot';
encrypt?: 'auto' | 'aes' | 'xor' | 'none';
output?: 'auto' | 'png' | 'rox';
includeName?: boolean;
brQuality?: number;
}
`$3
Decodes a PNG image back to binary data.
Parameters:
-
pngBuf: Buffer - The PNG image to decode
- options?: DecodeOptions - Decoding optionsReturns:
Promise - The decoded data and metadataOptions:
`typescript
interface DecodeOptions {
passphrase?: string;
}
`Result:
`typescript
interface DecodeResult {
buf: Buffer; meta?: {
name?: string;
};
}
`Performance Tips
$3
`bash
Use quality 0 for fastest encoding
npx rox encode large.bin output.png -q 0
``typescript
const png = await encodeBinaryToPng(largeFile, {
mode: 'screenshot',
brQuality: 0,
});
`$3
`bash
Use quality 11 for best compression
npx rox encode small.json output.png -q 11 -m compact
``typescript
const png = await encodeBinaryToPng(smallFile, {
mode: 'compact',
brQuality: 11,
});
`$3
File: 3.8 MB binary
- Quality 0: ~500-800ms, output ~1.2 MB
- Quality 1 (default): ~1-2s, output ~800 KB
- Quality 5: ~8-12s, output ~750 KB
- Quality 11: ~20-30s, output ~720 KB
Error Handling
`typescript
try {
const result = await decodePngToBinary(encoded, {
passphrase: 'wrong-password',
});
} catch (err) {
if (err.message.includes('Incorrect passphrase')) {
console.error('Wrong password!');
} else if (err.message.includes('Invalid ROX format')) {
console.error('Not a valid RoxCompressor PNG');
} else {
console.error('Decode failed:', err.message);
}
}
`Security
- AES-256-GCM: Authenticated encryption with 100,000 PBKDF2 iterations
- XOR cipher: Simple obfuscation (not cryptographically secure)
- No encryption: Data is compressed but not encrypted
ā ļø Warning: Use strong passphrases for sensitive data. The
xor encryption mode is not secure and should only be used for obfuscation.License
MIT Ā© RoxCompressor
Contributing
Contributions welcome! Please open an issue or PR on GitHub.
Links
- GitHub Repository
- npm Package
- Report Issues
CI / Multi-platform builds
This project runs continuous integration on Linux and Windows via GitHub Actions. Native modules are built on each platform and attached to the workflow (and release) as artifacts. On releases we also publish platform artifacts to GitHub Releases. For npm publishing, set the
NPM_TOKEN` secret in your repository settings to allow automated publishes on release.