mirror of
https://github.com/alexpasmantier/television.git
synced 2025-06-07 12:05:34 +00:00
feature: add new image format + small fixes on the rendering of the images
This commit is contained in:
parent
6e6ce28bf5
commit
2a02c7801e
@ -255,39 +255,58 @@ 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() {
|
||||||
let preview_window_dimension = preview_window.map(|rect| {
|
Ok(reader) => match reader.decode() {
|
||||||
(u32::from(rect.width), u32::from(rect.height))
|
Ok(image) => Some(image),
|
||||||
});
|
Err(e) => {
|
||||||
let image_preview_widget =
|
warn!(
|
||||||
ImagePreviewWidget::from_dynamic_image(
|
"Error impossible to decode {}: {:?}",
|
||||||
image,
|
entry.name, e
|
||||||
preview_window_dimension,
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
warn!(
|
||||||
|
"Error impossible to guess the format of {}: {:?}",
|
||||||
|
entry.name, e
|
||||||
);
|
);
|
||||||
let total_lines = image_preview_widget
|
None
|
||||||
.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);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Error opening file: {:?}", e);
|
warn!("Error opening image {}: {:?}", entry.name, e);
|
||||||
let p = meta::not_supported(&entry.name);
|
None
|
||||||
cache.lock().insert(entry.name.clone(), &p);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
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 {
|
} 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);
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user