From 6a4fee4db18883b1744d2dd141f20821f1a8677a Mon Sep 17 00:00:00 2001 From: gaesa <71256557+gaesa@users.noreply.github.com> Date: Mon, 11 Nov 2024 01:07:05 +0000 Subject: [PATCH] refactor(adapter): extract `image_area` from `image_show` Exposing `image_area` separately allows future Lua integration to handle image placement more flexibly, without needing to invoke full rendering. This change promotes modularity and simplifies obtaining image dimensions alone. This refactor provides the foundation for feature PR #1897, preparing for easier integration. --- yazi-adapter/src/adapter.rs | 16 +++++++++++++++- yazi-adapter/src/chafa.rs | 32 +++++++++++++++++++++++--------- yazi-adapter/src/iip.rs | 3 +-- yazi-adapter/src/image.rs | 7 +++++++ yazi-adapter/src/kgp.rs | 3 +-- yazi-adapter/src/kgp_old.rs | 3 +-- yazi-adapter/src/sixel.rs | 3 +-- yazi-adapter/src/ueberzug.rs | 30 ++++++++++++++++++------------ 8 files changed, 67 insertions(+), 30 deletions(-) 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);