jp2a ripoff
take a write
| -rw-r--r-- | Cargo.lock | 125 | ||||
| -rw-r--r-- | Cargo.toml | 9 | ||||
| -rw-r--r-- | src/main.rs | 7 | ||||
| -rw-r--r-- | src/picture.rs | 42 |
4 files changed, 28 insertions, 155 deletions
@@ -77,9 +77,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" [[package]] name = "byteorder" @@ -163,55 +163,6 @@ dependencies = [ ] [[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "either" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" - -[[package]] name = "errno" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -259,24 +210,15 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" [[package]] name = "image" -version = "0.24.6" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" dependencies = [ "bytemuck", "byteorder", @@ -293,7 +235,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "libc", "windows-sys", ] @@ -304,7 +246,7 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "io-lifetimes", "rustix", "windows-sys", @@ -315,9 +257,6 @@ name = "jpeg-decoder" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" -dependencies = [ - "rayon", -] [[package]] name = "libc" @@ -332,15 +271,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] - -[[package]] name = "miniz_oxide" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -373,24 +303,14 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi 0.2.6", - "libc", -] - -[[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -403,7 +323,6 @@ dependencies = [ "anyhow", "clap", "image", - "rayon", "rgb2ansi256", ] @@ -439,28 +358,6 @@ dependencies = [ ] [[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] name = "rgb2ansi256" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -481,12 +378,6 @@ dependencies = [ ] [[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] name = "simd-adler32" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -9,17 +9,12 @@ edition = "2021" anyhow = "1.0.71" clap = { version = "4.3.3", features = ["derive"] } image = { version = "0.24.6", features = [ - "png", - "jpeg_rayon", + "png", + "jpeg", ], default-features = false } -rayon = { version = "1.7.0", optional = true } rgb2ansi256 = "0.1.1" [profile.release] lto = true opt-level = 3 strip = true - -[features] -rayon = ["dep:rayon"] -default = [] diff --git a/src/main.rs b/src/main.rs index 58c844e..e4185f9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use clap::Parser; -use picture::*; -use std::path::PathBuf; +use picture::ToText; +use std::{io::BufWriter, path::PathBuf}; mod picture; #[derive(Parser)] @@ -14,6 +14,7 @@ struct Args { fn main() -> anyhow::Result<()> { let args = Args::parse(); let p = image::open(args.from)?; - println!("{}", p.text(" ...,:clodxkO0KXM".as_bytes())); + let mut s = BufWriter::new(std::io::stdout().lock()); + p.text(b" ...,:clodxkO0KXM", &mut s)?; Ok(()) } diff --git a/src/picture.rs b/src/picture.rs index 8fa1af8..04de046 100644 --- a/src/picture.rs +++ b/src/picture.rs @@ -1,7 +1,6 @@ use image::{DynamicImage, GenericImageView, Pixel, Rgb}; -#[cfg(rayon)] -use rayon::prelude::*; use rgb2ansi256::rgb_to_ansi256; +use std::io::{self, Write}; macro_rules! fg { ($color:expr,$c:expr) => { @@ -10,19 +9,13 @@ macro_rules! fg { } pub trait ToText { - fn text(&self, palette: &[u8]) -> String; + fn text(&self, palette: &[u8], w: &mut impl Write) -> io::Result<()>; } impl ToText for DynamicImage { - fn text(&self, palette: &[u8]) -> String { + fn text(&self, palette: &[u8], w: &mut impl Write) -> io::Result<()> { let p_len = (palette.len() - 1) as f32; - let mut output: Vec<String> = vec![]; let height = (self.height() / 2) as usize; - output.resize(height, String::new()); - #[cfg(not(rayon))] - let iter = output.iter_mut(); - #[cfg(rayon)] - let iter = output.par_iter_mut(); - iter.enumerate().for_each(|(mut y, output)| { + for mut y in 0..height { y <<= 1; let mut last_p: Option<u8> = None; for x in 0..self.width() { @@ -32,19 +25,25 @@ impl ToText for DynamicImage { let pos = (p_len * y).round(); let i: usize = (pos * a).round() as usize; let ch = palette[i] as char; + if y <= 0.01 { + write!(w, "{ch}")?; + continue; + } // must round it into ansi256 or we will get duplicates let color = p.to_rgb().ansi_256(); if let Some(last) = last_p { if last == color { - output.push(ch); + write!(w, "{ch}")?; continue; } } + last_p = Some(color); - output.push_str(&fg!(color, ch)); + write!(w, "{}", fg!(color, ch))?; } - }); - output.join("\n") + writeln!(w)?; + } + Ok(()) } } @@ -61,16 +60,3 @@ impl Ansi256 for Rgb<u8> { fn i2range(i: u8) -> f32 { (i as f32 / u8::MAX as f32).clamp(0.0, 1.0) } - -#[test] -fn ansi_color() { - macro_rules! test { - ($c:expr, $expect:expr) => {{ - let args: [u8; 3] = $c; - assert_eq!(Rgb::from(args).ansi_256(), $expect) - }}; - } - test!([0, 0, 255], 21); - test!([0, 255, 0], 46); - test!([255, 0, 0], 196); -} |