feature: add new image format + small fixes on the rendering of the images

This commit is contained in:
azy 2025-03-05 21:37:28 +09:00
parent 6e6ce28bf5
commit 2a02c7801e
3 changed files with 68 additions and 55 deletions

View File

@ -255,21 +255,43 @@ pub fn try_preview(
entry.name.clone(), entry.name.clone(),
&meta::loading(&format!("Loading {}", entry.name)), &meta::loading(&format!("Loading {}", entry.name)),
); );
debug!("File {:?} is an image", entry.name); debug!("File {:?} is an image", entry.name);
match ImageReader::open(path).unwrap().decode() { let option_image = match ImageReader::open(path) {
Ok(image) => { Ok(reader) => match reader.with_guessed_format() {
Ok(reader) => match reader.decode() {
Ok(image) => Some(image),
Err(e) => {
warn!(
"Error impossible to decode {}: {:?}",
entry.name, e
);
None
}
},
Err(e) => {
warn!(
"Error impossible to guess the format of {}: {:?}",
entry.name, e
);
None
}
},
Err(e) => {
warn!("Error opening image {}: {:?}", entry.name, e);
None
}
};
if let Some(image) = option_image {
let preview_window_dimension = preview_window.map(|rect| { let preview_window_dimension = preview_window.map(|rect| {
(u32::from(rect.width), u32::from(rect.height)) (u32::from(rect.width - 2), u32::from(rect.height - 2)) // - 2 for the marge
}); });
let image_preview_widget = let image_preview_widget = ImagePreviewWidget::from_dynamic_image(
ImagePreviewWidget::from_dynamic_image(
image, image,
preview_window_dimension, preview_window_dimension,
); );
let total_lines = image_preview_widget let total_lines =
.height() image_preview_widget.height().try_into().unwrap_or(u16::MAX);
.try_into()
.unwrap_or(u16::MAX);
let content = PreviewContent::Image(image_preview_widget); let content = PreviewContent::Image(image_preview_widget);
let preview = Arc::new(Preview::new( let preview = Arc::new(Preview::new(
entry.name.clone(), entry.name.clone(),
@ -279,15 +301,12 @@ pub fn try_preview(
total_lines, total_lines,
)); ));
cache.lock().insert(entry.name.clone(), &preview); cache.lock().insert(entry.name.clone(), &preview);
} } else {
Err(e) => {
warn!("Error opening file: {:?}", e);
let p = meta::not_supported(&entry.name); let p = meta::not_supported(&entry.name);
cache.lock().insert(entry.name.clone(), &p); cache.lock().insert(entry.name.clone(), &p);
} }
}
} else { } else {
debug!("File isn't text-based: {:?}", entry.name); debug!("File format isn't supported for preview: {:?}", entry.name);
let preview = meta::not_supported(&entry.name); let preview = meta::not_supported(&entry.name);
cache.lock().insert(entry.name.clone(), &preview); cache.lock().insert(entry.name.clone(), &preview);
} }

View File

@ -118,12 +118,12 @@ where
fn from(path: P) -> Self { fn from(path: P) -> Self {
debug!("Getting file type for {:?}", path); debug!("Getting file type for {:?}", path);
let p = path.as_ref(); let p = path.as_ref();
if is_known_text_extension(p) {
return FileType::Text;
}
if is_accepted_image_extension(p) { if is_accepted_image_extension(p) {
return FileType::Image; return FileType::Image;
} }
if is_known_text_extension(p) {
return FileType::Text;
}
if let Ok(mut f) = File::open(p) { if let Ok(mut f) = File::open(p) {
let mut buffer = [0u8; 256]; let mut buffer = [0u8; 256];
if let Ok(bytes_read) = f.read(&mut buffer) { if let Ok(bytes_read) = f.read(&mut buffer) {
@ -506,16 +506,10 @@ pub static KNOWN_IMAGE_FILE_EXTENSIONS: OnceLock<FxHashSet<&'static str>> =
pub fn get_known_image_file_extensions() -> &'static FxHashSet<&'static str> { pub fn get_known_image_file_extensions() -> &'static FxHashSet<&'static str> {
KNOWN_IMAGE_FILE_EXTENSIONS.get_or_init(|| { KNOWN_IMAGE_FILE_EXTENSIONS.get_or_init(|| {
[ [
//"avif", // "avif", requires the avif-native feature, uses the libdav1d C library.
//"bmp", // dds, dosen't work for some reason
//"dds", "bmp", "ff", "gif", "hdr", "ico", "jpeg", "jpg", "exr", "png",
//"farbfeld", "pnm", "qoi", "tga", "tif", "webp",
"gif", //"hdr",
"ico", "jpeg", "jpg", //"exr",
"png", //"pnm",
//"qoi",
//"tga",
"tif", "tiff", "webp",
] ]
.iter() .iter()
.copied() .copied()

View File

@ -8,7 +8,7 @@ use std::fmt::Debug;
use std::hash::Hash; use std::hash::Hash;
static PIXEL_STRING: &str = ""; static PIXEL_STRING: &str = "";
const FILTER_TYPE: FilterType = FilterType::Triangle; const FILTER_TYPE: FilterType = FilterType::Lanczos3;
// use to reduce the size of the image before storing it // use to reduce the size of the image before storing it
const DEFAULT_CACHED_WIDTH: u32 = 50; const DEFAULT_CACHED_WIDTH: u32 = 50;
@ -28,7 +28,7 @@ impl Widget for &ImagePreviewWidget {
let width = self.width(); let width = self.width();
// offset of the left top corner where the image is centered // offset of the left top corner where the image is centered
let total_width = usize::from(area.width) + 2 * usize::from(area.x); let total_width = usize::from(area.width) + 2 * usize::from(area.x);
let x_offset = total_width.saturating_sub(width) / 2; let x_offset = total_width.saturating_sub(width) / 2 + 1;
let total_height = usize::from(area.height) + 2 * usize::from(area.y); let total_height = usize::from(area.height) + 2 * usize::from(area.y);
let y_offset = total_height.saturating_sub(height) / 2; let y_offset = total_height.saturating_sub(height) / 2;
@ -42,7 +42,8 @@ impl Widget for &ImagePreviewWidget {
for (x, cell) in row.iter().enumerate() { for (x, cell) in row.iter().enumerate() {
let pos_x = let pos_x =
u16::try_from(x_offset + x).unwrap_or(u16::MAX); u16::try_from(x_offset + x).unwrap_or(u16::MAX);
if pos_x >= area_border_left && pos_x < area_border_right { if pos_x >= area_border_left && pos_x <= area_border_right
{
if let Some(buf_cell) = if let Some(buf_cell) =
buf.cell_mut(Position::new(pos_x, pos_y)) buf.cell_mut(Position::new(pos_x, pos_y))
{ {
@ -74,29 +75,28 @@ impl ImagePreviewWidget {
dynamic_image: DynamicImage, dynamic_image: DynamicImage,
dimension: Option<(u32, u32)>, dimension: Option<(u32, u32)>,
) -> Self { ) -> Self {
// first quick resize
let (window_width, window_height) = let (window_width, window_height) =
dimension.unwrap_or((DEFAULT_CACHED_WIDTH, DEFAULT_CACHED_HEIGHT)); dimension.unwrap_or((DEFAULT_CACHED_WIDTH, DEFAULT_CACHED_HEIGHT));
let big_resized_image = if dynamic_image.width() > window_width * 4 let (max_width, max_height) = (window_width, window_height * 2 - 2); // -2 to have some space with the title
|| dynamic_image.height() > window_height * 4
// first quick resize
let big_resized_image = if dynamic_image.width() > max_width * 4
|| dynamic_image.height() > max_height * 4
{ {
dynamic_image.resize( dynamic_image.resize(
window_width * 4, max_width * 4,
window_height * 4, max_height * 4,
FilterType::Nearest, FilterType::Nearest,
) )
} else { } else {
dynamic_image dynamic_image
}; };
// this time resize with the filter // this time resize with the filter
let resized_image = if big_resized_image.width() > window_width let resized_image = if big_resized_image.width() > max_width
|| big_resized_image.height() > window_height || big_resized_image.height() > max_height
{ {
big_resized_image.resize( big_resized_image.resize(max_width, max_height, FILTER_TYPE)
window_width,
DEFAULT_CACHED_HEIGHT,
FILTER_TYPE,
)
} else { } else {
big_resized_image big_resized_image
}; };