forked from rai-project/image
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathread.go
86 lines (75 loc) · 2.13 KB
/
read.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package image
import (
"bufio"
"io"
opentracing "github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/c3sr/image/types"
"github.com/c3sr/tracer"
)
// A reader is an io.Reader that can also peek ahead.
type reader interface {
io.Reader
Peek(int) ([]byte, error)
}
// asReader converts an io.Reader to a reader.
func asReader(r io.Reader) reader {
if rr, ok := r.(reader); ok {
return rr
}
return bufio.NewReader(r)
}
// TODO: replace with https://github.com/h2non/filetype/blob/master/matchers/image.go
func getFormat(reader reader) (string, error) {
formats := map[string]string{
"jpeg": "\xff\xd8",
"png": "\x89PNG\r\n\x1a\n",
"gif": "GIF8?a",
"bmp": "BM????\x00\x00\x00\x00",
}
for format, magic := range formats {
m, err := reader.Peek(len(magic))
if err != nil {
continue
}
if string(m) == magic {
return format, nil
}
}
return "", errors.New("input is not a valid image format")
}
func Read(r io.Reader, opts ...Option) (types.Image, error) {
options := NewOptions(opts...)
reader := asReader(r)
format, err := getFormat(reader)
if err != nil {
return nil, err
}
decoder, err := getDecoder(format, options)
if err != nil {
return nil, err
}
if options.ctx != nil && opentracing.SpanFromContext(options.ctx) != nil {
if span, ctx := tracer.StartSpanFromContext(options.ctx, tracer.APPLICATION_TRACE, "read", opentracing.Tags{"format": format}); span != nil {
options.ctx = ctx
defer span.Finish()
}
}
img, err := decodeReader(decoder, reader, options)
if err != nil {
return nil, errors.Wrap(err, "cannot decode reader")
}
switch img.(type) {
case *types.RGBImage, *types.BGRImage:
if options.resizeWidth == 0 && options.resizeHeight == 0 && options.maxDimension == nil && options.minDimension == nil {
return img, nil
}
if img.Bounds().Dx() == options.resizeWidth && img.Bounds().Dy() == options.resizeHeight && options.maxDimension == nil && options.minDimension == nil {
return img, nil
}
return Resize(img, opts...)
default:
return nil, errors.New("invalid return type for image read")
}
return nil, errors.New("unreachable in image read")
}