From 4891fa07a51f8da70773cbdbc64ff3aa7ebecf58 Mon Sep 17 00:00:00 2001 From: pommicket Date: Mon, 8 Sep 2025 15:02:43 -0400 Subject: Update to latest version of png crate --- Cargo.toml | 2 +- README.md | 10 +++++----- benches/bench.rs | 9 +++++---- check-size.sh | 3 +++ src/test.rs | 9 ++++++--- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d2e2bd5..f502239 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ edition = "2024" [dev-dependencies] criterion = { version = "0.5.1", features = ["html_reports"] } -png = "0.17.10" +png = "0.18.0" png-decoder = "0.1.1" [features] diff --git a/README.md b/README.md index 65c28ea..4e0d031 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [crates.io page](https://crates.io/crates/minipng) · [repository](https://github.com/pommicket/minipng) Tiny Rust PNG decoder with no dependencies (not even `std` or `alloc`) -and tiny code size (e.g. >8 times smaller `.wasm.gz` size compared to the `png` crate — see `check-size.sh`). +and tiny code size (e.g. ~9 times smaller `.wasm.gz` size compared to the `png` crate). ## Goals @@ -30,7 +30,7 @@ Basic usage: ```rust let mut buffer = vec![0; 1 << 20]; // hope this is big enough! -let png = &include_bytes!("../examples/image.png")[..]; +let png = &include_bytes!("examples/image.png")[..]; let image = minipng::decode_png(png, &mut buffer).expect("bad PNG"); println!("{}×{} image", image.width(), image.height()); let pixels = image.pixels(); @@ -41,7 +41,7 @@ println!("top-left pixel is #{:02x}{:02x}{:02x}", pixels[0], pixels[1], pixels[2 More complex example that allocates the right number of bytes and handles all color formats: ```rust -let png = &include_bytes!("../examples/image.png")[..]; +let png = &include_bytes!("examples/image.png")[..]; let header = minipng::decode_png_header(png).expect("bad PNG"); let mut buffer = vec![0; header.required_bytes_rgba8bpc()]; let mut image = minipng::decode_png(png, &mut buffer).expect("bad PNG"); @@ -72,8 +72,8 @@ tests and no way of enabling `--nocapture` by default *grumble grumble*). ## Performance -Benchmarks (see `cargo bench`) show that `minipng` is about 50% slower than the `png` crate -for large images, but faster than `png` for small images. +Benchmarks (see `cargo bench`) show that `minipng` is about 2× slower than the `png` crate +for large images, but about the same for small images. ## License diff --git a/benches/bench.rs b/benches/bench.rs index 9414278..35beb05 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,5 +1,6 @@ use criterion::{Criterion, criterion_group, criterion_main}; use std::hint::black_box; +use std::io::Cursor; fn run_benches(c: &mut Criterion) { let large_image = black_box(include_bytes!("large.png")); @@ -21,9 +22,9 @@ fn run_benches(c: &mut Criterion) { group.bench_function("png", |b| { b.iter(|| { let png = &large_image[..]; - let decoder = png::Decoder::new(png); + let decoder = png::Decoder::new(Cursor::new(png)); let mut reader = decoder.read_info().unwrap(); - let mut png_buf = vec![0; reader.output_buffer_size()]; + let mut png_buf = vec![0; reader.output_buffer_size().unwrap()]; reader.next_frame(&mut png_buf).unwrap(); std::hint::black_box(png_buf); }) @@ -44,9 +45,9 @@ fn run_benches(c: &mut Criterion) { group.bench_function("png", |b| { b.iter(|| { let png = &small_image[..]; - let decoder = png::Decoder::new(png); + let decoder = png::Decoder::new(Cursor::new(png)); let mut reader = decoder.read_info().unwrap(); - let mut png_buf = vec![0; reader.output_buffer_size()]; + let mut png_buf = vec![0; reader.output_buffer_size().unwrap()]; reader.next_frame(&mut png_buf).unwrap(); std::hint::black_box(png_buf); }) diff --git a/check-size.sh b/check-size.sh index dca7d0b..ea4ecde 100755 --- a/check-size.sh +++ b/check-size.sh @@ -5,3 +5,6 @@ cd examples/wasm-minipng && cargo b --release && cd ../.. && wasm-opt --strip-de cd examples/wasm-png && cargo b --release && cd ../.. && wasm-opt --strip-debug -Oz examples/wasm-png/target/wasm32-unknown-unknown/release/wasm_png.wasm -o target/png.wasm && gzip -k -f target/png.wasm || exit 1 wc -c target/png.wasm.gz target/minipng.wasm.gz | head -n2 +pngsz=$(wc -c target/png.wasm.gz | cut -d' ' -f1) +minipngsz=$(wc -c target/minipng.wasm.gz | cut -d' ' -f1) +echo 'Ratio: '$(python3 -c "print($pngsz / $minipngsz)") diff --git a/src/test.rs b/src/test.rs index 2f4a1be..87bfc2a 100644 --- a/src/test.rs +++ b/src/test.rs @@ -22,10 +22,12 @@ impl core::fmt::Display for Flaw { const LARGE_BUF: Mutex> = Mutex::new(vec![]); fn test_bytes(bytes: &[u8]) -> Result<(), Flaw> { - let decoder = png::Decoder::new(bytes); + let decoder = png::Decoder::new(std::io::Cursor::new(bytes)); let mut is_valid = true; - if let Ok(mut reader) = decoder.read_info() { - let mut png_buf = vec![0; reader.output_buffer_size()]; + if let Ok(mut reader) = decoder.read_info() + && let Some(output_buffer_size) = reader.output_buffer_size() + { + let mut png_buf = vec![0; output_buffer_size]; if let Ok(png_header) = reader.next_frame(&mut png_buf) { let png_bytes = &png_buf[..png_header.buffer_size()]; @@ -41,6 +43,7 @@ fn test_bytes(bytes: &[u8]) -> Result<(), Flaw> { if png_bytes != mini_bytes { return Err(Flaw::DecodedMismatch); } + // test convert_to_rgba8bpc vs. png_decoder crate let (_, mut data) = png_decoder::decode(bytes).unwrap(); if matches!(image.color_type(), ColorType::Gray | ColorType::Rgb) { // pretend there's no tRNS chunk. -- cgit v1.2.3