encoder.go

 1package kitty
 2
 3import (
 4	"compress/zlib"
 5	"fmt"
 6	"image"
 7	"image/png"
 8	"io"
 9)
10
11// Encoder is an encoder for the Kitty graphics protocol. It supports encoding
12// images in the 24-bit [RGB], 32-bit [RGBA], and [PNG] formats, and
13// compressing the data using zlib.
14// The default format is 32-bit [RGBA].
15type Encoder struct {
16	// Uses zlib compression.
17	Compress bool
18
19	// Can be one of [RGBA], [RGB], or [PNG].
20	Format int
21}
22
23// Encode encodes the image data in the specified format and writes it to w.
24func (e *Encoder) Encode(w io.Writer, m image.Image) error {
25	if m == nil {
26		return nil
27	}
28
29	if e.Compress {
30		zw := zlib.NewWriter(w)
31		defer zw.Close() //nolint:errcheck
32		w = zw
33	}
34
35	if e.Format == 0 {
36		e.Format = RGBA
37	}
38
39	switch e.Format {
40	case RGBA, RGB:
41		bounds := m.Bounds()
42		for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
43			for x := bounds.Min.X; x < bounds.Max.X; x++ {
44				r, g, b, a := m.At(x, y).RGBA()
45				switch e.Format {
46				case RGBA:
47					w.Write([]byte{byte(r >> 8), byte(g >> 8), byte(b >> 8), byte(a >> 8)}) //nolint:errcheck
48				case RGB:
49					w.Write([]byte{byte(r >> 8), byte(g >> 8), byte(b >> 8)}) //nolint:errcheck
50				}
51			}
52		}
53
54	case PNG:
55		if err := png.Encode(w, m); err != nil {
56			return fmt.Errorf("failed to encode PNG: %w", err)
57		}
58
59	default:
60		return fmt.Errorf("unsupported format: %d", e.Format)
61	}
62
63	return nil
64}