Compare commits
2 Commits
08af03380c
...
cc0038c1cd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc0038c1cd | ||
|
|
f0ba4e47d9 |
40
Cargo.toml
40
Cargo.toml
@ -3,6 +3,46 @@ name = "photo-frame"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lints.rust]
|
||||
unsafe_code = "forbid"
|
||||
|
||||
[lints.clippy]
|
||||
all = "deny"
|
||||
nursery = "deny"
|
||||
pedantic = "deny"
|
||||
complexity = "deny"
|
||||
perf = "deny"
|
||||
style = "deny"
|
||||
suspicious = "deny"
|
||||
unwrap_in_result = { level = "deny", priority = 1}
|
||||
unwrap_used = { level = "deny", priority = 1}
|
||||
expect_used = { level = "deny", priority = 1}
|
||||
verbose_file_reads = { level = "deny", priority = 1}
|
||||
unneeded_field_pattern = { level = "deny", priority = 1}
|
||||
tests_outside_test_module = { level = "deny", priority = 1}
|
||||
shadow_same = { level = "deny", priority = 1}
|
||||
same_name_method = { level = "deny", priority = 1}
|
||||
rest_pat_in_fully_bound_structs = { level = "deny", priority = 1}
|
||||
redundant_type_annotations = { level = "deny", priority = 1}
|
||||
panic = { level = "deny", priority = 1}
|
||||
# Allow some annoying lints
|
||||
module_name_repetitions = {level = "allow", priority = 1}
|
||||
missing_errors_doc = {level = "allow", priority = 1}
|
||||
needless_pass_by_value = {level = "allow", priority = 1}
|
||||
or_fun_call = {level = "allow", priority = 1}
|
||||
implicit_hasher = {level = "allow", priority = 1}
|
||||
significant_drop_tightening = {level = "allow", priority = 1}
|
||||
cast_possible_truncation = {level = "allow", priority = 1}
|
||||
cast_sign_loss = {level = "allow", priority = 1}
|
||||
cast_precision_loss = {level = "allow", priority = 1}
|
||||
future_not_send = {level = "allow", priority = 1}
|
||||
|
||||
[profile.release]
|
||||
strip = true
|
||||
lto = "thin"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.93"
|
||||
image = "0.25.4"
|
||||
macroquad = { version = "0.4.13" }
|
||||
walkdir = "2.5.0"
|
||||
|
||||
@ -5,11 +5,11 @@ pub struct Dimensions {
|
||||
}
|
||||
|
||||
impl Dimensions {
|
||||
pub fn new(width: u32, height: u32) -> Self {
|
||||
pub const fn new(width: u32, height: u32) -> Self {
|
||||
Self { width, height }
|
||||
}
|
||||
|
||||
pub fn aspect_ratio(&self) -> f32 {
|
||||
pub const fn aspect_ratio(self) -> f32 {
|
||||
self.width as f32 / self.height as f32
|
||||
}
|
||||
}
|
||||
|
||||
73
src/image_provider.rs
Normal file
73
src/image_provider.rs
Normal file
@ -0,0 +1,73 @@
|
||||
use crate::dimensions::{calculate_resize_dimensions, Dimensions};
|
||||
use image::ImageReader;
|
||||
use macroquad::texture::Texture2D;
|
||||
use std::path::PathBuf;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
pub struct ImageProvider {
|
||||
path: PathBuf,
|
||||
directory_it: Box<dyn Iterator<Item = Result<walkdir::DirEntry, walkdir::Error>>>,
|
||||
texture: Option<Texture2D>,
|
||||
screen_dimension: Dimensions,
|
||||
}
|
||||
|
||||
impl ImageProvider {
|
||||
pub fn new(screen_dimension: Dimensions, path: PathBuf) -> Self {
|
||||
Self {
|
||||
directory_it: Box::new(WalkDir::new(&path).max_open(8).into_iter()),
|
||||
texture: None,
|
||||
screen_dimension,
|
||||
path,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_next_image(&mut self) -> anyhow::Result<()> {
|
||||
let path = self.get_next_image_path()?;
|
||||
let image = ImageReader::open(path)?.decode()?;
|
||||
|
||||
let image_dim = Dimensions::new(image.width(), image.height());
|
||||
let new_dim = calculate_resize_dimensions(self.screen_dimension, image_dim);
|
||||
|
||||
let image = image.resize(
|
||||
new_dim.width,
|
||||
new_dim.height,
|
||||
image::imageops::FilterType::Lanczos3,
|
||||
);
|
||||
|
||||
self.texture = Some(Texture2D::from_rgba8(
|
||||
image.width().try_into()?,
|
||||
image.height().try_into()?,
|
||||
&image.into_rgba8(),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_current_texture(&self) -> anyhow::Result<&Texture2D> {
|
||||
self.texture
|
||||
.as_ref()
|
||||
.ok_or_else(|| anyhow::anyhow!("No image loaded"))
|
||||
}
|
||||
|
||||
fn get_next_image_path(&mut self) -> anyhow::Result<PathBuf> {
|
||||
loop {
|
||||
match self.directory_it.next() {
|
||||
Some(Ok(entry)) => {
|
||||
if entry.file_type().is_file()
|
||||
&& entry
|
||||
.path()
|
||||
.extension()
|
||||
.is_some_and(|ext| ext == "jpg" || ext == "jpeg" || ext == "png")
|
||||
{
|
||||
return Ok(entry.path().to_path_buf());
|
||||
}
|
||||
}
|
||||
Some(Err(e)) => return Err(e.into()),
|
||||
None => {
|
||||
// Reset the iterator when we reach the end
|
||||
self.directory_it = Box::new(WalkDir::new(&self.path).max_open(8).into_iter());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
src/main.rs
58
src/main.rs
@ -1,8 +1,13 @@
|
||||
use dimensions::{calculate_resize_dimensions, Dimensions};
|
||||
use image::ImageReader;
|
||||
use dimensions::Dimensions;
|
||||
use image_provider::ImageProvider;
|
||||
use macroquad::prelude::*;
|
||||
use std::{
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
mod dimensions;
|
||||
mod image_provider;
|
||||
|
||||
fn window_conf() -> Conf {
|
||||
Conf {
|
||||
@ -14,11 +19,11 @@ fn window_conf() -> Conf {
|
||||
}
|
||||
}
|
||||
|
||||
fn display_image(texture: &Texture2D) {
|
||||
fn display_image_centered(texture: &Texture2D) {
|
||||
let screen_width = screen_width();
|
||||
let screen_height = screen_height();
|
||||
draw_texture(
|
||||
&texture,
|
||||
texture,
|
||||
clamp(screen_width - texture.width(), 0.0f32, screen_width) / 2.0f32,
|
||||
clamp(screen_height - texture.height(), 0.0f32, screen_height) / 2.0f32,
|
||||
WHITE,
|
||||
@ -26,36 +31,35 @@ fn display_image(texture: &Texture2D) {
|
||||
}
|
||||
|
||||
#[macroquad::main(window_conf)]
|
||||
async fn main() {
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
show_mouse(false);
|
||||
let image = ImageReader::open("examples/test.jpg")
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
|
||||
let screen_dim = Dimensions::new(screen_width() as u32, screen_height() as u32);
|
||||
let image_dim = Dimensions::new(image.width(), image.height());
|
||||
|
||||
let new_dim = calculate_resize_dimensions(screen_dim, image_dim);
|
||||
let image = image.resize(
|
||||
new_dim.width,
|
||||
new_dim.height,
|
||||
image::imageops::FilterType::Lanczos3,
|
||||
);
|
||||
|
||||
let texture = Texture2D::from_rgba8(
|
||||
image.width().try_into().unwrap(),
|
||||
image.height().try_into().unwrap(),
|
||||
&image.into_rgba8().to_vec(),
|
||||
);
|
||||
let mut provider = ImageProvider::new(screen_dim, "/mnt/c/Users/beaus/Downloads".into());
|
||||
provider.load_next_image()?;
|
||||
let mut time = Instant::now();
|
||||
|
||||
loop {
|
||||
clear_background(BLACK);
|
||||
if is_quit_requested() || is_key_released(KeyCode::Escape) {
|
||||
break;
|
||||
}
|
||||
|
||||
display_image(&texture);
|
||||
next_frame().await
|
||||
display_frame(&provider)?;
|
||||
|
||||
if time.elapsed().as_secs() > 5 {
|
||||
provider.load_next_image()?;
|
||||
time = Instant::now();
|
||||
}
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
next_frame().await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_frame(provider: &ImageProvider) -> anyhow::Result<()> {
|
||||
let image = provider.get_current_texture()?;
|
||||
clear_background(BLACK);
|
||||
display_image_centered(image);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user