Files
overlord/Overlord-Client/cmd/agent/capture/jpeg_turbo.go
T

74 lines
1.9 KiB
Go
Raw Normal View History

2026-03-05 00:04:26 -06:00
//go:build turbojpeg
package capture
import (
"bytes"
"image"
2026-07-30 14:16:34 -05:00
"image/color"
2026-03-05 00:04:26 -06:00
ljpeg "github.com/pixiv/go-libjpeg/jpeg"
)
func encodeJPEG(img image.Image, quality int) ([]byte, error) {
opts := &ljpeg.EncoderOptions{
2026-07-30 14:16:34 -05:00
Quality: jpegEncoderQuality(quality),
2026-03-05 00:04:26 -06:00
OptimizeCoding: true,
DCTMethod: ljpeg.DCTISlow,
}
buf := bytes.Buffer{}
2026-07-30 14:16:34 -05:00
if err := ljpeg.Encode(&buf, jpeg444Image(img), opts); err != nil {
2026-03-05 00:04:26 -06:00
return nil, err
}
return buf.Bytes(), nil
}
2026-05-21 23:28:06 -05:00
func encodeJPEGToBuf(dst *bytes.Buffer, img image.Image, quality int) error {
opts := &ljpeg.EncoderOptions{
2026-07-30 14:16:34 -05:00
Quality: jpegEncoderQuality(quality),
2026-05-21 23:28:06 -05:00
OptimizeCoding: true,
DCTMethod: ljpeg.DCTISlow,
}
2026-07-30 14:16:34 -05:00
return ljpeg.Encode(dst, jpeg444Image(img), opts)
}
// libjpeg preserves the source YCbCr sampling factors, unlike Go's standard
// JPEG encoder, so TurboJPEG builds can retain full chroma resolution.
func jpeg444Image(src image.Image) image.Image {
if src == nil {
return src
}
if ycbcr, ok := src.(*image.YCbCr); ok && ycbcr.SubsampleRatio == image.YCbCrSubsampleRatio444 {
return src
}
bounds := src.Bounds()
dst := image.NewYCbCr(bounds, image.YCbCrSubsampleRatio444)
if rgba, ok := src.(*image.RGBA); ok {
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
srcOffset := rgba.PixOffset(bounds.Min.X, y)
dstOffset := dst.YOffset(bounds.Min.X, y)
for x := 0; x < bounds.Dx(); x++ {
i := srcOffset + x*4
yy, cb, cr := color.RGBToYCbCr(rgba.Pix[i], rgba.Pix[i+1], rgba.Pix[i+2])
dst.Y[dstOffset+x] = yy
dst.Cb[dstOffset+x] = cb
dst.Cr[dstOffset+x] = cr
}
}
return dst
}
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
pixel := color.NRGBAModel.Convert(src.At(x, y)).(color.NRGBA)
yy, cb, cr := color.RGBToYCbCr(pixel.R, pixel.G, pixel.B)
offset := dst.YOffset(x, y)
dst.Y[offset] = yy
dst.Cb[offset] = cb
dst.Cr[offset] = cr
}
}
return dst
2026-05-21 23:28:06 -05:00
}