diff --git a/Cargo.toml b/Cargo.toml index b9436e7..572de5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,16 @@ [package] name = "img2irc" -version = "0.2.0" +version = "1.0.0" authors = ["anatolybazarov"] github = "https://github.com/anatolybazarov/img2irc" edition = "2021" +[profile.release] +lto = true +codegen-units = 1 +opt-level = "z" +strip = true # Automatically strip symbols from the binary. + [dependencies] tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } reqwest = "0.11.14" diff --git a/README.md b/README.md index 59667f5..2345cd9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# img2irc (0.2.0) +# img2irc (1.0.0) ![img2irc preview](https://i.imgur.com/oetHhMB.png) img2irc is a utility which converts images to halfblock irc/ansi art, with a lot of post-processing filters @@ -14,14 +14,15 @@ the `irc` mode has 99 colours, the `ansi` mode has 256, `ansi24` has 16777216 | option | description | default value | | ------ | ----------- | ------------- | | `` | image url or file path | none | -| `-r, --render ` | render type (irc, ansi, ansi24) | irc | +| `--irc` | irc render type | true | +| `--ansi` | 8-bit ansi render type | false | +| `--ansi24` | 24-bit ansi render type | false | | `-w, --width ` | output image width in columns | 50 | | `-b, --brightness=` | adjust brightness (-255 to 255) | 0 | -| `-H, --hue=` | adjust hue (-180 to 180) | 0 | | `-c, --contrast=` | adjust contrast (-255 to 255) | 0 | | `-s, --saturation=` | adjust saturation (-255 to 255) | 0 | -| `-o, --opacity=` | adjust opacity (-255 to 255) | 0 | -| `-g, --gamma=` | adjust gamma (-255 to 255) | 0 | +| `-H, --hue ` | rotate hue (0 to 360) | 0 | +| `-g, --gamma ` | adjust gamma (0 to 255) | 0 | | `--dither ` | dithering (1 to 8) | 0 | | `--pixelize ` | pixelize pixel size | 0 | | `--gaussian-blur ` | gaussian blur radius | 0 | diff --git a/src/args.rs b/src/args.rs index d7791a6..69a38d1 100644 --- a/src/args.rs +++ b/src/args.rs @@ -7,37 +7,41 @@ pub struct Args { #[arg(index = 1)] pub image: String, - /// render type (irc, ansi) - #[arg(short, long)] - pub render: Option, + /// irc + #[arg(long, default_value_t = false)] + pub irc: bool, + + /// 8-bit ansi + #[arg(long, default_value_t = false)] + pub ansi: bool, + + /// 24-bit ansi + #[arg(long, default_value_t = false)] + pub ansi24: bool, /// image width to resize to #[arg(short, long, default_value_t = 50)] pub width: u32, /// brightness (-255 to 255) - #[arg(short, long, require_equals = true, default_value_t = 0)] - pub brightness: i16, - - /// hue (-180 to 180) - #[arg(short = 'H', long, require_equals = true, default_value_t = 0)] - pub hue: i16, + #[arg(short, long, require_equals = true, default_value_t = 0.0)] + pub brightness: f32, /// contrast (-255 to 255) - #[arg(short, long, require_equals = true, default_value_t = 0)] - pub contrast: i16, + #[arg(short, long, require_equals = true, default_value_t = 0.0)] + pub contrast: f32, /// saturation (-255 to 255) - #[arg(short, long, require_equals = true, default_value_t = 0)] - pub saturation: i16, + #[arg(short, long, require_equals = true, default_value_t = 0.0)] + pub saturation: f32, - /// opacity (-255 to 255) - #[arg(short, long, require_equals = true, default_value_t = 0)] - pub opacity: i16, + /// hue (0 to 360) + #[arg(short = 'H', long, default_value_t = 0.0)] + pub hue: f32, - /// gamma (-255 to 255) - #[arg(short, long, require_equals = true, default_value_t = 0)] - pub gamma: i16, + /// gamma (0 to 255) + #[arg(short, long, default_value_t = 0.0)] + pub gamma: f32, /// dither (1 to 8) #[arg(long, default_value_t = 0)] diff --git a/src/effects.rs b/src/effects.rs index 0a9b20d..cf8136c 100644 --- a/src/effects.rs +++ b/src/effects.rs @@ -1,5 +1,6 @@ use crate::args; -use photon_rs::{channels, channels::alter_channels, conv, effects, filters, monochrome, noise}; +use photon_rs::{colour_spaces}; +use photon_rs::{channels, conv, effects, filters, monochrome, noise}; use photon_rs::transform::{resize, SamplingFilter}; use photon_rs::PhotonImage; @@ -15,33 +16,41 @@ pub fn apply_effects( photon_image = resize(&mut photon_image, args.width, height, SamplingFilter::Lanczos3); // Adjust brightness - if args.brightness != 0 { - alter_channels(&mut photon_image, args.brightness, args.brightness, args.brightness); + match args.brightness { + x if x > 0.0 => { + colour_spaces::hsv(&mut photon_image, "brighten", args.brightness/255.0); + } + x if x < 0.0 => { + colour_spaces::hsv(&mut photon_image, "darken", args.brightness.abs()/255.0); + }, + _ => {} } // Adjust hue - if args.hue != 0 { - alter_channels(&mut photon_image, args.hue, args.hue, args.hue); + if args.hue > 0.0 { + colour_spaces::hsv(&mut photon_image, "shift_hue", args.hue/360.0); } // Adjust contrast - if args.contrast != 0 { - alter_channels(&mut photon_image, args.contrast, args.contrast, args.contrast); + if args.contrast != 0.0 { + effects::adjust_contrast(&mut photon_image, args.contrast); } // Adjust saturation - if args.saturation != 0 { - alter_channels(&mut photon_image, args.saturation, args.saturation, args.saturation); - } - - // Adjust opacity - if args.opacity != 0 { - alter_channels(&mut photon_image, args.opacity, args.opacity, args.opacity); + match args.saturation { + x if x > 0.0 => { + colour_spaces::hsv(&mut photon_image, "saturate", args.saturation/255.0); + } + x if x < 0.0 => { + colour_spaces::hsv(&mut photon_image, "desaturate", args.saturation.abs()/255.0); + } + _ => {} } // Adjust gamma - if args.gamma != 0 { - alter_channels(&mut photon_image, args.gamma, args.gamma, args.gamma); + if args.gamma != 0.0 { + let gamma_value = 1.0 - args.gamma/255.0; + colour_spaces::gamma_correction(&mut photon_image, gamma_value, gamma_value, gamma_value); } // Adjust dither @@ -51,7 +60,6 @@ pub fn apply_effects( // Adjust gaussian_blur if args.gaussian_blur > 0 { - conv::gaussian_blur(&mut photon_image, args.gaussian_blur); } diff --git a/src/main.rs b/src/main.rs index cc662d1..e34e26a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,18 +22,17 @@ async fn main() { ); let canvas = draw::AnsiImage::new(image); - match &args.render { - None => println!("{}", draw::irc_draw(canvas).as_str()), - Some(ref render) => match render.as_str() { - "irc" => println!("{}", draw::irc_draw(canvas).as_str()), - "ansi" => println!("{}", draw::ansi_draw_8bit(canvas).as_str()), - "ansi24" => println!("{}", draw::ansi_draw_24bit(canvas).as_str()), - _ => { - eprintln!("Error: invalid render type"); - exit(1); - } - }, + + if args.irc { + println!("{}", draw::irc_draw(canvas).as_str()); + } else if args.ansi { + println!("{}", draw::ansi_draw_8bit(canvas).as_str()); + } else if args.ansi24 { + println!("{}", draw::ansi_draw_24bit(canvas).as_str()); + } else { + println!("{}", draw::irc_draw(canvas).as_str()); } + } Err(e) => { eprintln!("Error: {}", e);