#tui #终端图形 #图像 #ratatui #sixel #kitty #背景色

bin+lib ratatui-image

ratatui图像小部件,支持sixel和unicode半块

27个版本 (6个稳定版)

1.0.5 2024年7月20日
1.0.1 2024年6月1日
1.0.0 2024年3月31日
0.10.0 2024年3月31日
0.4.3 2023年11月24日

#16图形API

Download history 363/week @ 2024-05-04 428/week @ 2024-05-11 529/week @ 2024-05-18 533/week @ 2024-05-25 813/week @ 2024-06-01 740/week @ 2024-06-08 563/week @ 2024-06-15 425/week @ 2024-06-22 609/week @ 2024-06-29 681/week @ 2024-07-06 451/week @ 2024-07-13 860/week @ 2024-07-20 974/week @ 2024-07-27 1082/week @ 2024-08-03 1325/week @ 2024-08-10 1029/week @ 2024-08-17

4,478 每月下载量
16 个crates中(14个直接使用) 使用

MIT 许可证

86KB
2K SLoC

Ratatui-image

CI Badge Crate Badge Docs Badge

展示

Recording

ratatui提供具有多个图形协议后端的图像小部件

ratatui是一个即时模式的TUI库。ratatui-image在即时模式的TUI中渲染图像时解决了3个一般问题

  1. 查询终端可用的图形协议。某些终端可能实现了一个或多个图形协议,例如Sixels,或iTerm2或Kitty图形协议。通过环境变量猜测。如果失败,使用一些控制序列查询终端。回退到使用一些带前景色和背景色的unicode半块字符的“半块”。

  2. 查询终端的像素字体大小。如果确实有图形协议可用,需要知道字体大小才能将图像像素映射到字符单元格区域。图像可以调整大小、适应或裁剪到某个区域。查询终端的窗口和列/行大小,并推导出字体大小。

  3. 通过猜测的协议渲染图像。某些协议,如Sixels,本质上属于“即时模式”,但我们仍然需要避免TUI覆盖图像区域,即使是空白字符。其他协议,如Kitty,本质上是有状态的,但至少提供了一种重新渲染已加载图像的方法,位置可以是不同的或相同的。

快速开始

use ratatui::{backend::TestBackend, Terminal, terminal::Frame};
use ratatui_image::{picker::Picker, StatefulImage, protocol::StatefulProtocol};

struct App {
    // We need to hold the render state.
    image: Box<dyn StatefulProtocol>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let backend = TestBackend::new(80, 30);
    let mut terminal = Terminal::new(backend)?;

    // Should use Picker::from_termios(), to get the font size,
    // but we can't put that here because that would break doctests!
    let mut picker = Picker::new((8, 12));
    // Guess the protocol.
    picker.guess_protocol();

    // Load an image with the image crate.
    let dyn_img = image::io::Reader::open("./assets/Ada.png")?.decode()?;

    // Create the Protocol which will be used by the widget.
    let image = picker.new_resize_protocol(dyn_img);

    let mut app = App { image };

    // This would be your typical `loop {` in a real app:
    terminal.draw(|f| ui(f, &mut app))?;

    Ok(())
}

fn ui(f: &mut Frame<'_>, app: &mut App) {
    // The image widget.
    let image = StatefulImage::new(None);
    // Render with the protocol state.
    f.render_stateful_widget(image, f.size(), &mut app.image);
}

picker::Picker 辅助工具用于执行所有这些字体大小和图形协议猜测,并且还可以将字符单元格大小映射到像素大小,这样我们就可以例如“适应”图像到所需的列+行边界内,等等。

小部件选择

  • 图片小部件不能适应渲染区域(如果空间不足则完全不绘制),可能更容易出现一些错误(过度绘制或伪影),并且与一些协议(例如状态性的Kitty图形协议)不太兼容。它最大的优点是它是无状态的(在ratatui中即即时模式),因此永远不会阻塞渲染线程/任务。许多ratatui应用程序只使用无状态小部件。
  • 有状态的图片小部件适应其渲染区域,对过度绘制错误和伪影更健壮,并且与一些图形协议更兼容。默认情况下,调整大小和编码是阻塞的,但可以将这些操作卸载到另一个线程或异步任务(请参阅examples/async.rs)。必须使用render_stateful_widget(即带有一些可变状态)进行渲染。

示例

  • examples/demo.rs是一个完整的演示。
  • examples/async.rs展示了如何将调整大小和编码卸载到另一个线程,以避免阻塞UI线程。

库还包含一个二进制文件,用于渲染图像文件,但它主要关注测试。

功能

  • rustix(默认)通过rustix::termios::tcgetattr启用了对图形协议的更好猜测。
  • crosstermtermion应与您的ratatui后端相匹配。termwiz可用,但与ratatu-image不正确工作。
  • serde用于picker::ProtocolType上的#[derive],以方便使用,因为它可能有助于将其保存到某些用户配置中。
  • image-defaults(默认)仅启用image/defaultsimagedefault-features = false)。为了仅支持一组图像格式并减少依赖项,请禁用此功能,将image添加到您的crate中,并根据需要启用其功能/格式。请参阅https://doc.rust-lang.net.cn/cargo/reference/features.html#feature-unification

兼容性矩阵

兼容性和QA

终端 协议 已修复 调整大小 备注
Xterm Sixel ✔️ ✔️ 使用-ti 340运行以确保启用Sixel支持。
页脚 Sixel ✔️ ✔️ Wayland。
kitty Kitty ✔️ ✔️
Wezterm iTerm2 ✔️ ✔️ 也支持SixelKitty,但只有iTerm2真正无错误工作。
Alacritty Sixel 存在一个Sixel分支,但它已过时且不清除图形。
iTerm2 iTerm2 未测试(需要苹果硬件),但应与WezTerm相同。
konsole Sixel 不会修复:不清除图形,其他伪影。
Contour Sixel 不清除图形。
ctx Sixel 有错误。
Blackbox Sixel 未测试。

在此,“已修复”是指Image小部件,“调整大小”是指StatefulWidget

使用xterm在Xvfb上运行了一个基本的截图测试(在CI中或cargo make screenshot-xvfb && cargo make screenshot-diff)。

半块应该在所有终端中工作。

使用ratatui-image的项目

  • iamb 一个具有vim快捷键的矩阵客户端。
  • joshuto 一个可以预览图片的终端文件管理器。
  • Aerostream 使用EventStream的Bluesky客户端。

比较

  • viuer 在不同的终端/协议中渲染图形,但“丢弃”图像,这使得TUI程序难以工作。终端协议猜测代码已适配到rustix,因此viuer的作者被包括在版权声明中。
  • yazi 不是一个库,而是一个实现了许多图形协议的终端文件管理器,允许你在文件系统中预览图片。
  • Überzug++ 一个CLI实用程序,通过使用X11/wayland子窗口、sixels、kitty和/或iterm2协议(任何必要的手段)在终端上绘制图像。存在几个包装器或绑定crates。经过更多实战测试,但本质上是有状态的,这使得与即时模式一起使用变得困难。

许可证:MIT

依赖项

~9–22MB
~330K SLoC