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::{
|
use std::{borrow::Cow, collections::HashMap, env, path::PathBuf};
|
||||||
borrow::Cow,
|
|
||||||
collections::HashMap,
|
|
||||||
env,
|
|
||||||
path::{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 ignore::{WalkBuilder, types::TypesBuilder};
|
||||||
use image::{DynamicImage, EncodableLayout, RgbaImage};
|
|
||||||
use rayon::iter::{ParallelBridge, ParallelIterator};
|
use rayon::iter::{ParallelBridge, ParallelIterator};
|
||||||
|
|
||||||
use crate::SUPPORTED_TYPES;
|
use crate::SUPPORTED_TYPES;
|
||||||
|
|
||||||
enum Message {}
|
#[derive(Clone, Debug)]
|
||||||
|
enum Message {
|
||||||
|
LoadImage(PathBuf),
|
||||||
|
UnloadImage(PathBuf),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
enum Mode {
|
enum Mode {
|
||||||
|
|
@ -23,7 +21,7 @@ enum Mode {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct State {
|
struct State {
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
images: HashMap<PathBuf, Option<(RgbaImage, widget::image::Handle)>>,
|
images: HashMap<PathBuf, Option<widget::image::Handle>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
|
|
@ -54,32 +52,40 @@ impl State {
|
||||||
.map(|entry| entry.into_path())
|
.map(|entry| entry.into_path())
|
||||||
})
|
})
|
||||||
.filter(|path| path.is_file())
|
.filter(|path| path.is_file())
|
||||||
.map(|path| {
|
.map(|path| (path, None))
|
||||||
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())))
|
|
||||||
})
|
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn update(&mut self, message: Message) -> Task<Message> {
|
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()
|
Task::none()
|
||||||
}
|
}
|
||||||
fn view(&self) -> Element<'_, Message, Theme, Renderer> {
|
fn view(&self) -> Element<'_, Message, Theme, Renderer> {
|
||||||
widget::scrollable(
|
widget::scrollable(
|
||||||
widget::grid(
|
widget::grid(self.images.iter().map(|(path, opt_handle)| {
|
||||||
self.images
|
opt_handle.as_ref().map_or_else(
|
||||||
.iter()
|
|| {
|
||||||
.filter_map(|(_k, v)| v.as_ref())
|
widget::sensor(widget::space())
|
||||||
.map(|(_image, handle)| widget::image(handle).into()),
|
.on_show(|_size| Message::LoadImage(path.clone()))
|
||||||
)
|
.into()
|
||||||
|
},
|
||||||
|
|handle| {
|
||||||
|
widget::sensor(widget::image(handle))
|
||||||
|
.on_hide(Message::UnloadImage(path.clone()))
|
||||||
|
.into()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}))
|
||||||
.fluid(500)
|
.fluid(500)
|
||||||
.spacing(0),
|
.spacing(0),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue