fixed resizing image
This commit is contained in:
parent
5a1eda07da
commit
b00ef93c1c
|
|
@ -1,4 +1,6 @@
|
|||
use std::process::exit;
|
||||
use image::{DynamicImage, GenericImageView, Rgba};
|
||||
use log::error;
|
||||
|
||||
//todo: consider how to take care of the a channel => do we want to render that as background?
|
||||
fn get_color(pixel: (u32, u32, Rgba<u8>)) -> u8 {
|
||||
|
|
@ -8,7 +10,6 @@ fn get_color(pixel: (u32, u32, Rgba<u8>)) -> u8 {
|
|||
}
|
||||
|
||||
fn to_ascii(char_map: String, image: DynamicImage) -> Vec<String> {
|
||||
//todo: add color support
|
||||
let l = char_map.len() as f32;
|
||||
let mut str = String::new();
|
||||
let mut out: Vec<String> = Vec::new();
|
||||
|
|
@ -39,6 +40,11 @@ pub fn to_braille_ascii(image: DynamicImage) -> Vec<String> {
|
|||
}
|
||||
|
||||
pub fn to_custom_ascii(char_map: String, image: DynamicImage) -> Vec<String> {
|
||||
//todo: this
|
||||
vec!["not implemented".to_owned()]
|
||||
if char_map.is_empty() {
|
||||
error!("Custom map can not be empty!");
|
||||
exit(1);
|
||||
}
|
||||
to_ascii(char_map, image)
|
||||
}
|
||||
|
||||
//todo: replace Vec<String> with a custom struct containing rgb information as well as character (for coloured output)
|
||||
30
src/cli.rs
30
src/cli.rs
|
|
@ -3,7 +3,6 @@ use std::path::PathBuf;
|
|||
use std::process::exit;
|
||||
use clap::Parser;
|
||||
use log::{debug, error};
|
||||
use image;
|
||||
|
||||
/// Convert an image to ASCII art and print it to the terminal.
|
||||
///
|
||||
|
|
@ -11,23 +10,40 @@ use image;
|
|||
#[derive(Parser)]
|
||||
pub struct Cli {
|
||||
/// Use a larger range of characters
|
||||
///
|
||||
/// Takes priority over '--map'
|
||||
#[arg(short = 'c', long)]
|
||||
pub complex: bool,
|
||||
/// Display ASCII art in full colour
|
||||
#[arg(short = 'C', long)]
|
||||
pub colour: bool,
|
||||
/// Use braille characters instead of ASCII
|
||||
///
|
||||
/// Takes priority over '--complex' and '--map'
|
||||
#[arg(short = 'b', long)]
|
||||
pub braille: bool,
|
||||
/// Print debugging information
|
||||
#[arg(short = 'd', long)]
|
||||
pub debug: bool,
|
||||
/// use the full width of the terminal
|
||||
///
|
||||
/// Takes priority over '--width'
|
||||
#[arg(short = 'f', long)]
|
||||
pub full: bool,
|
||||
/// use a custom character map for output
|
||||
///
|
||||
/// The character map is interpreted from dark(first character) to light(last character).
|
||||
/// The map can be any size, but at least 2 characters is recommended.
|
||||
#[arg(short = 'M', long)]
|
||||
pub map: Option<String>,
|
||||
/// Image path
|
||||
pub image: PathBuf,
|
||||
#[arg(short = 'w', long)]
|
||||
/// Set the width of the output, instead of using terminal width
|
||||
pub width: Option<u16>,
|
||||
#[arg(short = 'w', long)]
|
||||
pub width: Option<u32>,
|
||||
/// Save the output to a file, instead of printing to terminal
|
||||
///
|
||||
/// Incompatible with '--colour' and '--braille'
|
||||
#[arg(short = 'o', long = "output")]
|
||||
pub output: Option<PathBuf>,
|
||||
}
|
||||
|
|
@ -39,7 +55,13 @@ impl Cli {
|
|||
debug!("colour: {}", self.colour);
|
||||
debug!("braille: {}", self.braille);
|
||||
debug!("debug: {}", self.debug);
|
||||
debug!("width: {}", self.width.unwrap_or(u16::MAX));
|
||||
debug!("full: {}", self.full);
|
||||
if let Some(map) = self.map.clone() {
|
||||
debug!("map: \"{}\"", map);
|
||||
} else {
|
||||
debug!("map: None");
|
||||
}
|
||||
debug!("width: {}", self.width.unwrap_or(u32::MAX));
|
||||
debug!("image: {}", self.image.display());
|
||||
if let Some(output) = self.output.clone() {
|
||||
debug!("output: {}", output.display());
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
use std::cmp::min;
|
||||
use termion::terminal_size;
|
||||
use log::error;
|
||||
use log::{debug, error, trace};
|
||||
use std::process::exit;
|
||||
use std::path::PathBuf;
|
||||
use image::DynamicImage;
|
||||
use image::imageops::FilterType;
|
||||
|
||||
fn get_terminal_size() -> u32 {
|
||||
fn get_terminal_size() -> (u32, u32) {
|
||||
let size = terminal_size();
|
||||
match size {
|
||||
Ok(size) => {
|
||||
size.0 as u32
|
||||
(size.0 as u32, size.1 as u32)
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to get terminal size: {}", e.to_string());
|
||||
|
|
@ -18,12 +18,26 @@ fn get_terminal_size() -> u32 {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_size(w: Option<u16>, img_w: u32) -> u16 {
|
||||
if None == w {
|
||||
min(get_terminal_size(), img_w) as u16
|
||||
pub fn resize_image(img: DynamicImage, full: bool, opt_w: Option<u32>) -> DynamicImage {
|
||||
let (mut w, mut h) = (1,1);
|
||||
if full {
|
||||
w = get_terminal_size().0;
|
||||
h = (img.height() as f32 * w as f32 / img.width() as f32 * 0.5) as u32;
|
||||
} else if let Some(act_w) = opt_w {
|
||||
w = act_w;
|
||||
h = (img.height() as f32 * w as f32 / img.width() as f32 * 0.5) as u32;
|
||||
} else {
|
||||
w.unwrap()
|
||||
let (max_w, max_h) = get_terminal_size();
|
||||
if max_h*max_w/2 > img.height()*img.width() {
|
||||
h = max_h;
|
||||
w = (img.width() as f32 * h as f32 / img.height() as f32 * 2.0) as u32;
|
||||
} else {
|
||||
w = max_w;
|
||||
h = (img.height() as f32 * w as f32 / img.height() as f32 * 0.5) as u32;
|
||||
}
|
||||
}
|
||||
debug!("Resizing image to (w|h): {} | {}", w, h);
|
||||
img.resize_exact(w, h, FilterType::CatmullRom)
|
||||
}
|
||||
|
||||
pub fn open_image(path: PathBuf) -> DynamicImage {
|
||||
|
|
|
|||
40
src/main.rs
40
src/main.rs
|
|
@ -1,8 +1,8 @@
|
|||
use clap::Parser;
|
||||
use image::imageops::FilterType;
|
||||
use crate::ascii_manipulation::to_simple_ascii;
|
||||
use crate::ascii_manipulation::*;
|
||||
use crate::cli::Cli;
|
||||
use crate::output::print_terminal;
|
||||
use crate::output::*;
|
||||
use crate::image_manipulation::*;
|
||||
|
||||
mod cli;
|
||||
mod image_manipulation;
|
||||
|
|
@ -10,7 +10,9 @@ mod ascii_manipulation;
|
|||
mod output;
|
||||
|
||||
//todo: general
|
||||
/* https://stackoverflow.com/questions/69981449/how-do-i-print-colored-text-to-the-terminal-in-rust
|
||||
/* Documentation
|
||||
* Readme
|
||||
* https://stackoverflow.com/questions/69981449/how-do-i-print-colored-text-to-the-terminal-in-rust
|
||||
*/
|
||||
|
||||
fn main() {
|
||||
|
|
@ -21,21 +23,33 @@ fn main() {
|
|||
cli.init();
|
||||
cli.validate();
|
||||
|
||||
let mut img = image_manipulation::open_image(cli.image);
|
||||
let w = image_manipulation::get_size(cli.width, img.width());
|
||||
//preprocess image
|
||||
let mut img = open_image(cli.image);
|
||||
img = resize_image(img, cli.full, cli.width);
|
||||
|
||||
//todo: change logic to include -full flag for max width, otherwise use max height?
|
||||
let h: u32 = (img.height() as f32 * w as f32 / img.width() as f32 * 0.5) as u32;
|
||||
img = img.resize_exact(w as u32, h, FilterType::CatmullRom);
|
||||
//converting to ASCII
|
||||
let out: Vec<String>;
|
||||
if cli.braille {
|
||||
out = to_braille_ascii(img);
|
||||
} else if cli.complex {
|
||||
out = to_complex_ascii(img);
|
||||
} else if let Some(map) = cli.map {
|
||||
out = to_custom_ascii(map, img);
|
||||
} else {
|
||||
out = to_simple_ascii(img);
|
||||
}
|
||||
|
||||
let out = to_simple_ascii(img);
|
||||
|
||||
print_terminal(out);
|
||||
//output
|
||||
if let Some(output) = cli.output {
|
||||
print_file(out, output);
|
||||
} else {
|
||||
print_terminal(out, cli.colour);
|
||||
}
|
||||
|
||||
//todo:
|
||||
/* function that converts image to braille (if -b)
|
||||
* something about printing in colour
|
||||
* a function to let the user define a custom map
|
||||
* output to file
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
pub fn print_terminal(ascii: Vec<String>) {
|
||||
pub fn print_terminal(ascii: Vec<String>, in_colour: bool) {
|
||||
for line in ascii {
|
||||
println!("{}", line);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_file(ascii: Vec<String>, out: PathBuf) {
|
||||
//todo: output
|
||||
//todo: this
|
||||
}
|
||||
Loading…
Reference in New Issue