diff --git a/television/preview/mod.rs b/television/preview/mod.rs index 2ca49db..5c3b215 100644 --- a/television/preview/mod.rs +++ b/television/preview/mod.rs @@ -9,7 +9,7 @@ pub mod previewers; // previewer types use crate::utils::cache::RingSet; -use crate::utils::image::{CachedImageData}; +use crate::utils::image::CachedImageData; use crate::utils::syntax::HighlightedLines; pub use previewers::basic::BasicPreviewer; pub use previewers::basic::BasicPreviewerConfig; @@ -208,10 +208,7 @@ impl Previewer { } } - fn dispatch_request( - &mut self, - entry: &Entry, - ) -> Option> { + fn dispatch_request(&mut self, entry: &Entry) -> Option> { match &entry.preview_type { PreviewType::Basic => Some(self.basic.preview(entry)), PreviewType::EnvVar => Some(self.env_var.preview(entry)), @@ -225,10 +222,7 @@ impl Previewer { // faster, but since it's already running in the background and quite // fast for most standard file sizes, plus we're caching the previews, // I'm not sure the extra complexity is worth it. - pub fn preview( - &mut self, - entry: &Entry, - ) -> Option> { + pub fn preview(&mut self, entry: &Entry) -> Option> { // if we haven't acknowledged the request yet, acknowledge it self.requests.push(entry.clone()); diff --git a/television/preview/previewers/files.rs b/television/preview/previewers/files.rs index f0f4d83..890b1db 100644 --- a/television/preview/previewers/files.rs +++ b/television/preview/previewers/files.rs @@ -1,6 +1,6 @@ use crate::utils::files::{read_into_lines_capped, ReadResult}; use crate::utils::syntax::HighlightedLines; -use image::{ImageReader}; +use image::ImageReader; use parking_lot::Mutex; use rustc_hash::{FxBuildHasher, FxHashSet}; use std::collections::HashSet; @@ -18,12 +18,12 @@ use tracing::{debug, trace, warn}; use crate::channels::entry; use crate::preview::cache::PreviewCache; use crate::preview::{previewers::meta, Preview, PreviewContent}; +use crate::utils::image::CachedImageData; use crate::utils::{ files::FileType, strings::preprocess_line, syntax::{self, load_highlighting_assets, HighlightingAssetsExt}, }; -use crate::utils::image::CachedImageData; #[derive(Debug, Default)] pub struct FilePreviewer { @@ -80,20 +80,14 @@ impl FilePreviewer { self.cache.lock().get(&entry.name) } - pub fn preview( - &mut self, - entry: &entry::Entry, - ) -> Option> { + pub fn preview(&mut self, entry: &entry::Entry) -> Option> { if let Some(preview) = self.cached(entry) { trace!("Preview cache hit for {:?}", entry.name); if preview.partial_offset.is_some() { // preview is partial, spawn a task to compute the next chunk // and return the partial preview debug!("Spawning partial preview task for {:?}", entry.name); - self.handle_preview_request( - entry, - Some(preview.clone()) - ); + self.handle_preview_request(entry, Some(preview.clone())); } Some(preview) } else { @@ -107,7 +101,7 @@ impl FilePreviewer { pub fn handle_preview_request( &mut self, entry: &entry::Entry, - partial_preview: Option> + partial_preview: Option>, ) { if self.in_flight_previews.lock().contains(&entry.name) { trace!("Preview already in flight for {:?}", entry.name); @@ -252,7 +246,8 @@ pub fn try_preview( debug!("File {:?} is an image", entry.name); match ImageReader::open(path).unwrap().decode() { Ok(image) => { - let cached_image_data = CachedImageData::from_dynamic_image(image); + let cached_image_data = + CachedImageData::from_dynamic_image(image); let total_lines = cached_image_data.height().try_into().unwrap_or(u16::MAX); let content = PreviewContent::Image(cached_image_data); @@ -271,7 +266,6 @@ pub fn try_preview( cache.lock().insert(entry.name.clone(), &p); } } - } else { debug!("File isn't text-based: {:?}", entry.name); let preview = meta::not_supported(&entry.name); diff --git a/television/screen/preview.rs b/television/screen/preview.rs index c048934..4c3acce 100644 --- a/television/screen/preview.rs +++ b/television/screen/preview.rs @@ -3,9 +3,7 @@ use crate::preview::{ ansi::IntoText, PreviewContent, FILE_TOO_LARGE_MSG, LOADING_MSG, PREVIEW_NOT_SUPPORTED_MSG, TIMEOUT_MSG, }; -use crate::screen::{ - colors::{Colorscheme, PreviewColorscheme}, -}; +use crate::screen::colors::{Colorscheme, PreviewColorscheme}; use crate::utils::strings::{ replace_non_printable, shrink_with_ellipsis, ReplaceNonPrintableConfig, EMPTY_STRING, @@ -96,9 +94,7 @@ pub fn build_preview_paragraph<'a>( inner.height, ) } - PreviewContent::Image(image) => { - image.paragraph(inner, preview_block) - } + PreviewContent::Image(image) => image.paragraph(inner, preview_block), // meta PreviewContent::Loading => { @@ -247,7 +243,6 @@ fn build_syntect_highlighted_paragraph<'a>( //.scroll((preview_scroll, 0)) } - pub fn build_meta_preview_paragraph<'a>( inner: Rect, message: &str, @@ -434,5 +429,3 @@ fn convert_syn_color_to_ratatui_color( ) -> Color { Color::Rgb(color.r, color.g, color.b) } - - diff --git a/television/utils/image.rs b/television/utils/image.rs index 1b02d1a..04e9ce9 100644 --- a/television/utils/image.rs +++ b/television/utils/image.rs @@ -1,8 +1,6 @@ use std::hash::{Hash, Hasher}; - -use image::{DynamicImage, Rgba }; - +use image::{DynamicImage, Rgba}; use image::imageops::FilterType; use ratatui::layout::{Alignment, Rect}; @@ -29,24 +27,27 @@ impl Hash for CachedImageData { } } - impl CachedImageData { - pub fn new(rgba_image: DynamicImage) -> Self{ - CachedImageData{image: rgba_image} + pub fn new(rgba_image: DynamicImage) -> Self { + CachedImageData { image: rgba_image } } - pub fn height(&self) -> u32{ + pub fn height(&self) -> u32 { self.image.height() } - pub fn width(&self) -> u32{ + pub fn width(&self) -> u32 { self.image.width() } - pub fn from_dynamic_image( - dynamic_image: DynamicImage, - ) -> Self { + pub fn from_dynamic_image(dynamic_image: DynamicImage) -> Self { // if the image is smaller than the preview window, keep it small - let resized_image = if dynamic_image.width() > CACHED_WIDTH || dynamic_image.height() > CACHED_HEIGHT { - dynamic_image.resize(CACHED_WIDTH, CACHED_HEIGHT , FilterType::Nearest) + let resized_image = if dynamic_image.width() > CACHED_WIDTH + || dynamic_image.height() > CACHED_HEIGHT + { + dynamic_image.resize( + CACHED_WIDTH, + CACHED_HEIGHT, + FilterType::Nearest, + ) } else { dynamic_image }; @@ -55,12 +56,21 @@ impl CachedImageData { let rgba_image = resized_image.into_rgba8(); CachedImageData::new(DynamicImage::from(rgba_image)) } - pub fn paragraph<'a>(&self, inner: Rect, preview_block: Block<'a>) -> Paragraph<'a> { + pub fn paragraph<'a>( + &self, + inner: Rect, + preview_block: Block<'a>, + ) -> Paragraph<'a> { let preview_width = u32::from(inner.width); let preview_height = u32::from(inner.height) * 2; // *2 because 2 pixels per character - let image_rgba = if self.image.width() > preview_width || self.image.height() > preview_height { - &self.image.resize(preview_width, preview_height, FILTER_TYPE).into_rgba8() - } else{ + let image_rgba = if self.image.width() > preview_width + || self.image.height() > preview_height + { + &self + .image + .resize(preview_width, preview_height, FILTER_TYPE) + .into_rgba8() + } else { self.image.as_rgba8().expect("to be rgba8 image") // converted into rgba8 before being put into the cache, so it should never enter the expect }; // transform it into text @@ -68,44 +78,27 @@ impl CachedImageData { // iter over pair of rows .rows() .step_by(2) - .zip(image_rgba.rows().skip(1).step_by(2)).enumerate() - .map(|(double_row_y, (row_1, row_2))| - Line::from_iter(row_1.into_iter().zip(row_2.into_iter()).enumerate().map( - |(x, (color_up, color_down))| { - convert_pixel_to_span( - color_up, - color_down, - (x, double_row_y), - )} + .zip(image_rgba.rows().skip(1).step_by(2)) + .enumerate() + .map(|(double_row_y, (row_1, row_2))| { + Line::from_iter( + row_1.into_iter().zip(row_2).enumerate().map( + |(x, (color_up, color_down))| { + convert_pixel_to_span( + color_up, + color_down, + (x, double_row_y), + ) + }, + ), ) - )) + }) .collect::>(); let text_image = Text::from(lines); Paragraph::new(text_image) .block(preview_block) .alignment(Alignment::Center) } - -} - -#[allow(dead_code)] -fn calculate_fit_dimensions(original_width: u32, original_height: u32, max_width: u32, max_height: u32) -> (u32, u32) { - if original_width <= max_width && original_height <= max_height { - return (original_width, original_height); - } - - let width_ratio = f64::from(max_width) / f64::from(original_width); - let height_ratio = f64::from(max_height) / f64::from(original_height); - - let scale = width_ratio.min(height_ratio); - - - let new_width = u32::try_from((f64::from(original_width) * scale).round() as u64) - .unwrap_or(u32::MAX); - let new_height = u32::try_from((f64::from(original_height) * scale).round() as u64) - .unwrap_or(u32::MAX); - - (new_width, new_height) } pub fn convert_pixel_to_span<'a>( @@ -141,7 +134,6 @@ pub fn convert_pixel_to_span<'a>( let color_up = convert_image_color_to_ratatui_color(color_up); let color_down = convert_image_color_to_ratatui_color(color_down); - let style = Style::default().fg(color_up).bg(color_down); Span::styled(String::from(PIXEL), style) }