2019-12-25 11:06:15 +02:00
|
|
|
package imagemeta
|
2019-09-30 13:28:38 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/binary"
|
|
|
|
"io"
|
2021-05-13 15:58:44 +02:00
|
|
|
|
2021-09-30 16:23:30 +02:00
|
|
|
"github.com/imgproxy/imgproxy/v3/imagetype"
|
2019-09-30 13:28:38 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
var bmpMagick = []byte("BM")
|
|
|
|
|
|
|
|
type BmpFormatError string
|
|
|
|
|
|
|
|
func (e BmpFormatError) Error() string { return "invalid BMP format: " + string(e) }
|
|
|
|
|
2019-12-25 11:06:15 +02:00
|
|
|
func DecodeBmpMeta(r io.Reader) (Meta, error) {
|
2019-09-30 13:28:38 +02:00
|
|
|
var tmp [26]byte
|
|
|
|
|
|
|
|
if _, err := io.ReadFull(r, tmp[:]); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !bytes.Equal(tmp[:2], bmpMagick) {
|
|
|
|
return nil, BmpFormatError("malformed header")
|
|
|
|
}
|
|
|
|
|
|
|
|
infoSize := binary.LittleEndian.Uint32(tmp[14:18])
|
|
|
|
|
|
|
|
var width, height int
|
|
|
|
|
|
|
|
if infoSize >= 40 {
|
|
|
|
width = int(binary.LittleEndian.Uint32(tmp[18:22]))
|
2021-06-23 11:52:25 +02:00
|
|
|
height = int(int32(binary.LittleEndian.Uint32(tmp[22:26])))
|
2019-09-30 13:28:38 +02:00
|
|
|
} else {
|
|
|
|
// CORE
|
|
|
|
width = int(binary.LittleEndian.Uint16(tmp[18:20]))
|
2021-06-23 11:52:25 +02:00
|
|
|
height = int(int16(binary.LittleEndian.Uint16(tmp[20:22])))
|
|
|
|
}
|
|
|
|
|
|
|
|
// height can be negative in Windows bitmaps
|
|
|
|
if height < 0 {
|
|
|
|
height = -height
|
2019-09-30 13:28:38 +02:00
|
|
|
}
|
|
|
|
|
2019-12-25 11:06:15 +02:00
|
|
|
return &meta{
|
2021-05-13 15:58:44 +02:00
|
|
|
format: imagetype.BMP,
|
2019-12-25 11:06:15 +02:00
|
|
|
width: width,
|
|
|
|
height: height,
|
2019-09-30 13:28:38 +02:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
RegisterFormat(string(bmpMagick), DecodeBmpMeta)
|
|
|
|
}
|