Load any type of image

This commit is contained in:
2025-07-14 17:03:51 +02:00
parent 983008b01f
commit 76d9811291
3 changed files with 160 additions and 28 deletions

View File

@ -1,12 +1,12 @@
//! Image format is a buffer of `SCREEN_W * SCREEN_H + 1` bytes.
//! The 4 least-significant bits of each byte is one pixel. The 4 most-significant bits are unused.
//! Images are stored in landscape format, i.e. the first byte is the top-left pixel, and the
//! second-to-last byte is the bottom-right pixel. The final byte is a null-terminator, and must be 0.
use clap::Parser;
use eyre::{Context, ensure, eyre};
use eyre::{Context, bail, eyre};
use image::ImageReader;
use nix::ioctl_write_ptr;
use std::{
fs::File,
io::Read,
os::fd::AsRawFd,
path::{Path, PathBuf},
};
use std::{fs::File, os::fd::AsRawFd, path::PathBuf};
#[derive(Parser)]
struct Opt {
@ -14,11 +14,10 @@ struct Opt {
pub path: PathBuf,
}
const SCREEN_W: usize = 1404;
const SCREEN_H: usize = 1872;
const SCREEN_W: usize = 1872;
const SCREEN_H: usize = 1404;
const BITS_PER_PIXEL: usize = 4;
const FILE_SIZE: usize = SCREEN_W * SCREEN_H * BITS_PER_PIXEL / 8;
const FILE_SIZE: usize = SCREEN_W * SCREEN_H + 1;
// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
// const SPI_IOC_TYPE_MESSAGE: u8 = 0;
@ -46,12 +45,29 @@ fn main() -> eyre::Result<()> {
let opt = Opt::parse();
color_eyre::install()?;
let image =
read_file(&opt.path).wrap_err_with(|| eyre!("Failed to read file at {:?}", opt.path))?;
let mut image = ImageReader::open(&opt.path)?.decode()?;
let image_dimensions = (image.width() as usize, image.height() as usize);
match image_dimensions {
(SCREEN_W, SCREEN_H) => {}
(SCREEN_H, SCREEN_W) => image = image.rotate270(),
_ => bail!("Image must be {SCREEN_W}x{SCREEN_H}"),
}
let image = image.to_luma8();
let mut pixels = image.into_vec();
for pixel in &mut pixels {
*pixel >>= 4; // convert 8-bit colorspace to 4-bits.
}
pixels.push(0u8); // add a null-terminator
// sanity check buffer length
assert!(pixels.len() == FILE_SIZE);
let set_off_screen_data = DrmRockchipEbcOffScreen {
info1: 0, // TODO: what is this?
ptr_screen_content: image.as_ptr(),
ptr_screen_content: pixels.as_ptr(),
};
let driver_file = File::options()
@ -64,16 +80,3 @@ fn main() -> eyre::Result<()> {
Ok(())
}
fn read_file(path: &Path) -> eyre::Result<Vec<u8>> {
let mut file = File::open(path)?;
let mut buf = vec![0u8; FILE_SIZE];
file.read_exact(&mut buf[..])
.wrap_err_with(|| eyre!("Expected a raw image file, of exactly {FILE_SIZE} bytes"))?;
// Try to read a single byte. If n != 0, it means the file was larger than FILE_SIZE
let n = file.read(&mut [0u8])?;
ensure!(n == 0, "File must be exacly {FILE_SIZE} bytes long");
Ok(buf)
}