-
Notifications
You must be signed in to change notification settings - Fork 0
/
image.go
146 lines (116 loc) · 2.37 KB
/
image.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package picsum
import (
"errors"
"fmt"
"io"
"net/http"
"net/url"
"unicode/utf8"
)
type Image struct {
ID string
Content []byte
}
type ImageProvider struct {
url string
}
func Err404Image() error {
return errors.New("404 not found")
}
func (p *ImageProvider) Load() (*Image, error) {
res, err := http.Get(p.url)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return nil, Err404Image()
}
id := res.Header.Get("Picsum-Id")
content, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
return &Image{
ID: id,
Content: content,
}, nil
}
type ImageFormat uint8
const (
JPG ImageFormat = iota
WebP
)
type IdentifierType uint8
const (
ID IdentifierType = iota
Seed
)
type identifier struct {
value string
idType IdentifierType
}
type ImageOptions struct {
width int
height int
format ImageFormat
identifier *identifier
grayscale bool
blurDepth int
}
func (opt *ImageOptions) Filter(grayscale bool, blurDepth int) *ImageOptions {
opt.grayscale = grayscale
opt.blurDepth = blurDepth
return opt
}
func (opt *ImageOptions) Format(format ImageFormat) *ImageOptions {
opt.format = format
return opt
}
func (opt *ImageOptions) Identifier(value string, idType IdentifierType) *ImageOptions {
if utf8.RuneCountInString(value) == 0 {
value = "1"
idType = ID
}
opt.identifier = &identifier{value, idType}
return opt
}
func NewImageOptions(width, height int) *ImageOptions {
options := new(ImageOptions)
options.width = width
options.height = height
options.format = JPG
return options
}
func NewImageProvider(options *ImageOptions) *ImageProvider {
imageURL := "https://picsum.photos/"
identifier := options.identifier
if identifier != nil {
switch identifier.idType {
case ID:
imageURL += fmt.Sprintf("id/%s/", identifier.value)
case Seed:
imageURL += fmt.Sprintf("seed/%s/", identifier.value)
}
}
imageURL += fmt.Sprintf("%d/%d",
options.width, options.height)
switch options.format {
case JPG:
imageURL += ".jpg"
case WebP:
imageURL += ".webp"
}
query := url.Values{}
if options.grayscale {
query.Set("grayscale", "")
}
if options.blurDepth != 0 {
query.Set("blur", fmt.Sprintf("%d", options.blurDepth))
}
queryString := query.Encode()
if queryString != "" {
imageURL += "?" + queryString
}
return &ImageProvider{imageURL}
}