cover all png variants

This commit is contained in:
Johann Woelper 2023-06-25 08:58:02 +02:00
parent d9e5101c0e
commit b9ace311ea
7 changed files with 148 additions and 54 deletions

72
Cargo.lock generated
View file

@ -275,6 +275,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded"
[[package]]
name = "bitreader"
version = "0.3.7"
@ -394,7 +400,7 @@ version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52e0d00eb1ea24371a97d2da6201c6747a633dc6dc1988ef503403b4c59504a8"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"log",
"nix 0.25.1",
"slotmap",
@ -473,7 +479,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
dependencies = [
"atty",
"bitflags",
"bitflags 1.3.2",
"clap_lex",
"indexmap",
"strsim",
@ -541,7 +547,7 @@ version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"block",
"cocoa-foundation",
"core-foundation",
@ -557,7 +563,7 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"block",
"core-foundation",
"core-graphics-types",
@ -642,7 +648,7 @@ version = "0.22.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"core-foundation",
"core-graphics-types",
"foreign-types 0.3.2",
@ -655,7 +661,7 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"core-foundation",
"foreign-types 0.3.2",
"libc",
@ -1062,7 +1068,7 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ae66425802d6a903e268ae1a08b8c38ba143520f227a205edf4e9c7e3e26d5"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"libc",
"winapi",
]
@ -1261,7 +1267,7 @@ version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74eadec9d0a5c28c54bb9882e54787275152a4e36ce206b45d7451384e5bf5fb"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"freetype-sys",
"libc",
]
@ -1576,7 +1582,7 @@ version = "0.30.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b0385782048be65f0a9dd046c469d6a758a53fe1aa63a8111dea394d2ffa2f"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"cfg_aliases",
"cgl",
"core-foundation",
@ -2572,7 +2578,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"jni-sys",
"ndk-sys",
"num_enum",
@ -2636,7 +2642,7 @@ version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"cfg-if 1.0.0",
"libc",
"memoffset 0.6.5",
@ -2649,7 +2655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
dependencies = [
"autocfg",
"bitflags",
"bitflags 1.3.2",
"cfg-if 1.0.0",
"libc",
"memoffset 0.6.5",
@ -3164,6 +3170,7 @@ dependencies = [
"webbrowser",
"windres",
"winres",
"zune-png",
]
[[package]]
@ -3445,7 +3452,7 @@ version = "0.17.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"crc32fast",
"fdeflate",
"flate2",
@ -3459,7 +3466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
dependencies = [
"autocfg",
"bitflags",
"bitflags 1.3.2",
"cfg-if 1.0.0",
"concurrent-queue",
"libc",
@ -3716,7 +3723,7 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
"bitflags 1.3.2",
]
[[package]]
@ -3725,7 +3732,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
"bitflags 1.3.2",
]
[[package]]
@ -3927,7 +3934,7 @@ version = "0.37.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
@ -3978,7 +3985,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "162bdf42e261bee271b3957691018634488084ef577dddeb6420a9684cab2a6a"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"bytemuck",
"smallvec",
"ttf-parser 0.18.1",
@ -4246,7 +4253,7 @@ version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f307c47d32d2715eb2e0ece5589057820e0e5e70d07c247d1063e844e107f454"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"calloop",
"dlib",
"lazy_static",
@ -5017,7 +5024,7 @@ version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"downcast-rs",
"libc",
"nix 0.24.3",
@ -5056,7 +5063,7 @@ version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"wayland-client",
"wayland-commons",
"wayland-scanner",
@ -5398,7 +5405,7 @@ version = "0.27.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb796d6fbd86b2fd896c9471e6f04d39d750076ebe5680a3958f00f5ab97657c"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"cocoa",
"core-foundation",
"core-graphics",
@ -5547,6 +5554,15 @@ dependencies = [
"rgb",
]
[[package]]
name = "zune-core"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ca36c2e02af0d8d7ee977542bfe33ed1c516be73d3c1faa4420af46e96ceee"
dependencies = [
"bitflags 2.3.2",
]
[[package]]
name = "zune-inflate"
version = "0.2.54"
@ -5555,3 +5571,15 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
dependencies = [
"simd-adler32",
]
[[package]]
name = "zune-png"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee5abc36f78f32bf5ffb5f070a69cb7beffa7cb393817d3a30f9fe7c1ea57655"
dependencies = [
"bytemuck",
"log",
"zune-core",
"zune-inflate",
]

View file

@ -59,7 +59,7 @@ usvg = "0.33.0"
webbrowser = "0.8"
tiff = "0.9"
jxl-oxide = "0.3.0"
zune-png = "0.2"
[features]
avif_native = ["avif-decode"]

View file

@ -1 +1 @@
209ms
213ms

View file

@ -1 +1 @@
247ms
389ms

View file

@ -40,10 +40,13 @@ fn net() {
#[test]
fn bench_load_large() {
#[cfg(debug_assertions)]
panic!("This test needs release mode to pass.");
std::env::set_var("RUST_LOG", "info");
let _ = env_logger::try_init();
let iters = 5;
info!("Benching this with {iters} iterations...");
info!("Benching JPEG with {iters} iterations...");
let mut total = 0;
for _i in 0..iters {
@ -59,10 +62,9 @@ fn bench_load_large() {
}
info!("{} ms mean", total / iters);
let mut f = File::create("benches/load_large_jpg.bench").unwrap();
f.write_fmt(format_args!("{}ms", total / iters))
.unwrap();
f.write_fmt(format_args!("{}ms", total / iters)).unwrap();
info!("Benching this with {iters} iterations...");
info!("Benching PNG with {iters} iterations...");
let mut total = 0;
for _i in 0..iters {
@ -75,8 +77,7 @@ fn bench_load_large() {
}
info!("{} ms mean", total / iters);
let mut f = File::create("benches/load_large_png.bench").unwrap();
f.write_fmt(format_args!("{}ms", total / iters))
.unwrap();
f.write_fmt(format_args!("{}ms", total / iters)).unwrap();
}
#[test]

View file

@ -5,7 +5,7 @@ use jxl_oxide::{JxlImage, PixelFormat, RenderResult};
// use image::codecs::gif::GifDecoder;
use exr::prelude as exrs;
use exr::prelude::*;
use image::{DynamicImage, EncodableLayout, GrayAlphaImage, RgbImage, RgbaImage};
use image::{DynamicImage, EncodableLayout, GrayAlphaImage, GrayImage, RgbImage, RgbaImage};
use log::{debug, error, info};
use nalgebra::{clamp, Vector2};
use notan::graphics::Texture;
@ -23,6 +23,8 @@ use std::thread;
use std::time::Duration;
use tiff::decoder::Limits;
use usvg::{TreeParsing, TreeTextToPath};
use zune_png::zune_core::result::DecodingResult;
use zune_png::PngDecoder;
use anyhow::{anyhow, bail, Context, Result};
use image::Rgba;
@ -30,7 +32,6 @@ use image::{self};
use libwebp_sys::{WebPDecodeRGBA, WebPGetInfo};
use psd::Psd;
use rgb::*;
use std::io::Read;
use std::sync::mpsc::{self, channel};
use std::sync::mpsc::{Receiver, Sender};
use strum::Display;
@ -76,8 +77,6 @@ impl ExtendedImageInfo {
let exifreader = exif::Reader::new();
let exif = exifreader.read_from_container(&mut bufreader)?;
for f in exif.fields() {
// let s = format!("{} {} {}",
// f.tag, f.ifd_num, f.display_value().with_unit(&exif));
self.exif.insert(
f.tag.to_string(),
f.display_value().with_unit(&exif).to_string(),
@ -92,7 +91,7 @@ impl ExtendedImageInfo {
let mut green_histogram: HashMap<u8, usize> = Default::default();
let mut blue_histogram: HashMap<u8, usize> = Default::default();
let mut num_pixels = 0;
let num_pixels = img.width() as usize * img.height() as usize;
let mut num_transparent_pixels = 0;
for p in img.pixels() {
if is_pixel_fully_transparent(p) {
@ -106,26 +105,25 @@ impl ExtendedImageInfo {
let mut p = *p;
p.0[3] = 255;
colors.insert(p);
num_pixels += 1;
}
let mut green_histogram: Vec<(i32, i32)> = green_histogram
.par_iter()
.map(|(k, v)| (*k as i32, *v as i32))
.collect();
green_histogram.sort_by(|a, b| a.0.cmp(&b.0));
green_histogram.par_sort_by(|a, b| a.0.cmp(&b.0));
let mut red_histogram: Vec<(i32, i32)> = red_histogram
.par_iter()
.map(|(k, v)| (*k as i32, *v as i32))
.collect();
red_histogram.sort_by(|a, b| a.0.cmp(&b.0));
red_histogram.par_sort_by(|a, b| a.0.cmp(&b.0));
let mut blue_histogram: Vec<(i32, i32)> = blue_histogram
.par_iter()
.map(|(k, v)| (*k as i32, *v as i32))
.collect();
blue_histogram.sort_by(|a, b| a.0.cmp(&b.0));
blue_histogram.par_sort_by(|a, b| a.0.cmp(&b.0));
Self {
num_pixels,
@ -912,10 +910,7 @@ pub fn open_image(img_location: &Path) -> Result<Receiver<Frame>> {
return Ok(receiver);
}
"psd" => {
let mut file = File::open(img_location)?;
let mut contents = vec![];
file.read_to_end(&mut contents)?;
let contents = std::fs::read(img_location)?;
let psd = Psd::from_bytes(&contents).map_err(|e| anyhow!("{:?}", e))?;
let buf = image::ImageBuffer::from_raw(psd.width(), psd.height(), psd.rgba())
.context("Can't create imagebuffer from PSD")?;
@ -924,21 +919,91 @@ pub fn open_image(img_location: &Path) -> Result<Receiver<Frame>> {
return Ok(receiver);
}
"webp" => {
let mut file = File::open(img_location)?;
let mut contents = vec![];
file.read_to_end(&mut contents)?;
let contents = std::fs::read(img_location)?;
let buf = decode_webp(&contents).context("Can't decode webp")?;
_ = sender.send(Frame::new_still(buf));
return Ok(receiver);
}
"png" => {
let file = File::open(img_location)?;
let bufread = BufReader::new(file);
let mut reader = image::io::Reader::new(bufread).with_guessed_format()?;
reader.no_limits();
_ = sender.send(Frame::new_still(reader.decode()?.into_rgba8()));
return Ok(receiver);
// col.add_still(reader.decode()?.into_rgba8());
let contents = std::fs::read(&img_location)?;
let mut decoder = PngDecoder::new(&contents);
match decoder.decode().map_err(|e| anyhow!("{:?}", e))? {
// 16 bpp data
DecodingResult::U16(imgdata) => {
//convert to 8bpp
let imgdata_8bpp = imgdata
.par_iter()
.map(|x| *x as f32 / u16::MAX as f32)
.map(|p| p.powf(2.2))
.map(|p| tonemap_f32(p))
// .map(|x| x as u8)
.collect::<Vec<_>>();
let (width, height) = decoder
.get_dimensions()
.context("Can't get png dimensions")?;
let colorspace = decoder.get_colorspace().context("Can't get colorspace")?;
if colorspace.is_grayscale() {
let buf: GrayImage =
image::ImageBuffer::from_raw(width as u32, height as u32, imgdata_8bpp)
.context("Can't interpret image as grayscale")?;
let image_result = DynamicImage::ImageLuma8(buf);
_ = sender.send(Frame::new_still(image_result.to_rgba8()));
return Ok(receiver);
}
if colorspace.has_alpha() {
let float_image =
RgbaImage::from_raw(width as u32, height as u32, imgdata_8bpp)
.context("Can't decode rgba buffer")?;
_ = sender.send(Frame::new_still(
DynamicImage::ImageRgba8(float_image).to_rgba8(),
));
return Ok(receiver);
} else {
let float_image =
RgbImage::from_raw(width as u32, height as u32, imgdata_8bpp)
.context("Can't decode rgba buffer")?;
_ = sender.send(Frame::new_still(
DynamicImage::ImageRgb8(float_image).to_rgba8(),
));
return Ok(receiver);
}
}
// 8bpp
DecodingResult::U8(value) => {
let (width, height) = decoder
.get_dimensions()
.context("Can't get png dimensions")?;
let colorspace = decoder.get_colorspace().context("Can't get colorspace")?;
if colorspace.is_grayscale() {
let buf: GrayImage =
image::ImageBuffer::from_raw(width as u32, height as u32, value)
.context("Can't interpret image as grayscale")?;
let image_result = DynamicImage::ImageLuma8(buf);
_ = sender.send(Frame::new_still(image_result.to_rgba8()));
return Ok(receiver);
}
if colorspace.has_alpha() {
let buf: RgbaImage =
image::ImageBuffer::from_raw(width as u32, height as u32, value)
.context("Can't interpret image as rgba")?;
_ = sender.send(Frame::new_still(buf));
return Ok(receiver);
} else {
let buf: RgbImage =
image::ImageBuffer::from_raw(width as u32, height as u32, value)
.context("Can't interpret image as rgb")?;
let image_result = DynamicImage::ImageRgb8(buf);
_ = sender.send(Frame::new_still(image_result.to_rgba8()));
return Ok(receiver);
}
}
_ => {}
}
}
"gif" => {
let file = File::open(img_location)?;

BIN
tests/gray_8bpp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB