mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
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.
This commit is contained in:
parent
fd8871d878
commit
6a4fee4db1
8 changed files with 67 additions and 30 deletions
|
|
@ -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<Rect> {
|
||||
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<Rect> {
|
||||
if max.is_empty() {
|
||||
return Ok(Rect::default());
|
||||
|
|
|
|||
|
|
@ -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<Rect> {
|
||||
async fn symbol_bytes_with<F: Fn((Vec<&[u8]>, Rect)) -> Result<Rect>>(
|
||||
path: &Path,
|
||||
max: Rect,
|
||||
cb: F,
|
||||
) -> Result<Rect> {
|
||||
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<Rect> {
|
||||
Self::symbol_bytes_with(path, max, |(_, area)| Ok(area)).await
|
||||
}
|
||||
|
||||
pub(super) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
|
||||
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<()> {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@ pub(super) struct Iip;
|
|||
|
||||
impl Iip {
|
||||
pub(super) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
|
||||
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()?;
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -314,8 +314,7 @@ pub(super) struct Kgp;
|
|||
|
||||
impl Kgp {
|
||||
pub(super) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
|
||||
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)?;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ pub(super) struct KgpOld;
|
|||
|
||||
impl KgpOld {
|
||||
pub(super) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
|
||||
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()?;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ pub(super) struct Sixel;
|
|||
|
||||
impl Sixel {
|
||||
pub(super) async fn image_show(path: &Path, max: Rect) -> Result<Rect> {
|
||||
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()?;
|
||||
|
|
|
|||
|
|
@ -41,23 +41,29 @@ impl Ueberzug {
|
|||
DEMON.init(Some(tx))
|
||||
}
|
||||
|
||||
pub(super) async fn image_area(path: &Path, max: Rect) -> Result<Rect> {
|
||||
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<Rect> {
|
||||
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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue