add ansi24 mode

This commit is contained in:
Anatoly Bazarov 2023-04-03 13:58:50 -07:00
parent 8c191f264e
commit d7b58f9be3
3 changed files with 43 additions and 8 deletions

View File

@ -1,11 +1,11 @@
# img2irc (0.1.0) # img2irc (0.2.0)
![EVA Loader](https://i.imgur.com/wLyj1HH.png) ![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 img2irc is a utility which converts images to halfblock irc/ansi art, with a lot of post-processing filters
*halfblock* means that each row will contain two rows worth of pixels, effectively doubling the resolution *halfblock* means that each row will contain two rows worth of pixels, effectively doubling the resolution
the `irc` mode has 99 colours, the `ansi` mode has 256 the `irc` mode has 99 colours, the `ansi` mode has 256, `ansi24` has 65536
## usage ## usage
@ -14,7 +14,7 @@ the `irc` mode has 99 colours, the `ansi` mode has 256
| option | description | default value | | option | description | default value |
| ------ | ----------- | ------------- | | ------ | ----------- | ------------- |
| `<IMAGE>` | image url or file path | none | | `<IMAGE>` | image url or file path | none |
| `-r, --render <RENDER>` | render type (irc, ansi) | irc | | `-r, --render <RENDER>` | render type (irc, ansi, ansi24) | irc |
| `-w, --width <WIDTH>` | output image width in columns | 50 | | `-w, --width <WIDTH>` | output image width in columns | 50 |
| `-b, --brightness=<BRIGHTNESS>` | adjust brightness (-255 to 255) | 0 | | `-b, --brightness=<BRIGHTNESS>` | adjust brightness (-255 to 255) | 0 |
| `-H, --hue=<HUE>` | adjust hue (-180 to 180) | 0 | | `-H, --hue=<HUE>` | adjust hue (-180 to 180) | 0 |

View File

@ -40,7 +40,7 @@ impl AnsiImage {
pub fn new(image: PhotonImage) -> AnsiImage { pub fn new(image: PhotonImage) -> AnsiImage {
let mut bitmap = image.get_raw_pixels() let mut bitmap = image.get_raw_pixels()
.chunks(4) .chunks(4)
.map(|x| make_rgb(x.to_vec())) .map(|x| make_rgb_u32(x.to_vec()))
.collect::<Vec<u32>>() .collect::<Vec<u32>>()
.chunks(image.get_width() as usize) .chunks(image.get_width() as usize)
.map(|x| x.to_vec()) .map(|x| x.to_vec())
@ -60,7 +60,16 @@ impl AnsiImage {
} }
} }
pub fn make_rgb(rgb: Vec<u8>) -> u32 { pub fn make_rgb_u8(rgb: u32) -> [u8; 3] {
// convert u32 to r,g,b
let r = (rgb >> 16) as u8;
let g = (rgb >> 8) as u8;
let b = rgb as u8;
return [r, g, b]
}
pub fn make_rgb_u32(rgb: Vec<u8>) -> u32 {
let r = *rgb.get(0).unwrap() as u32; let r = *rgb.get(0).unwrap() as u32;
let g = *rgb.get(1).unwrap() as u32; let g = *rgb.get(1).unwrap() as u32;
let b = *rgb.get(2).unwrap() as u32; let b = *rgb.get(2).unwrap() as u32;
@ -105,12 +114,37 @@ pub fn halfblock_bitmap(bitmap: &Vec<Vec<u32>>) -> Vec<Vec<AnsiPixelPair>> {
ansi_canvas ansi_canvas
} }
pub fn ansi_draw(image: AnsiImage) -> String { pub fn ansi_draw_24bit(image: AnsiImage) -> String {
let mut out: String = String::new();
for row in image.halfblock {
for pixel_pair in row.iter() {
let fg = make_rgb_u8(pixel_pair.top.orig)
.to_vec()
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>();
let bg = make_rgb_u8(pixel_pair.bottom.orig)
.to_vec()
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>();
out.push_str(format!("\x1b[38;2;{}m\x1b[48;2;{}m{}", fg.join(";"), bg.join(";"), CHAR).as_str());
}
out.push_str("\x1b[0m");
out.push_str("\n");
}
return out
}
pub fn ansi_draw_8bit(image: AnsiImage) -> String {
let mut out: String = String::new(); let mut out: String = String::new();
for row in image.halfblock { for row in image.halfblock {
for pixel_pair in row.iter() { for pixel_pair in row.iter() {
let fg = pixel_pair.top.ansi; let fg = pixel_pair.top.ansi;
let bg = pixel_pair.bottom.ansi; let bg = pixel_pair.bottom.ansi;
out.push_str(format!("\x1b[38;5;{}m\x1b[48;5;{}m{}", fg, bg, CHAR).as_str()); out.push_str(format!("\x1b[38;5;{}m\x1b[48;5;{}m{}", fg, bg, CHAR).as_str());
} }
out.push_str("\x1b[0m"); out.push_str("\x1b[0m");

View File

@ -26,7 +26,8 @@ async fn main() {
None => println!("{}", draw::irc_draw(canvas).as_str()), None => println!("{}", draw::irc_draw(canvas).as_str()),
Some(ref render) => match render.as_str() { Some(ref render) => match render.as_str() {
"irc" => println!("{}", draw::irc_draw(canvas).as_str()), "irc" => println!("{}", draw::irc_draw(canvas).as_str()),
"ansi" => println!("{}", draw::ansi_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"); eprintln!("Error: invalid render type");
exit(1); exit(1);