encoder.go 1.3 KB

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