fast image operations
Diffstat (limited to 'src/term/bloc.rs')
-rw-r--r--src/term/bloc.rs70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/term/bloc.rs b/src/term/bloc.rs
new file mode 100644
index 0000000..2be3e25
--- /dev/null
+++ b/src/term/bloc.rs
@@ -0,0 +1,70 @@
+use crate::{pixels::convert::PFrom, Image};
+use std::fmt::{Debug, Display, Formatter, Result, Write};
+
+/// Colored `â–€`s. The simple, stupid solution.
+/// May be too big for your terminal.
+pub struct Bloc<T: AsRef<[u8]>, const N: usize>(pub Image<T, N>);
+impl<T: AsRef<[u8]>, const N: usize> std::ops::Deref for Bloc<T, N> {
+ type Target = Image<T, N>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T: AsRef<[u8]>, const N: usize> Display for Bloc<T, N>
+where
+ [u8; 3]: PFrom<N>,
+{
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ self.write(f)
+ }
+}
+
+impl<T: AsRef<[u8]>, const N: usize> Debug for Bloc<T, N>
+where
+ [u8; 3]: PFrom<N>,
+{
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ self.write(f)
+ }
+}
+
+impl<T: AsRef<[u8]>, const N: usize> Bloc<T, N>
+where
+ [u8; 3]: PFrom<N>,
+{
+ /// Write out halfblocks.
+ pub fn write(&self, to: &mut impl Write) -> Result {
+ macro_rules! c {
+ (fg $fg:expr, bg $bg:expr) => {{
+ let [fr, fg, fb] = $fg;
+ let [br, bg, bb] = $bg;
+ write!(to, "\x1b[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}mâ–€")?;
+ }};
+ }
+ // TODO: scale 2 fit
+ for [a, b] in self
+ .flatten()
+ .chunks_exact(self.width() as _)
+ .map(|x| x.iter().copied().map(<[u8; 3] as PFrom<N>>::pfrom))
+ .array_chunks::<2>()
+ {
+ for (a, b) in a.zip(b) {
+ c! { fg a, bg b };
+ }
+ writeln!(to)?;
+ }
+ write!(to, "\x1b[0m")?;
+ Ok(())
+ }
+}
+
+#[test]
+fn test() {
+ let x = Image::<_, 3>::open("tdata/small_cat.png");
+ use std::hash::Hasher;
+ let mut h = std::hash::DefaultHasher::new();
+ h.write(Bloc(x).to_string().as_bytes());
+ assert_eq!(h.finish(), 0x6546104ffee16f77);
+}