diff --git a/television/preview/previewers/files.rs b/television/preview/previewers/files.rs index 34a65ab..7438e9d 100644 --- a/television/preview/previewers/files.rs +++ b/television/preview/previewers/files.rs @@ -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); } diff --git a/television/utils/files.rs b/television/utils/files.rs index 17cf3df..70400b4 100644 --- a/television/utils/files.rs +++ b/television/utils/files.rs @@ -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> = 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() diff --git a/television/utils/image.rs b/television/utils/image.rs index d6b5e42..f657db1 100644 --- a/television/utils/image.rs +++ b/television/utils/image.rs @@ -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 };