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 7f281234..5288831c 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 5fe5570f..e6f2a147 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 fe039d90..025470c3 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 a2ba06e4..e6dc0e56 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 e6aa7e58..ac10cea0 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 3d483005..7f0872a4 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 06a551c2..5295bf00 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 d7a07cbb..4acf60ce 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);