braille output

This commit is contained in:
mehbark 2026-02-04 02:22:13 -05:00
parent f452a6e869
commit 1d209d6ba1

View file

@ -1,6 +1,16 @@
use std::{env, error::Error};
use std::{
env,
error::Error,
io::{self, BufWriter, Write},
};
use image::{DynamicImage, ImageReader, Luma};
use image::{ImageReader, Luma};
const BRAILLE_FIRST_BYTE: u8 = 0xe2;
const BRAILLE_SECOND_BYTE: u8 = 0xa0;
const BRAILLE_HEIGHT: u8 = 4;
const BRAILLE_BIT_MAPPING: [[u8; BRAILLE_HEIGHT as usize]; 2] =
[[0x1, 0x2, 0x4, 0x40], [0x8, 0x10, 0x20, 0x80]];
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
fn main() -> Result<(), Box<dyn Error>> {
@ -12,16 +22,25 @@ fn main() -> Result<(), Box<dyn Error>> {
];
let src = env::args().nth(1).ok_or("i need a source path")?;
let out_path = env::args().nth(2).ok_or("i need an output path")?;
let mut img = ImageReader::open(&src)?.decode()?.to_luma32f();
let mut out = img.clone();
let mut out = BufWriter::new(io::stdout().lock());
let mut output_line = vec![0u8; img.width().div_ceil(2) as usize];
let mut lines_buffered: u8 = 0;
for y in 0..img.height() {
for x in 0..img.width() {
let old_pixel = img.get_pixel(x, y);
let old_luma = old_pixel.0[0];
let luma = if old_luma < 0.5 { 0. } else { 1. };
let white = old_luma > 0.5;
let luma = if white { 1. } else { 0. };
out.put_pixel(x, y, Luma([luma]));
// white pixels are filled because i'm targetting a dark mode site
if white {
output_line[(x / 2) as usize] |=
BRAILLE_BIT_MAPPING[(x % 2) as usize][(y % 4) as usize];
}
let error = old_luma - luma;
for (dx, dy, quant) in kernel {
@ -39,7 +58,29 @@ fn main() -> Result<(), Box<dyn Error>> {
img.put_pixel(x, y, Luma([corrected]));
}
}
lines_buffered += 1;
if lines_buffered == BRAILLE_HEIGHT {
for byte in &output_line {
if *byte == 0 {
out.write_all(b" ").unwrap();
continue;
}
let upper_2 = byte >> 6;
let lower_6 = byte & 0b111_111;
out.write_all(&[
BRAILLE_FIRST_BYTE,
BRAILLE_SECOND_BYTE | upper_2,
0b10_000000 | lower_6,
])
.unwrap();
}
out.write_all(b"\n").unwrap();
output_line.fill(0);
lines_buffered = 0;
}
}
DynamicImage::from(out).into_luma8().save(out_path)?;
Ok(())
}