From ef99bee0d3b0ef56fa257e26596190fded039f54 Mon Sep 17 00:00:00 2001 From: Joscha Date: Sun, 30 Jul 2023 17:13:23 +0200 Subject: [PATCH] Convert images into black and white --- src/lib.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 42 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 src/lib.rs diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..2ea98a4 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,55 @@ +use image::RgbaImage; +use palette::{Hsl, IntoColor, Lab, LinSrgb, Oklab, Srgb}; + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum BwMethod { + SrgbAverage, + LinSrgbAverage, + Hsl, + Cielab, + Oklab, +} + +impl BwMethod { + fn to_bw(self, pixel: Srgb) -> Srgb { + match self { + Self::SrgbAverage => { + let value = (pixel.red + pixel.green + pixel.blue) / 3.0; + Srgb::new(value, value, value) + } + Self::LinSrgbAverage => { + let pixel: LinSrgb = pixel.into_color(); + let value = (pixel.red + pixel.green + pixel.blue) / 3.0; + LinSrgb::new(value, value, value).into_color() + } + Self::Hsl => { + let mut pixel: Hsl = pixel.into_color(); + pixel.saturation = 0.0; + pixel.into_color() + } + Self::Cielab => { + let mut pixel: Lab = pixel.into_color(); + pixel.a = 0.5; + pixel.b = 0.5; + pixel.into_color() + } + Self::Oklab => { + let mut pixel: Oklab = pixel.into_color(); + pixel.a = 0.0; + pixel.b = 0.0; + pixel.into_color() + } + } + } +} + +pub fn bw(image: &mut RgbaImage, method: BwMethod) { + for pixel in image.pixels_mut() { + let [r, g, b, _] = pixel.0; + let srgb = Srgb::new(r, g, b).into_format::(); + let srgb = method.to_bw(srgb).into_format::(); + pixel.0[0] = srgb.red; + pixel.0[1] = srgb.green; + pixel.0[2] = srgb.blue; + } +} diff --git a/src/main.rs b/src/main.rs index 49ea471..9c7be13 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,15 +6,54 @@ use std::{ use clap::Parser; use image::{ImageFormat, RgbaImage}; +#[derive(Debug, Clone, Copy, clap::ValueEnum)] +enum BwMethod { + SrgbAverage, + LinSrgbAverage, + Hsl, + Cielab, + Oklab, +} + +impl From for mark::BwMethod { + fn from(value: BwMethod) -> Self { + match value { + BwMethod::SrgbAverage => mark::BwMethod::SrgbAverage, + BwMethod::LinSrgbAverage => mark::BwMethod::LinSrgbAverage, + BwMethod::Hsl => mark::BwMethod::Hsl, + BwMethod::Cielab => mark::BwMethod::Cielab, + BwMethod::Oklab => mark::BwMethod::Oklab, + } + } +} + #[derive(Debug, clap::Parser)] /// Convert images into black and white. -struct BwCmd {} +struct BwCmd { + #[arg(long, short)] + method: BwMethod, +} + +impl BwCmd { + fn run(self, mut image: RgbaImage) -> RgbaImage { + mark::bw(&mut image, self.method.into()); + image + } +} #[derive(Debug, clap::Parser)] enum Cmd { Bw(BwCmd), } +impl Cmd { + fn run(self, image: RgbaImage) -> RgbaImage { + match self { + Cmd::Bw(cmd) => cmd.run(image), + } + } +} + #[derive(Debug, clap::Parser)] struct Args { /// Load image from file instead of stdin. @@ -70,5 +109,6 @@ fn save_image(out: &Option, image: RgbaImage) { fn main() { let args = Args::parse(); let image = load_image(&args.r#in); + let image = args.cmd.run(image); save_image(&args.out, image); }