Foo
This commit is contained in:
74
src/main.rs
74
src/main.rs
@ -1,6 +1,6 @@
|
||||
use clap::Parser;
|
||||
use eyre::{Context, ContextCompat, bail, eyre};
|
||||
use image::{DynamicImage, GrayImage, ImageReader, imageops::overlay};
|
||||
use eyre::{Context, ContextCompat, bail, ensure, eyre};
|
||||
use image::{DynamicImage, GrayAlphaImage, ImageReader, imageops::overlay};
|
||||
use nix::ioctl_write_ptr;
|
||||
use std::{
|
||||
fs::File,
|
||||
@ -49,23 +49,19 @@ ioctl_write_ptr!(
|
||||
DrmRockchipEbcOffScreen
|
||||
);
|
||||
|
||||
fn to_grayscale(path: &Path, image: DynamicImage) -> GrayImage {
|
||||
if let DynamicImage::ImageLuma8(image) = image {
|
||||
/// Convert [DynamicImage] into a [GrayAlphaImage].
|
||||
/// Note that we use [GrayAlphaImage] instead of `GrayImage` because we need the alpha channel to
|
||||
/// be able to add stamps.
|
||||
fn to_grayscale(path: &Path, image: DynamicImage) -> GrayAlphaImage {
|
||||
if let DynamicImage::ImageLumaA8(image) = image {
|
||||
return image;
|
||||
}
|
||||
|
||||
eprintln!("Image {path:?} is not 8-bit grayscale. Converting...");
|
||||
image.to_luma8()
|
||||
eprintln!("Image {path:?} is not 16-bit grayscale+alpha. Converting...");
|
||||
image.to_luma_alpha8()
|
||||
}
|
||||
|
||||
fn load_image(path: &Path) -> eyre::Result<GrayImage> {
|
||||
eprintln!("Opening image at {path:?}");
|
||||
|
||||
let image = ImageReader::open(path)?.decode()?;
|
||||
Ok(to_grayscale(path, image))
|
||||
}
|
||||
|
||||
fn load_wallpaper(path: &Path) -> eyre::Result<GrayImage> {
|
||||
fn load_wallpaper(path: &Path) -> eyre::Result<GrayAlphaImage> {
|
||||
eprintln!("Opening image at {path:?}");
|
||||
|
||||
let mut image = ImageReader::open(path)?.decode()?;
|
||||
@ -91,7 +87,7 @@ fn main() -> eyre::Result<()> {
|
||||
apply_stamp(stamp, &mut image)?;
|
||||
}
|
||||
|
||||
let pixels = image_to_offimage_buffer(image);
|
||||
let pixels = image_to_offimage_buffer(image)?;
|
||||
|
||||
let set_off_screen_data = DrmRockchipEbcOffScreen {
|
||||
info1: 0, // TODO: what is this?
|
||||
@ -109,23 +105,41 @@ fn main() -> eyre::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn image_to_offimage_buffer(image: image::ImageBuffer<image::Luma<u8>, Vec<u8>>) -> Vec<u8> {
|
||||
let mut pixels = image.into_vec();
|
||||
fn image_to_offimage_buffer(image: GrayAlphaImage) -> eyre::Result<Box<[u8; IOCTL_BUFFER_SIZE]>> {
|
||||
let mut buf: Box<[u8; IOCTL_BUFFER_SIZE]> = vec![0u8; IOCTL_BUFFER_SIZE]
|
||||
.into_boxed_slice()
|
||||
.try_into()
|
||||
.expect("Buffer is the correct size");
|
||||
|
||||
let image = image.into_vec();
|
||||
|
||||
ensure!(
|
||||
image.len() / 2 + 1 == IOCTL_BUFFER_SIZE,
|
||||
"Invalid size of image backing buffer. Bug?",
|
||||
);
|
||||
|
||||
// Iterate over pixels and copy them into `buf`.
|
||||
for (i, pixel) in image.chunks_exact(2).enumerate() {
|
||||
let &[gray, alpha] = pixel else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
// ignore the alpha channel.
|
||||
let _ = alpha;
|
||||
|
||||
// Convert 8-bit colorspace to 4-bits by truncating the 4 least significant bits.
|
||||
// Yes, this means that the most-significant 4 bits of each byte are unused.
|
||||
// Not idea why they designed it this way. Maybe it's faster?
|
||||
for pixel in &mut pixels {
|
||||
*pixel >>= 4;
|
||||
buf[i] = gray >> 4;
|
||||
}
|
||||
|
||||
// Add a null-terminator. No idea why this is necessary, but it is.
|
||||
pixels.push(0u8);
|
||||
|
||||
// Sanity check buffer length
|
||||
assert!(pixels.len() == IOCTL_BUFFER_SIZE);
|
||||
assert_eq!(buf.len(), IOCTL_BUFFER_SIZE);
|
||||
|
||||
pixels
|
||||
// Sanity-check that last byte is null.
|
||||
assert_eq!(buf.last(), Some(&0u8));
|
||||
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn parse_stamp(stamp: &str) -> Option<(i64, i64, &Path)> {
|
||||
@ -138,13 +152,21 @@ fn parse_stamp(stamp: &str) -> Option<(i64, i64, &Path)> {
|
||||
Some((x, y, path))
|
||||
}
|
||||
|
||||
fn apply_stamp(stamp: &str, onto: &mut GrayImage) -> eyre::Result<()> {
|
||||
fn apply_stamp(stamp: &str, onto: &mut GrayAlphaImage) -> eyre::Result<()> {
|
||||
let (x, y, path) =
|
||||
parse_stamp(stamp).wrap_err_with(|| eyre!("Invalid stamp format: {stamp:?}"))?;
|
||||
|
||||
let image = load_image(path)?;
|
||||
let image = load_stamp(path)?;
|
||||
|
||||
overlay(onto, &image, x, y);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_stamp(path: &Path) -> eyre::Result<GrayAlphaImage> {
|
||||
eprintln!("Opening image at {path:?}");
|
||||
|
||||
let image = ImageReader::open(path)?.decode()?;
|
||||
|
||||
Ok(to_grayscale(path, image))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user