package webcam import ( "bytes" "encoding/binary" "errors" "fmt" "image" "image/jpeg" "image/png" ) func encodeImage(img image.Image, format string, quality int) ([]byte, string, error) { var buf bytes.Buffer if format == "jpeg" { err := jpeg.Encode(&buf, img, &jpeg.Options{Quality: quality}) return buf.Bytes(), "image/jpeg", err } err := png.Encode(&buf, img) return buf.Bytes(), "image/png", err } func decodeBMP(data []byte) (*image.RGBA, error) { if len(data) < 54 || data[0] != 'B' || data[1] != 'M' { return nil, errors.New("invalid bitmap") } offset := binary.LittleEndian.Uint32(data[10:14]) width := int(int32(binary.LittleEndian.Uint32(data[18:22]))) heightSigned := int32(binary.LittleEndian.Uint32(data[22:26])) bits := binary.LittleEndian.Uint16(data[28:30]) compression := binary.LittleEndian.Uint32(data[30:34]) if compression != 0 { return nil, fmt.Errorf("unsupported bmp compression %d", compression) } if bits != 24 && bits != 32 { return nil, fmt.Errorf("unsupported bmp bit depth %d", bits) } topDown := heightSigned < 0 height := int(heightSigned) if height < 0 { height = -height } if width <= 0 || height <= 0 || int(offset) >= len(data) { return nil, errors.New("invalid bmp dimensions") } bpp := int(bits / 8) rowSize := (width*bpp + 3) &^ 3 need := int(offset) + rowSize*height if need > len(data) { return nil, errors.New("truncated bmp") } img := image.NewRGBA(image.Rect(0, 0, width, height)) for y := 0; y < height; y++ { srcY := y if !topDown { srcY = height - 1 - y } row := data[int(offset)+srcY*rowSize:] for x := 0; x < width; x++ { i := x * bpp b, g, r := row[i], row[i+1], row[i+2] a := byte(255) if bpp == 4 { a = row[i+3] } off := (y*width + x) * 4 img.Pix[off], img.Pix[off+1], img.Pix[off+2], img.Pix[off+3] = r, g, b, a } } return img, nil }