Initial commit
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
/target
 | 
			
		||||
							
								
								
									
										1196
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1196
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										10
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "yabinary"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
edition = "2021"
 | 
			
		||||
 | 
			
		||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
clap = { version = "4.5.9", features = ["derive"] }
 | 
			
		||||
image = "0.25.2"
 | 
			
		||||
							
								
								
									
										107
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
			
		||||
use clap::{Parser, ValueEnum};
 | 
			
		||||
use image::ImageReader;
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::{Read, Write};
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
 | 
			
		||||
const WHITE: u8 = 0x88;
 | 
			
		||||
const BLACK: u8 = 0xCC;
 | 
			
		||||
const SCREEN_WIDTH: usize = 16;
 | 
			
		||||
 | 
			
		||||
#[derive(ValueEnum, Clone, Copy)]
 | 
			
		||||
enum Color {
 | 
			
		||||
    White,
 | 
			
		||||
    Black,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Color {
 | 
			
		||||
    fn as_bytes(&self) -> u8 {
 | 
			
		||||
        match self {
 | 
			
		||||
            Color::White => WHITE,
 | 
			
		||||
            Color::Black => BLACK,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl std::fmt::Display for Color {
 | 
			
		||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            Self::White => f.write_str("white"),
 | 
			
		||||
            Self::Black => f.write_str("black"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Parser)]
 | 
			
		||||
struct Cli {
 | 
			
		||||
    #[arg(long, requires_all=["header_lines"])]
 | 
			
		||||
    header_from: Option<PathBuf>,
 | 
			
		||||
 | 
			
		||||
    #[arg(long)]
 | 
			
		||||
    header_lines: Option<usize>,
 | 
			
		||||
 | 
			
		||||
    image: PathBuf,
 | 
			
		||||
 | 
			
		||||
    #[arg(long, requires_all=["footer_lines"])]
 | 
			
		||||
    footer_from: Option<PathBuf>,
 | 
			
		||||
 | 
			
		||||
    #[arg(long)]
 | 
			
		||||
    footer_lines: Option<usize>,
 | 
			
		||||
 | 
			
		||||
    #[arg(long, default_value_t = Color::White)]
 | 
			
		||||
    background: Color,
 | 
			
		||||
 | 
			
		||||
    output: PathBuf,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
 | 
			
		||||
    let c = Cli::parse();
 | 
			
		||||
 | 
			
		||||
    let img = ImageReader::open(c.image)?.decode()?;
 | 
			
		||||
 | 
			
		||||
    if SCREEN_WIDTH < img.width() as usize {
 | 
			
		||||
        println!(
 | 
			
		||||
            "WARN: {} pixels are ignored",
 | 
			
		||||
            img.width() as usize - SCREEN_WIDTH
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut output = File::create(&c.output)?;
 | 
			
		||||
 | 
			
		||||
    if let Some(header_path) = c.header_from {
 | 
			
		||||
        let mut buffer = vec![0; c.header_lines.unwrap() * SCREEN_WIDTH];
 | 
			
		||||
        File::open(header_path)?.read_exact(&mut buffer)?;
 | 
			
		||||
        output.write(&buffer)?;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    for row in img.to_rgba8().rows() {
 | 
			
		||||
        let buffer: Vec<_> = (0..SCREEN_WIDTH)
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .zip(
 | 
			
		||||
                row.into_iter()
 | 
			
		||||
                    .map(|v| {
 | 
			
		||||
                        let brightness =
 | 
			
		||||
                            (v[0] as f32 / 256.0 + v[1] as f32 / 256.0 + v[2] as f32 / 256.0) / 3.0;
 | 
			
		||||
 | 
			
		||||
                        if brightness > 0.2 {
 | 
			
		||||
                            Color::White
 | 
			
		||||
                        } else {
 | 
			
		||||
                            Color::Black
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
                    .chain(std::iter::repeat(c.background)),
 | 
			
		||||
            )
 | 
			
		||||
            .map(|(_, color)| color.as_bytes())
 | 
			
		||||
            .collect();
 | 
			
		||||
 | 
			
		||||
        output.write(&buffer)?;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if let Some(footer_path) = c.footer_from {
 | 
			
		||||
        let mut buffer = vec![0; c.footer_lines.unwrap() * SCREEN_WIDTH];
 | 
			
		||||
        File::open(footer_path)?.read_exact(&mut buffer)?;
 | 
			
		||||
        output.write(&buffer)?;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user