Save thumbnails as handles to improve performance
This commit is contained in:
parent
a1c2828591
commit
3ea075b2c6
1 changed files with 46 additions and 50 deletions
96
src/tab.rs
96
src/tab.rs
|
|
@ -42,7 +42,6 @@ use mime_guess::{mime, Mime};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
|
@ -1053,8 +1052,8 @@ impl ItemMetadata {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ItemThumbnail {
|
pub enum ItemThumbnail {
|
||||||
NotImage,
|
NotImage,
|
||||||
Rgba(image::RgbaImage, Option<(u32, u32)>),
|
Image(widget::image::Handle, Option<(u32, u32)>),
|
||||||
Svg(Cow<'static, [u8]>),
|
Svg(widget::svg::Handle),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemThumbnail {
|
impl ItemThumbnail {
|
||||||
|
|
@ -1065,7 +1064,7 @@ impl ItemThumbnail {
|
||||||
match fs::read(&path) {
|
match fs::read(&path) {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
//TODO: validate SVG data
|
//TODO: validate SVG data
|
||||||
return ItemThumbnail::Svg(data.into());
|
return ItemThumbnail::Svg(widget::svg::Handle::from_memory(data));
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::warn!("failed to read {:?}: {}", path, err);
|
log::warn!("failed to read {:?}: {}", path, err);
|
||||||
|
|
@ -1076,9 +1075,14 @@ impl ItemThumbnail {
|
||||||
match image::io::Reader::open(&path).and_then(|img| img.with_guessed_format()) {
|
match image::io::Reader::open(&path).and_then(|img| img.with_guessed_format()) {
|
||||||
Ok(reader) => match reader.decode() {
|
Ok(reader) => match reader.decode() {
|
||||||
Ok(image) => {
|
Ok(image) => {
|
||||||
let thumbnail = image.thumbnail(thumbnail_size, thumbnail_size);
|
let thumbnail =
|
||||||
return ItemThumbnail::Rgba(
|
image.thumbnail(thumbnail_size, thumbnail_size).into_rgba8();
|
||||||
thumbnail.to_rgba8(),
|
return ItemThumbnail::Image(
|
||||||
|
widget::image::Handle::from_pixels(
|
||||||
|
thumbnail.width(),
|
||||||
|
thumbnail.height(),
|
||||||
|
thumbnail.into_raw(),
|
||||||
|
),
|
||||||
Some((image.width(), image.height())),
|
Some((image.width(), image.height())),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1121,9 +1125,16 @@ impl ItemThumbnail {
|
||||||
match image::io::Reader::open(file.path())
|
match image::io::Reader::open(file.path())
|
||||||
.and_then(|img| img.with_guessed_format())
|
.and_then(|img| img.with_guessed_format())
|
||||||
{
|
{
|
||||||
Ok(reader) => match reader.decode() {
|
Ok(reader) => match reader.decode().map(|image| image.into_rgba8()) {
|
||||||
Ok(image) => {
|
Ok(image) => {
|
||||||
return ItemThumbnail::Rgba(image.to_rgba8(), None);
|
return ItemThumbnail::Image(
|
||||||
|
widget::image::Handle::from_pixels(
|
||||||
|
image.width(),
|
||||||
|
image.height(),
|
||||||
|
image.into_raw(),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::warn!("failed to decode {:?}: {}", path, err);
|
log::warn!("failed to decode {:?}: {}", path, err);
|
||||||
|
|
@ -1193,22 +1204,15 @@ impl Item {
|
||||||
.unwrap_or(&ItemThumbnail::NotImage)
|
.unwrap_or(&ItemThumbnail::NotImage)
|
||||||
{
|
{
|
||||||
ItemThumbnail::NotImage => icon,
|
ItemThumbnail::NotImage => icon,
|
||||||
ItemThumbnail::Rgba(rgba, _) => {
|
ItemThumbnail::Image(handle, _) => {
|
||||||
if let Some(path) = self.path_opt() {
|
if let Some(path) = self.path_opt() {
|
||||||
if self.is_image() {
|
if self.is_image() {
|
||||||
return widget::image(widget::image::Handle::from_path(path)).into();
|
return widget::image(widget::image::Handle::from_path(path)).into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
widget::image(widget::image::Handle::from_pixels(
|
widget::image(handle.clone()).into()
|
||||||
rgba.width(),
|
|
||||||
rgba.height(),
|
|
||||||
rgba.as_raw().clone(),
|
|
||||||
))
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
ItemThumbnail::Svg(data) => {
|
|
||||||
widget::svg(widget::svg::Handle::from_memory(data.clone())).into()
|
|
||||||
}
|
}
|
||||||
|
ItemThumbnail::Svg(handle) => widget::svg(handle.clone()).into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1321,7 +1325,7 @@ impl Item {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap_or(&ItemThumbnail::NotImage)
|
.unwrap_or(&ItemThumbnail::NotImage)
|
||||||
{
|
{
|
||||||
ItemThumbnail::Rgba(_, Some((width, height))) => {
|
ItemThumbnail::Image(_, Some((width, height))) => {
|
||||||
details = details.push(widget::text(format!("{}x{}", width, height)));
|
details = details.push(widget::text(format!("{}x{}", width, height)));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
@ -2558,25 +2562,21 @@ impl Tab {
|
||||||
let location = Location::Path(path);
|
let location = Location::Path(path);
|
||||||
for item in items.iter_mut() {
|
for item in items.iter_mut() {
|
||||||
if item.location_opt.as_ref() == Some(&location) {
|
if item.location_opt.as_ref() == Some(&location) {
|
||||||
//TODO: pass handles already generated to avoid blocking main thread?
|
let handle_opt = match &thumbnail {
|
||||||
match &thumbnail {
|
ItemThumbnail::NotImage => None,
|
||||||
ItemThumbnail::NotImage => {}
|
ItemThumbnail::Image(handle, _) => Some(widget::icon::Handle {
|
||||||
ItemThumbnail::Rgba(rgba, _) => {
|
symbolic: false,
|
||||||
let handle = widget::icon::from_raster_pixels(
|
data: widget::icon::Data::Image(handle.clone()),
|
||||||
rgba.width(),
|
}),
|
||||||
rgba.height(),
|
ItemThumbnail::Svg(handle) => Some(widget::icon::Handle {
|
||||||
rgba.as_raw().clone(),
|
symbolic: false,
|
||||||
);
|
data: widget::icon::Data::Svg(handle.clone()),
|
||||||
item.icon_handle_grid = handle.clone();
|
}),
|
||||||
item.icon_handle_list = handle.clone();
|
};
|
||||||
item.icon_handle_list_condensed = handle;
|
if let Some(handle) = handle_opt {
|
||||||
}
|
item.icon_handle_grid = handle.clone();
|
||||||
ItemThumbnail::Svg(data) => {
|
item.icon_handle_list = handle.clone();
|
||||||
let handle = widget::icon::from_svg_bytes(data.clone());
|
item.icon_handle_list_condensed = handle;
|
||||||
item.icon_handle_grid = handle.clone();
|
|
||||||
item.icon_handle_list = handle.clone();
|
|
||||||
item.icon_handle_list_condensed = handle.clone();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
item.thumbnail_opt = Some(thumbnail);
|
item.thumbnail_opt = Some(thumbnail);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2897,7 +2897,7 @@ impl Tab {
|
||||||
.unwrap_or(&ItemThumbnail::NotImage)
|
.unwrap_or(&ItemThumbnail::NotImage)
|
||||||
{
|
{
|
||||||
ItemThumbnail::NotImage => {}
|
ItemThumbnail::NotImage => {}
|
||||||
ItemThumbnail::Rgba(rgba, _) => {
|
ItemThumbnail::Image(handle, _) => {
|
||||||
if let Some(path) = item.path_opt() {
|
if let Some(path) = item.path_opt() {
|
||||||
image_opt = Some(
|
image_opt = Some(
|
||||||
//TODO: use widget::image::viewer, when its zoom can be reset
|
//TODO: use widget::image::viewer, when its zoom can be reset
|
||||||
|
|
@ -2909,20 +2909,16 @@ impl Tab {
|
||||||
} else {
|
} else {
|
||||||
image_opt = Some(
|
image_opt = Some(
|
||||||
//TODO: use widget::image::viewer, when its zoom can be reset
|
//TODO: use widget::image::viewer, when its zoom can be reset
|
||||||
widget::image(widget::image::Handle::from_pixels(
|
widget::image(handle.clone())
|
||||||
rgba.width(),
|
.width(Length::Fill)
|
||||||
rgba.height(),
|
.height(Length::Fill)
|
||||||
rgba.as_raw().clone(),
|
.into(),
|
||||||
))
|
|
||||||
.width(Length::Fill)
|
|
||||||
.height(Length::Fill)
|
|
||||||
.into(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemThumbnail::Svg(data) => {
|
ItemThumbnail::Svg(handle) => {
|
||||||
image_opt = Some(
|
image_opt = Some(
|
||||||
widget::svg(widget::svg::Handle::from_memory(data.clone()))
|
widget::svg(handle.clone())
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.into(),
|
.into(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue