Implement fading
This commit is contained in:
parent
bfb3b23d70
commit
581e4263fc
@ -1,28 +1,34 @@
|
|||||||
use crate::dimensions::{calculate_resize_dimensions, Dimensions};
|
use crate::dimensions::{calculate_resize_dimensions, Dimensions};
|
||||||
use image::ImageReader;
|
use image::ImageReader;
|
||||||
use macroquad::texture::Texture2D;
|
use macroquad::texture::{Image, Texture2D};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
pub struct ImageProvider<'a> {
|
pub struct ImageProvider<'a> {
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
directory_it: Box<dyn Iterator<Item = Result<walkdir::DirEntry, walkdir::Error>>>,
|
directory_it: Box<dyn Iterator<Item = Result<walkdir::DirEntry, walkdir::Error>>>,
|
||||||
|
image: Option<Image>,
|
||||||
texture: Option<Texture2D>,
|
texture: Option<Texture2D>,
|
||||||
|
texture_darkening_factor: f32,
|
||||||
screen_dimension: Dimensions,
|
screen_dimension: Dimensions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ImageProvider<'a> {
|
impl<'a> ImageProvider<'a> {
|
||||||
pub fn new(screen_dimension: Dimensions, path: &'a Path) -> Self {
|
pub fn new(screen_dimension: Dimensions, path: &'a Path) -> Self {
|
||||||
Self {
|
Self {
|
||||||
directory_it: Box::new(WalkDir::new(&path).max_open(8).into_iter()),
|
directory_it: Box::new(WalkDir::new(path).max_open(8).into_iter()),
|
||||||
|
image: None,
|
||||||
texture: None,
|
texture: None,
|
||||||
screen_dimension,
|
screen_dimension,
|
||||||
path,
|
path,
|
||||||
|
texture_darkening_factor: 1.0f32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_next_image(&mut self) -> anyhow::Result<()> {
|
pub fn load_next_image(&mut self) -> anyhow::Result<()> {
|
||||||
let path = self.get_next_image_path()?;
|
let path = self.get_next_image_path()?;
|
||||||
|
println!("Loading image: {path:?}");
|
||||||
|
let now = chrono::Local::now().time();
|
||||||
let image = ImageReader::open(path)?.decode()?;
|
let image = ImageReader::open(path)?.decode()?;
|
||||||
|
|
||||||
let image_dim = Dimensions::new(image.width(), image.height());
|
let image_dim = Dimensions::new(image.width(), image.height());
|
||||||
@ -34,19 +40,51 @@ impl<'a> ImageProvider<'a> {
|
|||||||
image::imageops::FilterType::Lanczos3,
|
image::imageops::FilterType::Lanczos3,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.texture = Some(Texture2D::from_rgba8(
|
let mut i = Image::empty();
|
||||||
image.width().try_into()?,
|
i.width = image.width() as u16;
|
||||||
image.height().try_into()?,
|
i.height = image.height() as u16;
|
||||||
&image.into_rgba8(),
|
i.bytes = image.into_rgba8().into_raw();
|
||||||
));
|
|
||||||
|
self.image = Some(i);
|
||||||
|
self.texture = None;
|
||||||
|
|
||||||
|
let elapsed = chrono::Local::now().time() - now;
|
||||||
|
println!(
|
||||||
|
"Loading image elapsed time: {}ms",
|
||||||
|
elapsed.num_milliseconds()
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_current_texture(&self) -> anyhow::Result<&Texture2D> {
|
pub fn get_current_texture(&mut self, darkening_factor: f32) -> anyhow::Result<&Texture2D> {
|
||||||
self.texture
|
if (darkening_factor - self.texture_darkening_factor).abs() > f32::EPSILON {
|
||||||
.as_ref()
|
self.texture_darkening_factor = darkening_factor;
|
||||||
.ok_or_else(|| anyhow::anyhow!("No image loaded"))
|
self.texture = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.texture.is_none() {
|
||||||
|
let darken_image = self
|
||||||
|
.image
|
||||||
|
.as_ref()
|
||||||
|
.map(|i| {
|
||||||
|
let mut darken_image = i.clone();
|
||||||
|
darken_image.bytes.iter_mut().for_each(|b| {
|
||||||
|
*b = (f32::from(*b) * darkening_factor) as u8;
|
||||||
|
});
|
||||||
|
darken_image
|
||||||
|
})
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("No image loaded"))?;
|
||||||
|
|
||||||
|
let text =
|
||||||
|
Texture2D::from_rgba8(darken_image.width, darken_image.height, &darken_image.bytes);
|
||||||
|
self.texture = Some(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.texture {
|
||||||
|
Some(ref texture) => Ok(texture),
|
||||||
|
None => Err(anyhow::anyhow!("No texture available")),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_next_image_path(&mut self) -> anyhow::Result<PathBuf> {
|
fn get_next_image_path(&mut self) -> anyhow::Result<PathBuf> {
|
||||||
@ -65,7 +103,7 @@ impl<'a> ImageProvider<'a> {
|
|||||||
Some(Err(e)) => return Err(e.into()),
|
Some(Err(e)) => return Err(e.into()),
|
||||||
None => {
|
None => {
|
||||||
// Reset the iterator when we reach the end
|
// Reset the iterator when we reach the end
|
||||||
self.directory_it = Box::new(WalkDir::new(&self.path).max_open(8).into_iter());
|
self.directory_it = Box::new(WalkDir::new(self.path).max_open(8).into_iter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
src/main.rs
38
src/main.rs
@ -31,11 +31,6 @@ fn display_image_centered(texture: &Texture2D) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Mode {
|
|
||||||
Black,
|
|
||||||
Displayed,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macroquad::main(window_conf)]
|
#[macroquad::main(window_conf)]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
let settings = settings::Settings::new("settings.yml".into())?;
|
let settings = settings::Settings::new("settings.yml".into())?;
|
||||||
@ -51,37 +46,38 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let now = chrono::Local::now().time();
|
let now = chrono::Local::now().time();
|
||||||
|
let start_fading = chrono::NaiveTime::from_hms_opt(22, 45, 0).unwrap();
|
||||||
let go_to_bed = chrono::NaiveTime::from_hms_opt(23, 0, 0).unwrap();
|
let go_to_bed = chrono::NaiveTime::from_hms_opt(23, 0, 0).unwrap();
|
||||||
let wake_up = chrono::NaiveTime::from_hms_opt(9, 0, 0).unwrap();
|
let wake_up = chrono::NaiveTime::from_hms_opt(9, 0, 0).unwrap();
|
||||||
|
let full_brightness = chrono::NaiveTime::from_hms_opt(9, 15, 0).unwrap();
|
||||||
|
|
||||||
let mode = if now < go_to_bed && now > wake_up {
|
let darkening_factor = if now < start_fading && now > full_brightness {
|
||||||
Mode::Displayed
|
1.0f32
|
||||||
|
} else if now > start_fading && now < go_to_bed {
|
||||||
|
(go_to_bed - now).num_seconds() as f32 / (go_to_bed - start_fading).num_seconds() as f32
|
||||||
|
} else if now > wake_up && now < full_brightness {
|
||||||
|
(now - wake_up).num_seconds() as f32 / (full_brightness - wake_up).num_seconds() as f32
|
||||||
} else {
|
} else {
|
||||||
Mode::Black
|
0.0f32
|
||||||
};
|
};
|
||||||
|
|
||||||
match mode {
|
display_frame(&mut provider, darkening_factor)?;
|
||||||
Mode::Black => {
|
if time.elapsed() > settings.duration {
|
||||||
clear_background(BLACK);
|
if darkening_factor > 0.0f32 {
|
||||||
}
|
provider.load_next_image()?;
|
||||||
Mode::Displayed => {
|
|
||||||
display_frame(&provider)?;
|
|
||||||
if time.elapsed() > settings.duration {
|
|
||||||
provider.load_next_image()?;
|
|
||||||
time = Instant::now();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
time = Instant::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
thread::sleep(Duration::from_millis(250));
|
thread::sleep(Duration::from_millis(400));
|
||||||
next_frame().await;
|
next_frame().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_frame(provider: &ImageProvider) -> anyhow::Result<()> {
|
fn display_frame(provider: &mut ImageProvider, darkening_factor: f32) -> anyhow::Result<()> {
|
||||||
let image = provider.get_current_texture()?;
|
let image = provider.get_current_texture(darkening_factor)?;
|
||||||
clear_background(BLACK);
|
clear_background(BLACK);
|
||||||
display_image_centered(image);
|
display_image_centered(image);
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ impl Settings {
|
|||||||
.add_source(File::from(settings_file))
|
.add_source(File::from(settings_file))
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
let photo_path = settings.get_string("photo_path")?.try_into()?;
|
let photo_path = settings.get_string("photo_path")?.into();
|
||||||
let duration = settings.get_int("duration")?;
|
let duration = settings.get_int("duration")?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user