compress static method
Compresses raw image bytes using quality-based quantization and stride downsampling.
bytes — Raw image byte buffer (grayscale or RGBA pixel data).
quality — Quality factor from 0.0 (max compression) to 1.0 (no compression).
preserveAlpha — If true, preserves every 4th byte (alpha channel) unmodified.
Implementation
static CompressionResult compress(
Uint8List bytes, {
double quality = 0.85,
bool preserveAlpha = false,
}) {
final stopwatch = Stopwatch()..start();
final clampedQuality = quality.clamp(0.05, 1.0);
if (bytes.isEmpty || clampedQuality >= 0.99) {
stopwatch.stop();
return CompressionResult(
compressedBytes: bytes,
originalSize: bytes.length,
compressedSize: bytes.length,
compressionRatio: 1.0,
qualityUsed: clampedQuality,
elapsed: stopwatch.elapsed,
);
}
// Step 1: Quantization — reduce color depth based on quality
final quantizationBits = _qualityToQuantizationBits(clampedQuality);
final quantized = _quantizeBytes(bytes, quantizationBits, preserveAlpha);
// Step 2: Stride downsampling — skip pixels based on quality
final step = _qualityToStride(clampedQuality);
final Uint8List compressed;
if (step <= 1) {
compressed = quantized;
} else {
final result = <int>[];
for (int i = 0; i < quantized.length; i += step) {
result.add(quantized[i]);
}
compressed = Uint8List.fromList(result);
}
// Step 3: Run-length encoding for repeated byte sequences
final rleCompressed = _applyRle(compressed, clampedQuality);
stopwatch.stop();
return CompressionResult(
compressedBytes: rleCompressed,
originalSize: bytes.length,
compressedSize: rleCompressed.length,
compressionRatio:
bytes.isNotEmpty ? rleCompressed.length / bytes.length : 1.0,
qualityUsed: clampedQuality,
elapsed: stopwatch.elapsed,
);
}