feat: lazy load images
this keeps the images loaded, eventually causing an OOM weird that dropping the handles doesn't clear memory
This commit is contained in:
parent
c9f9e50d1a
commit
4cb52996e2
1 changed files with 34 additions and 28 deletions
|
|
@ -1,18 +1,16 @@
|
|||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
env,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use std::{borrow::Cow, collections::HashMap, env, path::PathBuf};
|
||||
|
||||
use iced::{Color, Element, Length, Renderer, Task, Theme, application, theme, widget};
|
||||
use iced::{Color, Element, Renderer, Task, Theme, application, theme, widget};
|
||||
use ignore::{WalkBuilder, types::TypesBuilder};
|
||||
use image::{DynamicImage, EncodableLayout, RgbaImage};
|
||||
use rayon::iter::{ParallelBridge, ParallelIterator};
|
||||
|
||||
use crate::SUPPORTED_TYPES;
|
||||
|
||||
enum Message {}
|
||||
#[derive(Clone, Debug)]
|
||||
enum Message {
|
||||
LoadImage(PathBuf),
|
||||
UnloadImage(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
enum Mode {
|
||||
|
|
@ -23,7 +21,7 @@ enum Mode {
|
|||
#[derive(Default)]
|
||||
struct State {
|
||||
mode: Mode,
|
||||
images: HashMap<PathBuf, Option<(RgbaImage, widget::image::Handle)>>,
|
||||
images: HashMap<PathBuf, Option<widget::image::Handle>>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
|
@ -54,32 +52,40 @@ impl State {
|
|||
.map(|entry| entry.into_path())
|
||||
})
|
||||
.filter(|path| path.is_file())
|
||||
.map(|path| {
|
||||
let image = image::open(&path)
|
||||
.inspect_err(|e| eprintln!("{e}"))
|
||||
.ok()
|
||||
.map(DynamicImage::into_rgba8);
|
||||
let handle = image.as_ref().map(|image| {
|
||||
widget::image::Handle::from_rgba(image.width(), image.height(), unsafe {
|
||||
std::mem::transmute::<&[u8], &'static [u8]>(image.as_bytes())
|
||||
})
|
||||
});
|
||||
(path, image.map(|image| (image, handle.unwrap())))
|
||||
})
|
||||
.map(|path| (path, None))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
fn update(&mut self, message: Message) -> Task<Message> {
|
||||
match message {
|
||||
Message::LoadImage(path) => {
|
||||
self.images
|
||||
.entry(path.clone())
|
||||
.and_modify(|e| *e = Some(widget::image::Handle::from_path(path)));
|
||||
}
|
||||
Message::UnloadImage(path) => {
|
||||
self.images.entry(path).and_modify(|e| *e = None);
|
||||
}
|
||||
}
|
||||
|
||||
Task::none()
|
||||
}
|
||||
fn view(&self) -> Element<'_, Message, Theme, Renderer> {
|
||||
widget::scrollable(
|
||||
widget::grid(
|
||||
self.images
|
||||
.iter()
|
||||
.filter_map(|(_k, v)| v.as_ref())
|
||||
.map(|(_image, handle)| widget::image(handle).into()),
|
||||
)
|
||||
widget::grid(self.images.iter().map(|(path, opt_handle)| {
|
||||
opt_handle.as_ref().map_or_else(
|
||||
|| {
|
||||
widget::sensor(widget::space())
|
||||
.on_show(|_size| Message::LoadImage(path.clone()))
|
||||
.into()
|
||||
},
|
||||
|handle| {
|
||||
widget::sensor(widget::image(handle))
|
||||
.on_hide(Message::UnloadImage(path.clone()))
|
||||
.into()
|
||||
},
|
||||
)
|
||||
}))
|
||||
.fluid(500)
|
||||
.spacing(0),
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue