...
Source file
src/image/format.go
Documentation: image
1
2
3
4
5 package image
6
7 import (
8 "bufio"
9 "errors"
10 "io"
11 )
12
13
14 var ErrFormat = errors.New("image: unknown format")
15
16
17 type format struct {
18 name, magic string
19 decode func(io.Reader) (Image, error)
20 decodeConfig func(io.Reader) (Config, error)
21 }
22
23
24 var formats []format
25
26
27
28
29
30
31
32 func RegisterFormat(name, magic string, decode func(io.Reader) (Image, error), decodeConfig func(io.Reader) (Config, error)) {
33 formats = append(formats, format{name, magic, decode, decodeConfig})
34 }
35
36
37 type reader interface {
38 io.Reader
39 Peek(int) ([]byte, error)
40 }
41
42
43 func asReader(r io.Reader) reader {
44 if rr, ok := r.(reader); ok {
45 return rr
46 }
47 return bufio.NewReader(r)
48 }
49
50
51 func match(magic string, b []byte) bool {
52 if len(magic) != len(b) {
53 return false
54 }
55 for i, c := range b {
56 if magic[i] != c && magic[i] != '?' {
57 return false
58 }
59 }
60 return true
61 }
62
63
64 func sniff(r reader) format {
65 for _, f := range formats {
66 b, err := r.Peek(len(f.magic))
67 if err == nil && match(f.magic, b) {
68 return f
69 }
70 }
71 return format{}
72 }
73
74
75
76
77
78 func Decode(r io.Reader) (Image, string, error) {
79 rr := asReader(r)
80 f := sniff(rr)
81 if f.decode == nil {
82 return nil, "", ErrFormat
83 }
84 m, err := f.decode(rr)
85 return m, f.name, err
86 }
87
88
89
90
91
92 func DecodeConfig(r io.Reader) (Config, string, error) {
93 rr := asReader(r)
94 f := sniff(rr)
95 if f.decodeConfig == nil {
96 return Config{}, "", ErrFormat
97 }
98 c, err := f.decodeConfig(rr)
99 return c, f.name, err
100 }
101
View as plain text