52 lines
2.7 KiB
Go
52 lines
2.7 KiB
Go
package stego
|
||
|
||
import (
|
||
"encoding/base64"
|
||
"fmt"
|
||
"strings"
|
||
)
|
||
|
||
// KittyEscape кодирует PNG-байты в escape-последовательность протокола
|
||
// Kitty graphics — Konsole его понимает (это уже выяснялось раньше, на
|
||
// другом проекте, где графические протоколы работали в Konsole, но не
|
||
// в Alacritty).
|
||
//
|
||
// ЧЕСТНАЯ ОГОВОРКА, серьёзнее обычной: сама генерация escape-кода по
|
||
// спецификации протокола — то, что я действительно знаю и могу
|
||
// аргументировать (a=T — передать и сразу отобразить одним действием;
|
||
// f=100 — формат PNG, протокол умеет декодировать его сам, кодировать
|
||
// в сырой RGBA не нужно; t=d — данные идут прямо в escape-последовательности,
|
||
// не через файл; чанки по 4096 base64-байт — так требует спецификация
|
||
// для больших изображений). А вот что произойдёт, когда bubbletea в
|
||
// alt-screen режиме в следующий раз перерисует экран поверх уже
|
||
// показанной Kitty-картинки — я предсказать не могу совсем: там нет
|
||
// реального терминала, чтобы проверить. Другие непроверенные места в
|
||
// проекте (например, зависимость на sqlite) — это "может не
|
||
// скомпилироваться, поправишь по ошибке компилятора". Здесь другое:
|
||
// код скомпилируется и, скорее всего, отработает без паники, вопрос
|
||
// только в том, что увидишь на экране — и тут я честно не знаю. Отсюда
|
||
// клавиша ctrl+v на вкладке Steganography — передать escape-код заново,
|
||
// если картинку перекрыло перерисовкой TUI.
|
||
func KittyEscape(pngData []byte) string {
|
||
b64 := base64.StdEncoding.EncodeToString(pngData)
|
||
const chunkSize = 4096
|
||
|
||
var b strings.Builder
|
||
for i := 0; i < len(b64); i += chunkSize {
|
||
end := i + chunkSize
|
||
if end > len(b64) {
|
||
end = len(b64)
|
||
}
|
||
chunk := b64[i:end]
|
||
more := 0
|
||
if end < len(b64) {
|
||
more = 1
|
||
}
|
||
if i == 0 {
|
||
fmt.Fprintf(&b, "\x1b_Ga=T,f=100,t=d,m=%d;%s\x1b\\", more, chunk)
|
||
} else {
|
||
fmt.Fprintf(&b, "\x1b_Gm=%d;%s\x1b\\", more, chunk)
|
||
}
|
||
}
|
||
return b.String()
|
||
}
|