colorpickle/src/main.rs

64 lines
1.8 KiB
Rust

use clap::Parser;
use color_thief::ColorFormat;
use image::io::Reader as ImageReader;
use miette::{IntoDiagnostic, Result};
use pastel::ansi::{self, Brush, ToAnsiStyle};
#[derive(Parser, Debug)]
#[command(author, version, about)]
struct Args {
/// Number of colors to generate (excluding bold colors)
#[arg(short, long, default_value_t = 8)]
colors: u8,
/// Path to image to pick colors from
image: String,
/// Skip generating bold color variants
#[arg(short = 'b', long)]
no_bold: bool,
}
fn main() -> Result<()> {
let args = Args::parse();
// Parse image into a list of pixels
let pixels = ImageReader::open(args.image)
.into_diagnostic()?
.decode()
.into_diagnostic()?
.into_bytes();
// Generate colorscheme
let mut colors: Vec<_> =
color_thief::get_palette(pixels.as_ref(), ColorFormat::Rgb, 1, args.colors + 1)
.into_diagnostic()?
.into_iter()
.map(|c| pastel::Color::from_rgb(c.r, c.g, c.b))
.collect();
// Sort colors by luminance
colors.sort_by_key(|c| (c.luminance() * 1000.0) as i32);
if !args.no_bold {
// Create second pairs of lighter colors
let bold_colors = colors.clone();
let bold_colors = bold_colors.iter().map(|c| c.lighten(0.2));
colors.extend(bold_colors);
}
let brush = Brush::from_mode(Some(ansi::Mode::TrueColor));
// Print colors with formatting turned off for pipes
colors.iter().for_each(|c| {
println!(
"{}",
if atty::is(atty::Stream::Stdout) {
brush.paint(c.to_rgb_hex_string(true), c.text_color().ansi_style().on(c))
} else {
c.to_rgb_hex_string(true)
}
)
});
Ok(())
}