From bbbdc2c1ca3f8b7732829232bc960e63deb2c4db Mon Sep 17 00:00:00 2001 From: Shinyzenith Date: Wed, 20 Jul 2022 19:21:15 +0530 Subject: [PATCH] [backend.rs] Add support for ppm rendering. * Closes: https://github.com/waycrate/wayshot/issues/12 * Thanks to AmusedAstronaut in our matrix room for patching ppm support in * Fixes a regression where `--stdout` would not respect `--extension` provided by user Signed-off-by: Shinyzenith --- Cargo.lock | 40 ++++++++++++++-------------------------- Cargo.toml | 4 ++-- src/backend.rs | 30 +++++++++++++++++++++++++++++- src/wayshot.rs | 50 +++++++++++++++++++++++++++----------------------- 4 files changed, 72 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a9090d30..52097806 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,9 +63,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.2.12" +version = "3.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8b79fe3946ceb4a0b1c080b4018992b8d27e9ff363644c1c9b6387c854614d" +checksum = "ac2bd7a1eb07da9ac757c923f69373deb7bc2ba5efc951b873bcb5e693992dca" dependencies = [ "atty", "bitflags", @@ -137,9 +137,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hermit-abi" @@ -152,15 +152,14 @@ dependencies = [ [[package]] name = "image" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28edd9d7bc256be2502e325ac0628bde30b7001b9b52e0abe31a1a9dc2701212" +checksum = "7e30ca2ecf7666107ff827a8e481de6a132a9b687ed3bb20bb1c144a36c00964" dependencies = [ "bytemuck", "byteorder", "color_quant", "jpeg-decoder", - "num-iter", "num-rational", "num-traits", "png", @@ -248,9 +247,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9" +checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" dependencies = [ "bitflags", "cfg-if", @@ -268,17 +267,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" version = "0.4.1" @@ -307,9 +295,9 @@ checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" [[package]] name = "pkg-config" @@ -408,9 +396,9 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" [[package]] name = "wayland-client" @@ -473,14 +461,14 @@ dependencies = [ [[package]] name = "wayshot" -version = "1.1.7" +version = "1.1.9" dependencies = [ "clap", "env_logger", "image", "log", "memmap2", - "nix 0.24.1", + "nix 0.24.2", "tempfile", "wayland-client", "wayland-protocols", diff --git a/Cargo.toml b/Cargo.toml index 1a9c9241..12ffd837 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["screenshot", "wayland", "wlroots"] license = "BSD-2-Clause" name = "wayshot" repository = "https://git.sr.ht/~shinyzenith/wayshot" -version = "1.1.8" +version = "1.1.9" exclude = [ "CODE_OF_CONDUCT.md", "CONTRIBUTING.md", @@ -20,7 +20,7 @@ exclude = [ [dependencies] clap = "3.1.18" env_logger = { version = "0.9.0", default-features = false, features = ["atty", "termcolor"] } -image = { version = "0.24", default-features = false, features = ["jpeg", "png"] } +image = { version = "0.24", default-features = false, features = ["jpeg", "png", "pnm"] } log = "0.4.17" memmap2 = "0.5.3" nix = "0.24.1" diff --git a/src/backend.rs b/src/backend.rs index 19cae9e4..e3f140ee 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -19,7 +19,11 @@ use nix::{ }; use image::{ - codecs::{jpeg::JpegEncoder, png::PngEncoder}, + codecs::{ + jpeg::JpegEncoder, + png::PngEncoder, + pnm::{self, PnmEncoder}, + }, ColorType, ColorType::Rgba8, ImageEncoder, @@ -84,6 +88,8 @@ pub enum EncodingFormat { Jpg, /// Png encoder. Png, + /// Ppm encoder + Ppm, } /// Get a FrameCopy instance with screenshot pixel data for any wl_output object. @@ -375,6 +381,28 @@ pub fn write_to_file( )?; let _ = output_file.flush()?; } + EncodingFormat::Ppm => { + let rgb8_data = if let ColorType::Rgba8 = frame_copy.frame_color_type { + let data = frame_copy + .frame_mmap + .iter() + .enumerate() + .filter_map(|(i, &v)| if i % 4 != 3 { Some(v) } else { None }) + .collect::>(); + data + } else { + unimplemented!("Currently only ColorType::Rgba8 is supported") + }; + PnmEncoder::new(&mut output_file) + .with_subtype(pnm::PnmSubtype::Pixmap(pnm::SampleEncoding::Binary)) + .write_image( + &rgb8_data, + frame_copy.frame_format.width, + frame_copy.frame_format.height, + ColorType::Rgb8, + )?; + let _ = output_file.flush()?; + } } Ok(()) diff --git a/src/wayshot.rs b/src/wayshot.rs index 1a65a372..77cf6cd6 100644 --- a/src/wayshot.rs +++ b/src/wayshot.rs @@ -29,7 +29,6 @@ fn main() -> Result<(), Box> { log::trace!("Logger initialized."); let display = Display::connect_to_env()?; - let mut extension = backend::EncodingFormat::Png; let mut cursor_overlay: i32 = 0; if args.is_present("cursor") { @@ -111,14 +110,32 @@ fn main() -> Result<(), Box> { backend::capture_output_frame(display, cursor_overlay, output, None)? }; + let extension = if args.is_present("extension") { + let ext = args.value_of("extension").unwrap().trim(); + match ext { + "jpeg" | "jpg" => backend::EncodingFormat::Jpg, + "png" => backend::EncodingFormat::Png, + "ppm" => backend::EncodingFormat::Ppm, + _ => { + log::error!("Invalid extension provided.\nValid extensions:\n1) jpeg\n2) jpg\n3) png\n4) ppm"); + exit(1); + } + } + } else { + backend::EncodingFormat::Png + }; + + if extension != backend::EncodingFormat::Png { + log::debug!("Using custom extension: {:#?}", extension); + } + if args.is_present("stdout") { let stdout = stdout(); let writer = BufWriter::new(stdout.lock()); backend::write_to_file(writer, extension, frame_copy)?; } else { - let path: String; - if args.is_present("file") { - path = args.value_of("file").unwrap().trim().to_string(); + let path = if args.is_present("file") { + args.value_of("file").unwrap().trim().to_string() } else { let time = match SystemTime::now().duration_since(UNIX_EPOCH) { Ok(n) => n.as_secs().to_string(), @@ -128,28 +145,15 @@ fn main() -> Result<(), Box> { } }; - if args.is_present("extension") { - let ext = args.value_of("extension").unwrap().trim(); - match ext { - "jpeg" | "jpg" => { - extension = backend::EncodingFormat::Jpg; - log::debug!("Using custom extension: {:#?}", extension); - } - "png" => {} - _ => { - log::error!("Invalid extension provided.\nValid extensions:\n1) jpeg\n2) jpg\n3) png"); - exit(1); - } - } + time + match extension { + backend::EncodingFormat::Png => "-wayshot.png", + backend::EncodingFormat::Jpg => "-wayshot.jpg", + backend::EncodingFormat::Ppm => "-wayshot.ppm", } - path = time - + match extension { - backend::EncodingFormat::Png => "-wayshot.png", - backend::EncodingFormat::Jpg => "-wayshot.jpg", - }; - } + }; backend::write_to_file(File::create(path)?, extension, frame_copy)?; } + Ok(()) }