mirror of
https://github.com/gen2brain/cam2ip.git
synced 2025-12-16 04:18:39 +00:00
Add support for YUYV/YUY2 format
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
package camera
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
)
|
||||
|
||||
// Options .
|
||||
type Options struct {
|
||||
Index int
|
||||
@@ -10,3 +16,84 @@ type Options struct {
|
||||
Timestamp bool
|
||||
TimeFormat string
|
||||
}
|
||||
|
||||
var (
|
||||
yuy2FourCC = fourcc("YUY2")
|
||||
yuyvFourCC = fourcc("YUYV")
|
||||
mjpgFourCC = fourcc("MJPG")
|
||||
)
|
||||
|
||||
func fourcc(b string) uint32 {
|
||||
return uint32(b[0]) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24)
|
||||
}
|
||||
|
||||
func bmp24ToRgba(data []byte, dst *image.RGBA) error {
|
||||
r := bytes.NewReader(data)
|
||||
|
||||
width := dst.Bounds().Dx()
|
||||
height := dst.Bounds().Dy()
|
||||
|
||||
// There are 3 bytes per pixel, and each row is 4-byte aligned.
|
||||
b := make([]byte, (3*width+3)&^3)
|
||||
|
||||
// BMP images are stored bottom-up rather than top-down.
|
||||
for y := height - 1; y >= 0; y-- {
|
||||
_, err := r.Read(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := dst.Pix[y*dst.Stride : y*dst.Stride+width*4]
|
||||
for i, j := 0, 0; i < len(p); i, j = i+4, j+3 {
|
||||
// BMP images are stored in BGR order rather than RGB order.
|
||||
p[i+0] = b[j+2]
|
||||
p[i+1] = b[j+1]
|
||||
p[i+2] = b[j+0]
|
||||
p[i+3] = 0xFF
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// yuy2ToYCbCr422 converts a YUY2 (YUYV) byte slice to an image.YCbCr with YCbCrSubsampleRatio422 (I422).
|
||||
func yuy2ToYCbCr422(data []byte, dst *image.YCbCr) error {
|
||||
if dst.SubsampleRatio != image.YCbCrSubsampleRatio422 {
|
||||
return fmt.Errorf("subsample ratio must be 422, got %s", dst.SubsampleRatio.String())
|
||||
}
|
||||
|
||||
width := dst.Bounds().Dx()
|
||||
height := dst.Bounds().Dy()
|
||||
|
||||
if width%2 != 0 {
|
||||
return fmt.Errorf("width must be even for YUY2")
|
||||
}
|
||||
|
||||
if len(data) != width*height*2 {
|
||||
return fmt.Errorf("invalid data length for YUY2")
|
||||
}
|
||||
|
||||
stride := width * 2 // 2 bytes per pixel
|
||||
|
||||
for y := 0; y < height; y++ {
|
||||
for x := 0; x < width; x += 2 {
|
||||
idx := y*stride + x*2
|
||||
|
||||
y0 := data[idx+0]
|
||||
cb := data[idx+1]
|
||||
y1 := data[idx+2]
|
||||
cr := data[idx+3]
|
||||
|
||||
// Y plane: every pixel
|
||||
dst.Y[y*dst.YStride+x+0] = y0
|
||||
dst.Y[y*dst.YStride+x+1] = y1
|
||||
|
||||
// Cb/Cr plane: every 2 pixels (422)
|
||||
off := y*dst.CStride + x/2
|
||||
dst.Cb[off] = cb
|
||||
dst.Cr[off] = cr
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user