From 0797fdd2e3e248a69ae7bc4cf47b1622bb4611e3 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 26 Feb 2024 11:08:55 +0100 Subject: [PATCH] Replace `zune-jpeg` with the default `image` crate --- Cargo.lock | 17 ------ Cargo.toml | 2 - Cranky.toml | 1 + crates/re_log/src/lib.rs | 2 - crates/re_types/Cargo.toml | 8 +-- .../re_types/src/datatypes/tensor_data_ext.rs | 12 ++-- crates/re_types/src/tensor_data.rs | 56 ++++--------------- 7 files changed, 23 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c09f797c89fd9..c8a3a5366be68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4936,8 +4936,6 @@ dependencies = [ "smallvec", "thiserror", "uuid", - "zune-core", - "zune-jpeg", ] [[package]] @@ -7730,21 +7728,6 @@ dependencies = [ "flate2", ] -[[package]] -name = "zune-core" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae122f32a8e2a653acb430c9af5e79e7056c519fa8bac46e51e670868e5c0f2" - -[[package]] -name = "zune-jpeg" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" -dependencies = [ - "zune-core", -] - [[package]] name = "zvariant" version = "3.15.0" diff --git a/Cargo.toml b/Cargo.toml index 7690e330ca631..e1404ece3eb41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -255,8 +255,6 @@ wgpu = { version = "0.19.1", default-features = false, features = [ wgpu-core = "0.19.0" xshell = "0.2" zip = { version = "0.6", default-features = false } -zune-core = "0.4" -zune-jpeg = "0.4" [profile.dev] diff --git a/Cranky.toml b/Cranky.toml index a9438d5b41c4e..aa4ca15c2ba9a 100644 --- a/Cranky.toml +++ b/Cranky.toml @@ -155,6 +155,7 @@ allow = [ "clippy::let_underscore_untyped", "clippy::missing_assert_message", "clippy::missing_errors_doc", + "clippy::use_self", "trivial_casts", "unused_qualifications", diff --git a/crates/re_log/src/lib.rs b/crates/re_log/src/lib.rs index 05dd6022f006c..5e5a6a790d6a6 100644 --- a/crates/re_log/src/lib.rs +++ b/crates/re_log/src/lib.rs @@ -51,8 +51,6 @@ pub mod external { /// Never log anything less serious than a `ERROR` from these crates. const CRATES_AT_ERROR_LEVEL: &[&str] = &[ - // Waiting for https://github.com/etemesi254/zune-image/issues/131 to be released - "zune_jpeg", // silence rustls in release mode: https://github.com/rerun-io/rerun/issues/3104 #[cfg(not(debug_assertions))] "rustls", diff --git a/crates/re_types/Cargo.toml b/crates/re_types/Cargo.toml index 6d32e54cfbc85..1a1deb5704d65 100644 --- a/crates/re_types/Cargo.toml +++ b/crates/re_types/Cargo.toml @@ -39,7 +39,7 @@ egui_plot = ["dep:egui_plot"] glam = ["dep:glam"] ## Integration with the [`image`](https://crates.io/crates/image/) crate, plus JPEG support. -image = ["dep:ecolor", "dep:image", "dep:zune-core", "dep:zune-jpeg"] +image = ["dep:ecolor", "dep:image"] ## Enable (de)serialization using serde. serde = ["dep:serde"] @@ -81,12 +81,12 @@ uuid = { workspace = true, features = ["serde", "v4", "js"] } ecolor = { workspace = true, optional = true } egui_plot = { workspace = true, optional = true } glam = { workspace = true, optional = true } -image = { workspace = true, optional = true, default-features = false } +image = { workspace = true, optional = true, default-features = false, features = [ + "jpeg", +] } mint = { workspace = true, optional = true } rand = { workspace = true, optional = true, features = ["std", "std_rng"] } serde = { workspace = true, optional = true, features = ["derive", "rc"] } -zune-core = { workspace = true, optional = true } -zune-jpeg = { workspace = true, optional = true } [dev-dependencies] diff --git a/crates/re_types/src/datatypes/tensor_data_ext.rs b/crates/re_types/src/datatypes/tensor_data_ext.rs index 479838ac1075c..25ae101053a5e 100644 --- a/crates/re_types/src/datatypes/tensor_data_ext.rs +++ b/crates/re_types/src/datatypes/tensor_data_ext.rs @@ -625,17 +625,17 @@ impl TensorData { pub fn from_jpeg_bytes(jpeg_bytes: Vec) -> Result { re_tracing::profile_function!(); - use zune_jpeg::JpegDecoder; - - let mut decoder = JpegDecoder::new(&jpeg_bytes); - decoder.decode_headers()?; - let (w, h) = decoder.dimensions().unwrap(); // Can't fail after a successful decode_headers + // Parse JPEG header: + use image::ImageDecoder as _; + let jpeg = image::codecs::jpeg::JpegDecoder::new(std::io::Cursor::new(&jpeg_bytes))?; + let (w, h) = jpeg.dimensions(); + let depth = jpeg.color_type().channel_count(); Ok(Self { shape: vec![ TensorDimension::height(h as _), TensorDimension::width(w as _), - TensorDimension::depth(3), + TensorDimension::depth(depth as _), ], buffer: TensorBuffer::Jpeg(jpeg_bytes.into()), }) diff --git a/crates/re_types/src/tensor_data.rs b/crates/re_types/src/tensor_data.rs index 8d7ea54d7ad1e..6c93bbca92edc 100644 --- a/crates/re_types/src/tensor_data.rs +++ b/crates/re_types/src/tensor_data.rs @@ -44,9 +44,6 @@ pub enum TensorImageLoadError { #[error("The encoded tensor shape did not match its metadata {expected:?} != {found:?}")] InvalidMetaData { expected: Vec, found: Vec }, - - #[error(transparent)] - JpegDecode(#[from] zune_jpeg::errors::DecodeErrors), } #[cfg(feature = "image")] @@ -549,59 +546,30 @@ impl DecodedTensor { } pub fn decode_jpeg_bytes( - jpeg_bytes: &::re_types_core::ArrowBuffer, + jpeg_bytes: &[u8], [expected_height, expected_width, expected_channels]: [u64; 3], ) -> Result { re_tracing::profile_function!(format!("{expected_width}x{expected_height}")); - use zune_core::colorspace::ColorSpace; - use zune_core::options::DecoderOptions; - use zune_jpeg::JpegDecoder; - - let mut options = DecoderOptions::default(); - - let depth = if expected_channels == 1 { - options = options.jpeg_set_out_colorspace(ColorSpace::Luma); - 1 - } else { - // We decode to RGBA directly so we don't need to pad to four bytes later when uploading to GPU. - options = options.jpeg_set_out_colorspace(ColorSpace::RGBA); - 4 + use image::io::Reader as ImageReader; + let mut reader = ImageReader::new(std::io::Cursor::new(jpeg_bytes)); + reader.set_format(image::ImageFormat::Jpeg); + let img = { + re_tracing::profile_scope!("decode_jpeg"); + reader.decode()? }; - let mut decoder = JpegDecoder::new_with_options(jpeg_bytes.as_slice(), options); - let pixels = decoder.decode()?; - let (w, h) = decoder.dimensions().unwrap(); // Can't fail after a successful decode - - let (w, h) = (w as u64, h as u64); + let (w, h) = (img.width() as u64, img.height() as u64); + let channels = img.color().channel_count() as u64; - if w != expected_width || h != expected_height { + if (w, h, channels) != (expected_width, expected_height, expected_channels) { return Err(TensorImageLoadError::InvalidMetaData { expected: [expected_height, expected_width, expected_channels].into(), - found: [h, w, depth].into(), + found: [h, w, channels].into(), }); } - if pixels.len() as u64 != w * h * depth { - return Err(zune_jpeg::errors::DecodeErrors::Format(format!( - "Bug in zune-jpeg: Expected {w}x{h}x{depth}={} bytes, got {}", - w * h * depth, - pixels.len() - )) - .into()); - } - - let tensor = TensorData { - shape: vec![ - TensorDimension::height(h), - TensorDimension::width(w), - TensorDimension::depth(depth), - ], - buffer: TensorBuffer::U8(pixels.into()), - }; - let decoded_tensor = DecodedTensor(tensor); - - Ok(decoded_tensor) + Self::from_image(img) } }