Kitty 图形协议[1] 用于使终端支持高清图形功能。
基本使用
协议的构成如下:
<ESC>_G<control data>;<payload><ESC>\
其中 control data 是由逗号分割的 key=value
对。payload 是由 base64 编码的数据。
协议对 PNG 提供原生支持,如果需要渲染 PNG 数据,只需要使用:
<ESC>_Gf=100;<payload><ESC>\
其中 payload 是 base64 编码的 PNG 二进制数据。
如果同时还使用了压缩协议,则必须提供 payload 的大小 |
传输介质
通过 key t
能够指明 payload 的含意,具体有:
value | 含意 |
---|---|
d | payload 包含了需要渲染的二进制数据。 |
f | payload 代表了一个文件路径。此文件是一个 regular 文件。 |
t | payload 指向临时文件路径,终端将会在读取后将此文家删除。 |
s | 共享内存对象。 |
渲染数据
下面给出了渲染数据的例子:
use std::collections::HashMap;
use base64::Engine;
use base64::engine::general_purpose;
#[derive(Debug, Default)]
struct KittyBuilder<T: AsRef<[u8]>> {
opts: HashMap<String, String>,
payload: T,
}
impl<T: AsRef<[u8]>> KittyBuilder<T> {
fn build(self) -> String {
let opts: Vec<String> = self
.opts
.into_iter()
.map(|(key, value)| format!("{key}={value}"))
.collect();
format!(
"\x1b_G{};{}\x1b\\",
opts.join(",").to_string(),
general_purpose::STANDARD.encode(self.payload)
)
}
fn opt(mut self, key: String, value: String) -> Self {
self.opts.insert(key, value);
self
}
fn payload(mut self, payload: T) -> Self {
self.payload = payload;
self
}
}
fn main() {
let pic1 = KittyBuilder::default()
.opt("f".into(), "100".into())
.opt("a".into(), "T".into())
.opt("t".into(), "f".into())
.payload("1.png") (1)
.build();
print!("{}", pic1);
let pic1 = KittyBuilder::default()
.opt("f".into(), "100".into())
.opt("a".into(), "T".into())
.payload(std::fs::read("1.png").unwrap()) (2)
.build();
print!("{}", pic1);
}
直接渲染数据
要求渲染指定路径的数据