Skip to content

Commit 3e30c6c

Browse files
committed
fix: cached Sixel encoding in RenderImageToStdout
Signed-off-by: drew <[email protected]>
1 parent 75f74a9 commit 3e30c6c

1 file changed

Lines changed: 21 additions & 11 deletions

File tree

view/html.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,11 @@ func ImageProtocolSupported() bool {
257257
return imageProtocolSupported()
258258
}
259259

260+
// SixelSupported returns true if the terminal uses the Sixel graphics protocol.
261+
func SixelSupported() bool {
262+
return sixelSupported()
263+
}
264+
260265
// imageProtocolSupported checks if any supported image protocol terminal is detected.
261266
func imageProtocolSupported() bool {
262267
return sixelSupported() || kittySupported() || ghosttySupported() || iterm2Supported() ||
@@ -581,16 +586,20 @@ func RenderImageToStdout(placement *ImagePlacement, screenRow int, screenCol ...
581586
// Priority: Sixel in multiplexers
582587
if sixelSupported() {
583588
debugImageProtocol("Sixel: RenderImageToStdout row=%d col=%d base64len=%d", screenRow, col, len(placement.Base64))
584-
seq := sixelImageEscapeOnly(placement.Base64)
585-
if seq == "" {
586-
debugImageProtocol("Sixel: sixelImageEscapeOnly returned empty")
587-
return
589+
590+
// Encode once, reuse cached Sixel on subsequent renders (like Kitty's upload-once pattern)
591+
if placement.SixelEncoded == "" {
592+
placement.SixelEncoded = sixelImageEscapeOnly(placement.Base64)
593+
if placement.SixelEncoded == "" {
594+
debugImageProtocol("Sixel: sixelImageEscapeOnly returned empty")
595+
return
596+
}
588597
}
589598

590-
debugImageProtocol("Sixel: rendering %d bytes at row=%d col=%d", len(seq), screenRow+1, col)
599+
debugImageProtocol("Sixel: rendering %d bytes at row=%d col=%d", len(placement.SixelEncoded), screenRow+1, col)
591600
// Position cursor + render Sixel
592601
fmt.Fprintf(os.Stdout, "\x1b[s\x1b[%d;%dH%s\x1b[u",
593-
screenRow+1, col, seq)
602+
screenRow+1, col, placement.SixelEncoded)
594603
os.Stdout.Sync()
595604
return
596605
}
@@ -640,11 +649,12 @@ type InlineImage struct {
640649
// line in the email body. Images are rendered directly to stdout (bypassing
641650
// bubbletea's cell-based renderer which cannot handle graphics protocols).
642651
type ImagePlacement struct {
643-
Line int // Line number in the processed body text where the image starts
644-
Base64 string // Base64-encoded image data (PNG)
645-
Rows int // Number of terminal rows the image occupies
646-
Uploaded bool // Whether the image has been uploaded to the terminal via Kitty ID
647-
ID uint32 // Kitty image ID for display-by-reference
652+
Line int // Line number in the processed body text where the image starts
653+
Base64 string // Base64-encoded image data (PNG)
654+
Rows int // Number of terminal rows the image occupies
655+
Uploaded bool // Whether the image has been uploaded to the terminal via Kitty ID
656+
ID uint32 // Kitty image ID for display-by-reference
657+
SixelEncoded string // Cached Sixel escape sequence (encode once, reuse on scroll)
648658
}
649659

650660
// ProcessBodyWithInline renders the body and resolves CID inline images when provided.

0 commit comments

Comments
 (0)