5 Commits
1.0 ... 1.1

Author SHA1 Message Date
520d8ddd00 updated README 2023-02-09 14:08:00 +01:00
bb92920e65 updated version 2023-02-09 14:03:23 +01:00
f4d7e60a07 added support for colouring th background instead of the foreground 2023-02-09 14:01:45 +01:00
c138c047ed small rebase of to_ascii function 2023-02-09 13:49:16 +01:00
8de99aefac added grayscale support 2023-02-09 13:46:12 +01:00
7 changed files with 100 additions and 10 deletions

View File

@@ -1,6 +1,6 @@
[package]
name = "img2ascii"
version = "1.0.0"
version = "1.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@@ -6,6 +6,8 @@ It can be configured using flags on the command line, a few options of which are
* Complex ASCII (using the map ``` .'`^",:;Il!i><~+_-?][}{1)(|\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$```)
* [Braille symbols](https://en.wikipedia.org/wiki/Braille_Patterns)
* Custom character maps (through the `--map` flag)
* Output in full colour
* Output in grayscale
# Prerequisites
* [Rust](https://www.rust-lang.org/) (building from source only)
@@ -32,6 +34,8 @@ Of course the output can be customized, by using one (or more) flags.
## options
* -c, --complex: uses the extended character map
* -C, --colour: Display ASCII art in full 24-bit colour
* --background: Colour the background instead of the foreground
* -g, --grayscale: Display ASCII art in grayscale
* -b, --braille: Use braille characters instead of a character map
* -d, --debug: Print debugging information
* -f, --full: use the full width of the terminal, instead of fitting the image to the terminal dimensions
@@ -47,14 +51,19 @@ When two or more of these are entered in the same command,
the program uses the one with the highest precedence, in the order
`braille > complex > map`.
The flags `--output` and `--colour` also conflict.
The flags `--output`, `--colour` and `--grayscale` also conflict.
When both are entered, the flag `--output` takes precedence
(leading to a simple txt file).
Lastly, the flags `--full` and `--width` are mutually exclusive.
The flags `--full` and `--width` are mutually exclusive.
When both are entered, the flag `-full` will be applied
(`full > width`).
Lastly, the flags `--colour` and `--grayscale` are not mutually applicable.
When both are entered, the flag `--colour` will be applied.
Note also that the `--background` flag requires either `--colour` or `--grayscale` to do anything.
# Documentation
The program has been documented with RustDoc,
which can be compiled and viewed with

View File

@@ -36,8 +36,10 @@ fn to_ascii(char_map: String, image: DynamicImage) -> Vec<Vec<Ascii>> {
let mut out: Vec<Vec<Ascii>> = Vec::new();
for pixel in image.pixels() {
let ch = char_map.as_bytes()[((get_color(pixel.2) as f32-1.0)/255f32 * l) as usize];
str.push(Ascii::new(ch, pixel.2[0], pixel.2[1], pixel.2[2]));
let mut ascii = Ascii::new(0, pixel.2[0], pixel.2[1], pixel.2[2]);
let ch = char_map.as_bytes()[((ascii.col_depth as f32-1.0)/255f32 * l) as usize];
ascii.char = char::from(ch);
str.push(ascii);
if pixel.0 == image.width()-1 {
out.push(str);
@@ -116,7 +118,7 @@ pub fn to_braille_ascii(image: DynamicImage, threshold: u8) -> Vec<Vec<Ascii>> {
}
}
}
str.push(Ascii { char: char::from_u32(braille_value).unwrap(), rgb: [(r/8) as u8, (g/8) as u8, (b/8) as u8] });
str.push(Ascii::new_with_char(char::from_u32(braille_value).unwrap(), (r/8) as u8, (g/8) as u8, (b/8) as u8));
}
out.push(str);
str = Vec::new();

View File

@@ -18,8 +18,20 @@ pub struct Cli {
#[arg(short = 'c', long)]
pub complex: bool,
/// Display ASCII art in full colour
///
/// Takes priority over '--grayscale'
#[arg(short = 'C', long)]
pub colour: bool,
/// Colour the background instead of the foreground
///
/// Requires '--colour' or '--grayscale' to be passed
#[arg(long)]
pub background: bool,
/// Display ASCII art in grayscale
///
/// incompatible with '--color'
#[arg(short= 'g', long)]
pub grayscale: bool,
/// Use braille characters instead of ASCII
///
/// Takes priority over '--complex' and '--map'
@@ -49,7 +61,7 @@ pub struct Cli {
pub width: Option<u32>,
/// Save the output to a file, instead of printing to terminal
///
/// Incompatible with '--colour'
/// Incompatible with '--colour' and '--grayscale'
#[arg(short = 'o', long = "output")]
pub output: Option<PathBuf>,
}
@@ -62,6 +74,8 @@ impl Cli {
pub fn debug_print(&self) {
debug!("complex: {}", self.complex);
debug!("colour: {}", self.colour);
debug!("background: {}", self.background);
debug!("grayscale: {}", self.grayscale);
debug!("braille: {}", self.braille);
debug!("debug: {}", self.debug);
debug!("full: {}", self.full);

View File

@@ -45,6 +45,10 @@ fn main() {
if let Some(output) = cli.output {
print_file(out, output);
} else {
print_terminal(out, cli.colour);
if cli.background && (cli.colour || cli.grayscale) {
print_terminal_background(out, cli.colour, cli.grayscale);
} else {
print_terminal(out, cli.colour, cli.grayscale);
}
}
}

View File

@@ -1,9 +1,15 @@
//! This module contains the Ascii struct.
/// This struct represents one character + rgb colour.
///
/// attributes:
/// char: char - the character associated with this ASCII value
/// rgb: [u8; 3] - vec of 3 u8 values representing red, green, and blue respectively
/// col_depthL u8 - the depth of the rgb values, calculated through the luminosity method
pub struct Ascii {
pub char: char,
pub rgb: [u8; 3],
pub col_depth: u8,
}
impl Ascii {
@@ -21,6 +27,25 @@ impl Ascii {
Ascii {
char: char::from(ch),
rgb: [r, g, b],
col_depth: (r as f32 * 0.3 + g as f32 * 0.59 + b as f32 * 0.11) as u8,
}
}
/// This function creates a new Ascii instance.
///
/// Arguments:
/// ch: char - the character
/// r: u8 - Red colour value
/// g: u8 - Green colour value
/// b: u8 - Blue colour value
///
/// returns:
/// self
pub fn new_with_char(ch: char, r: u8, g: u8, b: u8) -> Self {
Ascii {
char: ch,
rgb: [r, g, b],
col_depth: (r as f32 * 0.3 + g as f32 * 0.59 + b as f32 * 0.11) as u8,
}
}
}

View File

@@ -4,7 +4,7 @@ use std::io::{stdout, Write};
use std::path::PathBuf;
use std::process::exit;
use crossterm::execute;
use crossterm::style::{Color, SetForegroundColor, Print, ResetColor};
use crossterm::style::{Color, SetForegroundColor, SetBackgroundColor, Print, ResetColor};
use log::error;
use crate::model_rgb_ascii::Ascii;
@@ -13,7 +13,8 @@ use crate::model_rgb_ascii::Ascii;
/// arguments:
/// art: Vec<Vec<Ascii>> - vector of vectors representing the art
/// in_colour: bool - whether to print in colour or as hard white
pub fn print_terminal(art: Vec<Vec<Ascii>>, in_colour: bool) {
/// grayscale: bool - whether to print grayscale
pub fn print_terminal(art: Vec<Vec<Ascii>>, in_colour: bool, grayscale: bool) {
for line in art {
for ascii in line {
if in_colour {
@@ -21,6 +22,11 @@ pub fn print_terminal(art: Vec<Vec<Ascii>>, in_colour: bool) {
SetForegroundColor(Color::Rgb {r: ascii.rgb[0], g: ascii.rgb[1], b: ascii.rgb[2]}),
Print(ascii.char),
ResetColor);
} else if grayscale {
let _ = execute!(stdout(),
SetForegroundColor(Color::Rgb {r: ascii.col_depth, g: ascii.col_depth, b: ascii.col_depth}),
Print(ascii.char),
ResetColor);
} else {
print!("{}", ascii.char);
}
@@ -29,6 +35,36 @@ pub fn print_terminal(art: Vec<Vec<Ascii>>, in_colour: bool) {
}
}
/// This function prints ASCII art to the background of stdout.
///
/// arguments:
/// art: Vec<Vec<Ascii>> - vector of vectors representing the art
/// in_colour: bool - whether to print in colour
/// grayscale: bool - whether to print grayscale
pub fn print_terminal_background(art: Vec<Vec<Ascii>>, in_colour: bool, grayscale: bool) {
for line in art {
for ascii in line {
if in_colour {
let _ = execute!(stdout(),
SetBackgroundColor(Color::Rgb {r: ascii.rgb[0], g: ascii.rgb[1], b: ascii.rgb[2]}),
SetForegroundColor(Color::Rgb {r: 255-ascii.rgb[0], g: 255-ascii.rgb[1], b: 255-ascii.rgb[2]}),
Print(ascii.char),
ResetColor);
} else if grayscale {
let _ = execute!(stdout(),
SetBackgroundColor(Color::Rgb {r: ascii.col_depth, g: ascii.col_depth, b: ascii.col_depth}),
SetForegroundColor(Color::Rgb {r: 255-ascii.col_depth, g: 255-ascii.col_depth, b: 255-ascii.col_depth}),
Print(ascii.char),
ResetColor);
} else {
error!("This should be unreachable!");
exit(1);
}
}
println!();
}
}
/// This function prints ASCII art to a file.
///
/// arguments: