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,39 +255,58 @@ pub fn try_preview(
entry.name.clone(),
&meta::loading(&format!("Loading {}", entry.name)),
);
debug!("File {:?} is an image", entry.name);
match ImageReader::open(path).unwrap().decode() {
Ok(image) => {
let preview_window_dimension = preview_window.map(|rect| {
(u32::from(rect.width), u32::from(rect.height))
});
let image_preview_widget =
ImagePreviewWidget::from_dynamic_image(
image,
preview_window_dimension,
let option_image = match ImageReader::open(path) {
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
);
let total_lines = image_preview_widget
.height()
.try_into()
.unwrap_or(u16::MAX);
let content = PreviewContent::Image(image_preview_widget);
let preview = Arc::new(Preview::new(
entry.name.clone(),
content,
entry.icon,
None,
total_lines,
));
cache.lock().insert(entry.name.clone(), &preview);
}
None
}
},
Err(e) => {
warn!("Error opening file: {:?}", e);
let p = meta::not_supported(&entry.name);
cache.lock().insert(entry.name.clone(), &p);
warn!("Error opening image {}: {:?}", entry.name, e);
None
}
};
if let Some(image) = option_image {
let preview_window_dimension = preview_window.map(|rect| {
(u32::from(rect.width - 2), u32::from(rect.height - 2)) // - 2 for the marge
});
let image_preview_widget = ImagePreviewWidget::from_dynamic_image(
image,
preview_window_dimension,
);
let total_lines =
image_preview_widget.height().try_into().unwrap_or(u16::MAX);
let content = PreviewContent::Image(image_preview_widget);
let preview = Arc::new(Preview::new(
entry.name.clone(),
content,
entry.icon,
None,
total_lines,
));
cache.lock().insert(entry.name.clone(), &preview);
} else {
let p = meta::not_supported(&entry.name);
cache.lock().insert(entry.name.clone(), &p);
}
} 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);
cache.lock().insert(entry.name.clone(), &preview);
}

View File

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

View File

@ -8,7 +8,7 @@ use std::fmt::Debug;
use std::hash::Hash;
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
const DEFAULT_CACHED_WIDTH: u32 = 50;
@ -28,7 +28,7 @@ impl Widget for &ImagePreviewWidget {
let width = self.width();
// offset of the left top corner where the image is centered
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 y_offset = total_height.saturating_sub(height) / 2;
@ -42,7 +42,8 @@ impl Widget for &ImagePreviewWidget {
for (x, cell) in row.iter().enumerate() {
let pos_x =
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) =
buf.cell_mut(Position::new(pos_x, pos_y))
{
@ -74,29 +75,28 @@ impl ImagePreviewWidget {
dynamic_image: DynamicImage,
dimension: Option<(u32, u32)>,
) -> Self {
// first quick resize
let (window_width, window_height) =
dimension.unwrap_or((DEFAULT_CACHED_WIDTH, DEFAULT_CACHED_HEIGHT));
let big_resized_image = if dynamic_image.width() > window_width * 4
|| dynamic_image.height() > window_height * 4
let (max_width, max_height) = (window_width, window_height * 2 - 2); // -2 to have some space with the title
// first quick resize
let big_resized_image = if dynamic_image.width() > max_width * 4
|| dynamic_image.height() > max_height * 4
{
dynamic_image.resize(
window_width * 4,
window_height * 4,
max_width * 4,
max_height * 4,
FilterType::Nearest,
)
} else {
dynamic_image
};
// this time resize with the filter
let resized_image = if big_resized_image.width() > window_width
|| big_resized_image.height() > window_height
let resized_image = if big_resized_image.width() > max_width
|| big_resized_image.height() > max_height
{
big_resized_image.resize(
window_width,
DEFAULT_CACHED_HEIGHT,
FILTER_TYPE,
)
big_resized_image.resize(max_width, max_height, FILTER_TYPE)
} else {
big_resized_image
};