diff --git a/Cargo.lock b/Cargo.lock index bfb6ff08..81bd9c68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -561,6 +561,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.9.0" @@ -2247,6 +2253,18 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "image" +version = "0.25.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" +dependencies = [ + "bytemuck", + "byteorder-lite", + "num-traits", + "png", +] + [[package]] name = "indexmap" version = "2.6.0" @@ -2308,7 +2326,7 @@ version = "0.6.0" dependencies = [ "anyhow", "async-trait", - "bmp", + "image", "ironrdp-acceptor", "ironrdp-blocking", "ironrdp-cliprdr", diff --git a/crates/ironrdp/Cargo.toml b/crates/ironrdp/Cargo.toml index f1dabc6e..f9d79df9 100644 --- a/crates/ironrdp/Cargo.toml +++ b/crates/ironrdp/Cargo.toml @@ -53,7 +53,7 @@ ironrdp-blocking.workspace = true ironrdp-cliprdr-native.workspace = true anyhow = "1" async-trait = "0.1" -bmp = "0.5" +image = { version = "0.25.5", default-features = false, features = ["png"] } pico-args = "0.5" x509-cert = { version = "0.2", default-features = false, features = ["std"] } sspi = { workspace = true, features = ["network_client"] } diff --git a/crates/ironrdp/examples/screenshot.rs b/crates/ironrdp/examples/screenshot.rs index 5b5ef5b6..c3683509 100644 --- a/crates/ironrdp/examples/screenshot.rs +++ b/crates/ironrdp/examples/screenshot.rs @@ -6,12 +6,12 @@ //! //! In this basic client implementation, the client establishes a connection //! with the destination server, decodes incoming graphics updates, and saves the -//! resulting output as a BMP image file on the disk. +//! resulting output as a PNG image file on the disk. //! //! # Usage example //! //! ```shell -//! cargo run --example=screenshot -- --host -u -p -o out.bmp +//! cargo run --example=screenshot -- --host -u -p -o out.png //! ``` #![allow(unused_crate_dependencies)] // false positives because there is both a library and a binary @@ -99,7 +99,7 @@ fn parse_args() -> anyhow::Result { let password = args.value_from_str(["-p", "--password"])?; let output = args .opt_value_from_str(["-o", "--output"])? - .unwrap_or_else(|| PathBuf::from("out.bmp")); + .unwrap_or_else(|| PathBuf::from("out.png")); let domain = args.opt_value_from_str(["-d", "--domain"])?; Action::Run { @@ -156,27 +156,11 @@ fn run( active_stage(connection_result, framed, &mut image).context("active stage")?; - let mut bmp = bmp::Image::new(u32::from(image.width()), u32::from(image.height())); + let img: image::ImageBuffer, _> = + image::ImageBuffer::from_raw(u32::from(image.width()), u32::from(image.height()), image.data()) + .context("invalid image")?; - image - .data() - .chunks_exact(usize::from(image.width()).checked_mul(4).expect("never overflow")) - .enumerate() - .for_each(|(y, row)| { - row.chunks_exact(4).enumerate().for_each(|(x, pixel)| { - let r = pixel[0]; - let g = pixel[1]; - let b = pixel[2]; - let _a = pixel[3]; - bmp.set_pixel( - u32::try_from(x).unwrap(), - u32::try_from(y).unwrap(), - bmp::Pixel::new(r, g, b), - ); - }) - }); - - bmp.save(output).context("save BMP image to disk")?; + img.save(output).context("save image to disk")?; Ok(()) } diff --git a/crates/ironrdp/src/lib.rs b/crates/ironrdp/src/lib.rs index be28c3a1..142ccfbb 100644 --- a/crates/ironrdp/src/lib.rs +++ b/crates/ironrdp/src/lib.rs @@ -5,7 +5,7 @@ #[cfg(test)] use { - anyhow as _, async_trait as _, bmp as _, ironrdp_blocking as _, ironrdp_cliprdr_native as _, pico_args as _, + anyhow as _, async_trait as _, image as _, ironrdp_blocking as _, ironrdp_cliprdr_native as _, pico_args as _, rand as _, sspi as _, tokio_rustls as _, tracing as _, tracing_subscriber as _, x509_cert as _, };