init
This commit is contained in:
commit
b8bf240101
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
test.jpg
|
224
Cargo.lock
generated
Normal file
224
Cargo.lock
generated
Normal file
|
@ -0,0 +1,224 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ASCIIfryer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"argh",
|
||||
"image",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "argh"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab257697eb9496bf75526f0217b5ed64636a9cfafa78b8365c71bd283fcef93e"
|
||||
dependencies = [
|
||||
"argh_derive",
|
||||
"argh_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh_derive"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b382dbd3288e053331f03399e1db106c9fb0d8562ad62cb04859ae926f324fa6"
|
||||
dependencies = [
|
||||
"argh_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh_shared"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64cb94155d965e3d37ffbbe7cc5b82c3dd79dd33bd48e536f73d2cfb8d85506f"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fdeflate"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10"
|
||||
dependencies = [
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.24.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder",
|
||||
"color_quant",
|
||||
"jpeg-decoder",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jpeg-decoder"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.17.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crc32fast",
|
||||
"fdeflate",
|
||||
"flate2",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
24
Cargo.toml
Normal file
24
Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "ASCIIfryer"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
argh = "0.1.10"
|
||||
image = { version = "0.24.6", default-features = false, features = [
|
||||
"jpeg",
|
||||
"png",
|
||||
"bmp",
|
||||
] }
|
||||
|
||||
[profile.dev]
|
||||
lto = true
|
||||
opt-level = 1
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 3
|
98
src/main.rs
Normal file
98
src/main.rs
Normal file
|
@ -0,0 +1,98 @@
|
|||
#![allow(non_snake_case)]
|
||||
use argh::FromArgs;
|
||||
use image::{self, imageops, Rgb};
|
||||
use std::fs;
|
||||
use std::io::{self, BufRead, BufReader, Read};
|
||||
#[derive(FromArgs)]
|
||||
/// Convert images to ascii.
|
||||
/// works with Jpeg, PNG, and BMP formats
|
||||
struct ASCIIfryer {
|
||||
/// width in columns of output ASCII
|
||||
#[argh(option, short = 'w', default = "40")]
|
||||
width: u32,
|
||||
/// height in rows of output ASCII
|
||||
#[argh(option, short = 'h', default = "40")]
|
||||
height: u32,
|
||||
/// palette of ASCII characters to render image with
|
||||
#[argh(option, short = 'p', default = "String::from(\".,-+=oO0#\")")]
|
||||
palette: String,
|
||||
|
||||
/// read image from standard input
|
||||
#[argh(switch, short = 's')]
|
||||
stdin: bool,
|
||||
|
||||
/// input file path (jpeg/png/bmp)
|
||||
#[argh(positional)]
|
||||
input: Option<String>,
|
||||
}
|
||||
|
||||
struct Charset {
|
||||
characters: String,
|
||||
mult: f32,
|
||||
}
|
||||
impl Charset {
|
||||
fn new(characters: &str) -> Self {
|
||||
let characters = characters.to_owned();
|
||||
let mult = characters.chars().count() as f32 / (255.0 * 3.0);
|
||||
|
||||
Charset { characters, mult }
|
||||
}
|
||||
fn convert_pixel(&self, px: &Rgb<u8>) -> char {
|
||||
let p = px[0] as u16 + px[1] as u16 + px[2] as u16;
|
||||
let scaled = p as f32 * self.mult;
|
||||
|
||||
let scaled = scaled.floor() as usize;
|
||||
self.characters.chars().nth(scaled).unwrap_or('X')
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), &'static str> {
|
||||
// Args
|
||||
let settings: ASCIIfryer = argh::from_env();
|
||||
|
||||
// Specifying whether reading from file or from stdin
|
||||
// invalid states panic
|
||||
let mut reader: Box<dyn BufRead> = match (settings.input, settings.stdin) {
|
||||
(Some(filename), false) => Box::new(BufReader::new(
|
||||
fs::File::open(filename).expect("Could not read file"),
|
||||
)),
|
||||
(None, true) => Box::new(BufReader::new(io::stdin().lock())),
|
||||
(Some(_), true) => {
|
||||
return Err("Can not load image from file and stdin. Use one or the other");
|
||||
}
|
||||
(None, false) => {
|
||||
return Err("No input provided");
|
||||
}
|
||||
};
|
||||
let mut file = vec![];
|
||||
// Load data from file/stdin
|
||||
reader
|
||||
.read_to_end(&mut file)
|
||||
.expect("Error while reading input");
|
||||
// Parse data to image
|
||||
let image = image::load_from_memory(&file)
|
||||
.expect("Could not load as image. PNG, BMP, and JPEG are supported");
|
||||
// Downscale image to reasonable size
|
||||
let image = image.resize(
|
||||
settings.width,
|
||||
settings.height,
|
||||
imageops::FilterType::Nearest,
|
||||
);
|
||||
// Convert image into buffer of Rgb<u8> (pixels)
|
||||
let buffer = image
|
||||
.as_rgb8()
|
||||
.expect("Could not extract 8-bit RGB buffer from image");
|
||||
|
||||
let width = image.width();
|
||||
let charset = Charset::new(&settings.palette);
|
||||
|
||||
// Iterate through each pixel and print resulting ASCII
|
||||
for (col, _, pix) in buffer.enumerate_pixels() {
|
||||
let symbol = charset.convert_pixel(pix);
|
||||
print!("{symbol}");
|
||||
if col == width - 1 {
|
||||
println!();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in a new issue