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"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
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]
|
[dependencies]
|
||||||
|
anyhow = "1.0.93"
|
||||||
image = "0.25.4"
|
image = "0.25.4"
|
||||||
macroquad = { version = "0.4.13" }
|
macroquad = { version = "0.4.13" }
|
||||||
|
walkdir = "2.5.0"
|
||||||
|
|||||||
@ -5,11 +5,11 @@ pub struct Dimensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Dimensions {
|
impl Dimensions {
|
||||||
pub fn new(width: u32, height: u32) -> Self {
|
pub const fn new(width: u32, height: u32) -> Self {
|
||||||
Self { width, height }
|
Self { width, height }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aspect_ratio(&self) -> f32 {
|
pub const fn aspect_ratio(self) -> f32 {
|
||||||
self.width as f32 / self.height as 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 dimensions::Dimensions;
|
||||||
use image::ImageReader;
|
use image_provider::ImageProvider;
|
||||||
use macroquad::prelude::*;
|
use macroquad::prelude::*;
|
||||||
|
use std::{
|
||||||
|
thread,
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
|
||||||
mod dimensions;
|
mod dimensions;
|
||||||
|
mod image_provider;
|
||||||
|
|
||||||
fn window_conf() -> Conf {
|
fn window_conf() -> 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_width = screen_width();
|
||||||
let screen_height = screen_height();
|
let screen_height = screen_height();
|
||||||
draw_texture(
|
draw_texture(
|
||||||
&texture,
|
texture,
|
||||||
clamp(screen_width - texture.width(), 0.0f32, screen_width) / 2.0f32,
|
clamp(screen_width - texture.width(), 0.0f32, screen_width) / 2.0f32,
|
||||||
clamp(screen_height - texture.height(), 0.0f32, screen_height) / 2.0f32,
|
clamp(screen_height - texture.height(), 0.0f32, screen_height) / 2.0f32,
|
||||||
WHITE,
|
WHITE,
|
||||||
@ -26,36 +31,35 @@ fn display_image(texture: &Texture2D) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[macroquad::main(window_conf)]
|
#[macroquad::main(window_conf)]
|
||||||
async fn main() {
|
async fn main() -> anyhow::Result<()> {
|
||||||
show_mouse(false);
|
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 screen_dim = Dimensions::new(screen_width() as u32, screen_height() as u32);
|
||||||
let image_dim = Dimensions::new(image.width(), image.height());
|
let mut provider = ImageProvider::new(screen_dim, "/mnt/c/Users/beaus/Downloads".into());
|
||||||
|
provider.load_next_image()?;
|
||||||
let new_dim = calculate_resize_dimensions(screen_dim, image_dim);
|
let mut time = Instant::now();
|
||||||
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(),
|
|
||||||
);
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
clear_background(BLACK);
|
|
||||||
if is_quit_requested() || is_key_released(KeyCode::Escape) {
|
if is_quit_requested() || is_key_released(KeyCode::Escape) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
display_image(&texture);
|
display_frame(&provider)?;
|
||||||
next_frame().await
|
|
||||||
|
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