diff --git a/yazi-adapter/src/adapter.rs b/yazi-adapter/src/adapter.rs index 7f2812348..5288831c6 100644 --- a/yazi-adapter/src/adapter.rs +++ b/yazi-adapter/src/adapter.rs @@ -5,7 +5,7 @@ use ratatui::layout::Rect; use tracing::warn; use yazi_shared::env_exists; -use super::{Iip, Kgp, KgpOld}; +use super::{Iip, Image, Kgp, KgpOld}; use crate::{Chafa, Emulator, SHOWN, Sixel, TMUX, Ueberzug, WSL}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -36,6 +36,20 @@ impl Display for Adapter { } impl Adapter { + pub async fn image_area(self, path: &Path, max: Rect) -> Result { + if max.is_empty() { + return Ok(Rect::default()); + } + + match self { + Self::Kgp | Self::KgpOld | Self::Iip | Self::Sixel => { + Image::image_area(path, max).await.map(|(_img, area)| area) + } + Self::X11 | Self::Wayland => Ueberzug::image_area(path, max).await, + Self::Chafa => Chafa::image_area(path, max).await, + } + } + pub async fn image_show(self, path: &Path, max: Rect) -> Result { if max.is_empty() { return Ok(Rect::default()); diff --git a/yazi-adapter/src/chafa.rs b/yazi-adapter/src/chafa.rs index 5fe5570f8..e6f2a1474 100644 --- a/yazi-adapter/src/chafa.rs +++ b/yazi-adapter/src/chafa.rs @@ -11,7 +11,11 @@ use crate::{Adapter, Emulator}; pub(super) struct Chafa; impl Chafa { - pub(super) async fn image_show(path: &Path, max: Rect) -> Result { + async fn symbol_bytes_with, Rect)) -> Result>( + path: &Path, + max: Rect, + cb: F, + ) -> Result { let output = Command::new("chafa") .args([ "-f", @@ -52,16 +56,26 @@ impl Chafa { width: first.width() as u16, height: lines.len() as u16, }; + cb((lines, area)) + } - Adapter::Chafa.image_hide()?; - Adapter::shown_store(area); - Emulator::move_lock((max.x, max.y), |stderr| { - for (i, line) in lines.into_iter().enumerate() { - stderr.write_all(line)?; - queue!(stderr, MoveTo(max.x, max.y + i as u16 + 1))?; - } - Ok(area) + pub(super) async fn image_area(path: &Path, max: Rect) -> Result { + Self::symbol_bytes_with(path, max, |(_, area)| Ok(area)).await + } + + pub(super) async fn image_show(path: &Path, max: Rect) -> Result { + Self::symbol_bytes_with(path, max, |(lines, area)| { + Adapter::Chafa.image_hide()?; + Adapter::shown_store(area); + Emulator::move_lock((max.x, max.y), |stderr| { + for (i, line) in lines.into_iter().enumerate() { + stderr.write_all(line)?; + queue!(stderr, MoveTo(max.x, max.y + i as u16 + 1))?; + } + Ok(area) + }) }) + .await } pub(super) fn image_erase(area: Rect) -> Result<()> { diff --git a/yazi-adapter/src/iip.rs b/yazi-adapter/src/iip.rs index fe039d907..025470c35 100644 --- a/yazi-adapter/src/iip.rs +++ b/yazi-adapter/src/iip.rs @@ -14,8 +14,7 @@ pub(super) struct Iip; impl Iip { pub(super) async fn image_show(path: &Path, max: Rect) -> Result { - let img = Image::downscale(path, max).await?; - let area = Image::pixel_area((img.width(), img.height()), max); + let (img, area) = Image::image_area(path, max).await?; let b = Self::encode(img).await?; Adapter::Iip.image_hide()?; diff --git a/yazi-adapter/src/image.rs b/yazi-adapter/src/image.rs index a2ba06e4d..e6dc0e566 100644 --- a/yazi-adapter/src/image.rs +++ b/yazi-adapter/src/image.rs @@ -84,6 +84,13 @@ impl Image { .unwrap_or(rect) } + #[inline] + pub(super) async fn image_area(path: &Path, max: Rect) -> Result<(DynamicImage, Rect)> { + let img = Self::downscale(path, max).await?; + let area = Self::pixel_area((img.width(), img.height()), max); + Ok((img, area)) + } + #[inline] fn filter() -> FilterType { match PREVIEW.image_filter.as_str() { diff --git a/yazi-adapter/src/kgp.rs b/yazi-adapter/src/kgp.rs index e6aa7e588..ac10cea00 100644 --- a/yazi-adapter/src/kgp.rs +++ b/yazi-adapter/src/kgp.rs @@ -314,8 +314,7 @@ pub(super) struct Kgp; impl Kgp { pub(super) async fn image_show(path: &Path, max: Rect) -> Result { - let img = Image::downscale(path, max).await?; - let area = Image::pixel_area((img.width(), img.height()), max); + let (img, area) = Image::image_area(path, max).await?; let b1 = Self::encode(img).await?; let b2 = Self::place(&area)?; diff --git a/yazi-adapter/src/kgp_old.rs b/yazi-adapter/src/kgp_old.rs index 3d483005a..7f0872a4f 100644 --- a/yazi-adapter/src/kgp_old.rs +++ b/yazi-adapter/src/kgp_old.rs @@ -13,8 +13,7 @@ pub(super) struct KgpOld; impl KgpOld { pub(super) async fn image_show(path: &Path, max: Rect) -> Result { - let img = Image::downscale(path, max).await?; - let area = Image::pixel_area((img.width(), img.height()), max); + let (img, area) = Image::image_area(path, max).await?; let b = Self::encode(img).await?; Adapter::KgpOld.image_hide()?; diff --git a/yazi-adapter/src/sixel.rs b/yazi-adapter/src/sixel.rs index 06a551c2a..5295bf000 100644 --- a/yazi-adapter/src/sixel.rs +++ b/yazi-adapter/src/sixel.rs @@ -13,8 +13,7 @@ pub(super) struct Sixel; impl Sixel { pub(super) async fn image_show(path: &Path, max: Rect) -> Result { - let img = Image::downscale(path, max).await?; - let area = Image::pixel_area((img.width(), img.height()), max); + let (img, area) = Image::image_area(path, max).await?; let b = Self::encode(img).await?; Adapter::Sixel.image_hide()?; diff --git a/yazi-adapter/src/ueberzug.rs b/yazi-adapter/src/ueberzug.rs index d7a07cbb0..4acf60ce0 100644 --- a/yazi-adapter/src/ueberzug.rs +++ b/yazi-adapter/src/ueberzug.rs @@ -41,23 +41,29 @@ impl Ueberzug { DEMON.init(Some(tx)) } + pub(super) async fn image_area(path: &Path, max: Rect) -> Result { + let p = path.to_owned(); + let ImageSize { width: w, height: h } = + tokio::task::spawn_blocking(move || imagesize::size(p)).await??; + + Ok( + Dimension::ratio() + .map(|(r1, r2)| Rect { + x: max.x, + y: max.y, + width: max.width.min((w.min(PREVIEW.max_width as _) as f64 / r1).ceil() as _), + height: max.height.min((h.min(PREVIEW.max_height as _) as f64 / r2).ceil() as _), + }) + .unwrap_or(max), + ) + } + pub(super) async fn image_show(path: &Path, max: Rect) -> Result { let Some(tx) = &*DEMON else { bail!("uninitialized ueberzugpp"); }; - let p = path.to_owned(); - let ImageSize { width: w, height: h } = - tokio::task::spawn_blocking(move || imagesize::size(p)).await??; - - let area = Dimension::ratio() - .map(|(r1, r2)| Rect { - x: max.x, - y: max.y, - width: max.width.min((w.min(PREVIEW.max_width as _) as f64 / r1).ceil() as _), - height: max.height.min((h.min(PREVIEW.max_height as _) as f64 / r2).ceil() as _), - }) - .unwrap_or(max); + let area = Self::image_area(path, max).await?; tx.send(Some((path.to_owned(), area)))?; Adapter::shown_store(area);