zenpng 0.1.4

PNG encoding and decoding with zencodec trait integration
Documentation
use enough::Unstoppable;
use zenpixels::descriptor::{ChannelLayout, ChannelType};
use zenpixels_convert::PixelBufferConvertTypedExt;

/// Time each compression level on a single image.
fn main() {
    let path = std::env::args().nth(1).unwrap_or_else(|| {
        format!(
            "{}/clic2025-1024/0d154749c7771f58e89ad343653ec4e20d6f037da829f47f5598e5d0a4ab61f0.png",
            std::env::var("CODEC_CORPUS_DIR")
                .unwrap_or_else(|_| "/home/lilith/work/codec-corpus".to_string())
        )
    });

    let source = std::fs::read(&path).unwrap();
    let decoded = zenpng::decode(&source, &zenpng::PngDecodeConfig::none(), &Unstoppable).unwrap();

    let levels = [
        ("Fastest", zenpng::Compression::Fastest),
        ("Fast", zenpng::Compression::Fast),
        ("Balanced", zenpng::Compression::Balanced),
        ("Thorough", zenpng::Compression::Thorough),
        ("High", zenpng::Compression::High),
        ("Aggressive", zenpng::Compression::Aggressive),
        ("Intense", zenpng::Compression::Intense),
        ("Crush", zenpng::Compression::Crush),
    ];

    println!(
        "{:<10} {:>10} {:>8} {:>10}",
        "Level", "Size", "Time", "MiB/s"
    );
    println!("{}", "-".repeat(42));

    let desc = decoded.pixels.descriptor();
    let raw_mib = decoded.pixels.copy_to_contiguous_bytes().len() as f64 / 1_048_576.0;

    for (name, comp) in &levels {
        let config = zenpng::EncodeConfig::default()
            .with_compression(*comp)
            .with_source_gamma(decoded.info.source_gamma)
            .with_srgb_intent(decoded.info.srgb_intent)
            .with_chromaticities(decoded.info.chromaticities);

        let start = std::time::Instant::now();
        let encoded = match (desc.layout(), desc.channel_type()) {
            (ChannelLayout::Rgb, ChannelType::U8) => {
                let buf = decoded.pixels.to_rgb8();
                zenpng::encode_rgb8(buf.as_imgref(), None, &config, &Unstoppable, &Unstoppable)
            }
            (ChannelLayout::Rgba, ChannelType::U8) => {
                let buf = decoded.pixels.to_rgba8();
                zenpng::encode_rgba8(buf.as_imgref(), None, &config, &Unstoppable, &Unstoppable)
            }
            _ => panic!("unsupported format: {:?}", desc),
        };
        let elapsed = start.elapsed().as_secs_f64();

        match encoded {
            Ok(data) => {
                let speed = raw_mib / elapsed;
                println!(
                    "{:<10} {:>10} {:>7.2}s {:>8.1}",
                    name,
                    data.len(),
                    elapsed,
                    speed
                );
            }
            Err(e) => println!("{:<10} ERR: {e}", name),
        }
    }
}