Files
go-worm/lib/webcam/bmp.go
T

72 lines
1.8 KiB
Go

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
}