recolor outlines
This commit is contained in:
87
src/main.rs
87
src/main.rs
@@ -7,25 +7,40 @@ use std::process;
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
if args.len() < 4 {
|
||||
if args.len() < 5 {
|
||||
print_usage(&args[0]);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let input_path = &args[1];
|
||||
let output_path = &args[2];
|
||||
let color_input = &args[3];
|
||||
let apply_texture = args.len() > 4 && args[4].to_lowercase() == "true";
|
||||
let white_color_input = &args[3];
|
||||
let black_color_input = &args[4];
|
||||
let apply_texture = args.len() > 5 && args[5].to_lowercase() == "true";
|
||||
|
||||
let target_color = match parse_hex_color(color_input) {
|
||||
let white_color = match parse_hex_color(white_color_input) {
|
||||
Ok(color) => color,
|
||||
Err(e) => {
|
||||
eprintln!("Error: {}", e);
|
||||
eprintln!("Error parsing white color: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
match recolor_gif(input_path, output_path, target_color, apply_texture) {
|
||||
let black_color = match parse_hex_color(black_color_input) {
|
||||
Ok(color) => color,
|
||||
Err(e) => {
|
||||
eprintln!("Error parsing black color: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
match recolor_gif(
|
||||
input_path,
|
||||
output_path,
|
||||
white_color,
|
||||
black_color,
|
||||
apply_texture,
|
||||
) {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
eprintln!("Error: {}", e);
|
||||
@@ -36,19 +51,24 @@ fn main() {
|
||||
|
||||
fn print_usage(program: &str) {
|
||||
eprintln!(
|
||||
"Usage: {} <input.gif> <output.gif> <color> [texture]",
|
||||
"Usage: {} <input.gif> <output.gif> <white_color> <black_color> [texture]",
|
||||
program
|
||||
);
|
||||
eprintln!();
|
||||
eprintln!("Arguments:");
|
||||
eprintln!(" <input.gif> Path to input GIF file");
|
||||
eprintln!(" <output.gif> Path to output GIF file");
|
||||
eprintln!(" <color> Target color in hex format (e.g., FF5733 or #FF5733)");
|
||||
eprintln!(
|
||||
" <white_color> Target color for white pixels in hex format (e.g., FF5733 or #FF5733)"
|
||||
);
|
||||
eprintln!(
|
||||
" <black_color> Target color for black pixels in hex format (e.g., 000000 or #000000)"
|
||||
);
|
||||
eprintln!(" [texture] Optional: 'true' to apply texture/noise (default: false)");
|
||||
eprintln!();
|
||||
eprintln!("Examples:");
|
||||
eprintln!(" {} neko.gif neko_red.gif FF0000", program);
|
||||
eprintln!(" {} neko.gif neko_blue.gif 0066FF true", program);
|
||||
eprintln!(" {} neko.gif neko_red.gif FF0000 000000", program);
|
||||
eprintln!(" {} neko.gif neko_blue.gif 0066FF 330000 true", program);
|
||||
}
|
||||
|
||||
fn parse_hex_color(hex: &str) -> Result<Rgba<u8>, String> {
|
||||
@@ -67,7 +87,8 @@ fn parse_hex_color(hex: &str) -> Result<Rgba<u8>, String> {
|
||||
fn recolor_gif(
|
||||
input_path: &str,
|
||||
output_path: &str,
|
||||
target_color: Rgba<u8>,
|
||||
white_color: Rgba<u8>,
|
||||
black_color: Rgba<u8>,
|
||||
apply_texture: bool,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Open and decode input GIF
|
||||
@@ -94,7 +115,7 @@ fn recolor_gif(
|
||||
.ok_or("Failed to create image from frame")?;
|
||||
|
||||
// Recolor the image
|
||||
recolor_image(&mut img, target_color, apply_texture);
|
||||
recolor_image(&mut img, white_color, black_color, apply_texture);
|
||||
|
||||
// Create output frame with same timing
|
||||
let mut pixel_data = img.into_raw();
|
||||
@@ -107,12 +128,23 @@ fn recolor_gif(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn recolor_image(img: &mut RgbaImage, target_color: Rgba<u8>, apply_texture: bool) {
|
||||
// Generate color palette with variations if texture is enabled
|
||||
let color_palette = if apply_texture {
|
||||
generate_color_palette(target_color, 7)
|
||||
fn recolor_image(
|
||||
img: &mut RgbaImage,
|
||||
white_color: Rgba<u8>,
|
||||
black_color: Rgba<u8>,
|
||||
apply_texture: bool,
|
||||
) {
|
||||
// Generate color palettes with variations if texture is enabled
|
||||
let white_palette = if apply_texture {
|
||||
generate_color_palette(white_color, 7)
|
||||
} else {
|
||||
vec![target_color]
|
||||
vec![white_color]
|
||||
};
|
||||
|
||||
let black_palette = if apply_texture {
|
||||
generate_color_palette(black_color, 7)
|
||||
} else {
|
||||
vec![black_color]
|
||||
};
|
||||
|
||||
for (x, y, pixel) in img.enumerate_pixels_mut() {
|
||||
@@ -128,14 +160,19 @@ fn recolor_image(img: &mut RgbaImage, target_color: Rgba<u8>, apply_texture: boo
|
||||
|
||||
// Determine pixel type based on brightness
|
||||
if brightness < 64 {
|
||||
// Very dark pixels (outlines) - keep original
|
||||
continue;
|
||||
} else if brightness > 200 {
|
||||
// White/light pixels (body) - apply target color
|
||||
// Very dark pixels (outlines) - apply black target color
|
||||
let chosen_color = if apply_texture {
|
||||
pick_color_from_palette(&color_palette, x, y)
|
||||
pick_color_from_palette(&black_palette, x, y)
|
||||
} else {
|
||||
target_color
|
||||
black_color
|
||||
};
|
||||
*pixel = chosen_color;
|
||||
} else if brightness > 200 {
|
||||
// White/light pixels (body) - apply white target color
|
||||
let chosen_color = if apply_texture {
|
||||
pick_color_from_palette(&white_palette, x, y)
|
||||
} else {
|
||||
white_color
|
||||
};
|
||||
*pixel = chosen_color;
|
||||
} else {
|
||||
@@ -145,9 +182,9 @@ fn recolor_image(img: &mut RgbaImage, target_color: Rgba<u8>, apply_texture: boo
|
||||
let blend_factor = blend_factor.clamp(0.0, 1.0);
|
||||
|
||||
let chosen_color = if apply_texture {
|
||||
pick_color_from_palette(&color_palette, x, y)
|
||||
pick_color_from_palette(&white_palette, x, y)
|
||||
} else {
|
||||
target_color
|
||||
white_color
|
||||
};
|
||||
|
||||
let new_r =
|
||||
|
||||
Reference in New Issue
Block a user