64 lines
1.8 KiB
Rust
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(())
|
|
}
|