1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-01-08 10:45:04 +02:00
imgproxy/image_size/image_meta.go
2019-10-10 19:20:25 +06:00

73 lines
1.2 KiB
Go

package imagesize
import (
"bufio"
"errors"
"io"
"sync"
"sync/atomic"
)
type Meta struct {
Format string
Width, Height int
}
type format struct {
magic string
decodeMeta func(io.Reader) (*Meta, error)
}
type reader interface {
io.Reader
Peek(int) ([]byte, error)
}
var (
formatsMu sync.Mutex
atomicFormats atomic.Value
ErrFormat = errors.New("unknown image format")
)
func asReader(r io.Reader) reader {
if rr, ok := r.(reader); ok {
return rr
}
return bufio.NewReader(r)
}
func matchMagic(magic string, b []byte) bool {
if len(magic) != len(b) {
return false
}
for i, c := range b {
if magic[i] != c && magic[i] != '?' {
return false
}
}
return true
}
func RegisterFormat(magic string, decodeMeta func(io.Reader) (*Meta, error)) {
formatsMu.Lock()
defer formatsMu.Unlock()
formats, _ := atomicFormats.Load().([]format)
atomicFormats.Store(append(formats, format{magic, decodeMeta}))
}
func DecodeMeta(r io.Reader) (*Meta, error) {
rr := asReader(r)
formats, _ := atomicFormats.Load().([]format)
for _, f := range formats {
b, err := rr.Peek(len(f.magic))
if err == nil && matchMagic(f.magic, b) {
return f.decodeMeta(rr)
}
}
return nil, ErrFormat
}