diff --git a/Cargo.lock b/Cargo.lock index 69e6cb599c69..babfdf15a89e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1737,9 +1737,9 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" @@ -2568,6 +2568,8 @@ dependencies = [ "byteorder", "num-traits", "png", + "zune-core", + "zune-jpeg", ] [[package]] @@ -2714,15 +2716,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -2835,9 +2828,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "libloading" @@ -3937,7 +3930,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -3958,7 +3951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.48", @@ -4327,7 +4320,7 @@ version = "0.17.0-alpha.3" dependencies = [ "ahash", "anyhow", - "image 0.24.6", + "image 0.25.1", "once_cell", "parking_lot", "rayon", @@ -4401,7 +4394,7 @@ dependencies = [ "egui", "egui_extras", "egui_plot", - "image 0.24.6", + "image 0.25.1", "itertools 0.13.0", "re_data_store", "re_entity_db", @@ -4703,7 +4696,7 @@ dependencies = [ "bytemuck", "console_error_panic_hook", "glam", - "image 0.24.6", + "image 0.25.1", "itertools 0.13.0", "macaw", "pollster", @@ -5043,7 +5036,7 @@ dependencies = [ "emath", "glam", "half 2.3.1", - "image 0.24.6", + "image 0.25.1", "infer", "itertools 0.13.0", "linked-hash-map", @@ -5065,8 +5058,6 @@ dependencies = [ "smallvec", "thiserror", "uuid", - "zune-core", - "zune-jpeg", ] [[package]] @@ -5164,7 +5155,7 @@ dependencies = [ "egui-wgpu", "egui_plot", "ehttp", - "image 0.24.6", + "image 0.25.1", "itertools 0.13.0", "js-sys", "poll-promise", @@ -5271,7 +5262,7 @@ dependencies = [ "egui", "egui_tiles", "glam", - "image 0.24.6", + "image 0.25.1", "itertools 0.13.0", "nohash-hasher", "rayon", @@ -5633,7 +5624,7 @@ version = "0.17.0-alpha.3" dependencies = [ "anyhow", "clap", - "image 0.24.6", + "image 0.25.1", "re_log", "rerun", ] @@ -5655,7 +5646,7 @@ dependencies = [ "anyhow", "clap", "half 2.3.1", - "image 0.24.6", + "image 0.25.1", "ndarray", "re_log", "rerun", @@ -5717,7 +5708,7 @@ version = "0.17.0-alpha.3" dependencies = [ "anyhow", "clap", - "image 0.24.6", + "image 0.25.1", "re_log", "rerun", ] @@ -6409,7 +6400,7 @@ version = "0.17.0-alpha.3" dependencies = [ "anyhow", "clap", - "image 0.24.6", + "image 0.25.1", "re_log", "rerun", ] diff --git a/Cargo.toml b/Cargo.toml index ca6fbfb8af89..758afa18c777 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -143,7 +143,7 @@ glam = "0.22" # glam update blocked by macaw glob = "0.3" gltf = "1.1" half = "2.3.1" -image = { version = "0.24", default-features = false } +image = { version = "0.25", default-features = false } indent = "0.1" indexmap = "2.1" # Version chosen to align with other dependencies indicatif = "0.17.7" # Progress bar @@ -258,8 +258,6 @@ wgpu = { version = "0.19.4", default-features = false, features = [ wgpu-core = "0.19.4" xshell = "0.2" zip = { version = "0.6", default-features = false } -zune-core = "0.4" -zune-jpeg = "0.4" [profile.dev] diff --git a/crates/re_log/src/lib.rs b/crates/re_log/src/lib.rs index 3a8fc97e624e..71cb27234b4c 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 6dc2a6b6ec00..efba7c322c42 100644 --- a/crates/re_types/Cargo.toml +++ b/crates/re_types/Cargo.toml @@ -37,7 +37,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,11 +81,11 @@ 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 } 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 e43765ad5bb4..4d8eacd44cab 100644 --- a/crates/re_types/src/datatypes/tensor_data_ext.rs +++ b/crates/re_types/src/datatypes/tensor_data_ext.rs @@ -647,19 +647,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() - .expect("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 c80aaf4a9f55..31dcc37e6615 100644 --- a/crates/re_types/src/tensor_data.rs +++ b/crates/re_types/src/tensor_data.rs @@ -47,9 +47,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")] @@ -562,62 +559,31 @@ impl DecodedTensor { /// Decode the contents of a JPEG file, with the given expected size. /// /// Returns an error if the size does not match. - fn decode_jpeg_bytes( + pub fn decode_jpeg_bytes( 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, options); - let pixels = decoder.decode()?; - let (w, h) = decoder - .dimensions() - .expect("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 = Self(tensor); - - Ok(decoded_tensor) + Self::from_image(img) } } diff --git a/crates/re_viewer/src/web.rs b/crates/re_viewer/src/web.rs index 2ab5755c6929..7b7a8a9eaf14 100644 --- a/crates/re_viewer/src/web.rs +++ b/crates/re_viewer/src/web.rs @@ -32,7 +32,7 @@ pub struct WebHandle { #[wasm_bindgen] impl WebHandle { - #[allow(clippy::new_without_default)] + #[allow(clippy::new_without_default, clippy::use_self)] // Can't use `Self` here because of `#[wasm_bindgen]`. #[wasm_bindgen(constructor)] pub fn new(app_options: JsValue) -> Result { re_log::setup_logging(); @@ -281,11 +281,10 @@ enum PanelState { impl From for re_types::blueprint::components::PanelState { fn from(value: PanelState) -> Self { - use re_types::blueprint::components::PanelState as Out; match value { - PanelState::Hidden => Out::Hidden, - PanelState::Collapsed => Out::Collapsed, - PanelState::Expanded => Out::Expanded, + PanelState::Hidden => Self::Hidden, + PanelState::Collapsed => Self::Collapsed, + PanelState::Expanded => Self::Expanded, } } }