-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimage_format.go
234 lines (211 loc) · 6.55 KB
/
image_format.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
// Copyright ©2021-2022 by Richard A. Wilkes. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, version 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible With Secondary Licenses", as
// defined by the Mozilla Public License, version 2.0.
package unison
import (
"net/url"
"path"
"strings"
"github.com/ddkwork/golibrary/mylog"
)
// InvalidImageFormatStr is returned for as an error indicator for some methods on EncodedImageFormat.
const InvalidImageFormatStr = "\x00invalid"
// EncodedImageFormat holds the type of encoding an image was stored with.
type EncodedImageFormat uint8
// Possible values for EncodedImageFormat.
const (
BMP EncodedImageFormat = iota
GIF
ICO
JPEG
PNG
WBMP
WEBP
/*
The following formats, though supported in theory, fail to work with the cskia builds I've done.
PKM
KTX
ASTC
DNG
HEIF
*/
knownEncodedImageFormatCount
UnknownEncodedImageFormat EncodedImageFormat = 255
)
type imageFormatInfo struct {
Extensions []string
MimeTypes []string
UTI string
CanWrite bool
}
var knownImageFormats = []*imageFormatInfo{
{
Extensions: []string{".bmp", ".dib"},
MimeTypes: []string{"image/bmp", "image/x-bmp"},
UTI: "com.microsoft.bmp",
},
{
Extensions: []string{".gif"},
MimeTypes: []string{"image/gif"},
UTI: "com.compuserve.gif",
},
{
Extensions: []string{".ico"},
MimeTypes: []string{"image/x-icon", "image/vnd.microsoft.icon"},
UTI: "com.microsoft.ico",
},
{
Extensions: []string{".jpg", ".jpeg", ".jpe", ".jif", ".jfif", ".jfi"},
MimeTypes: []string{"image/jpeg"},
UTI: "public.jpeg",
CanWrite: true,
},
{
Extensions: []string{".png"},
MimeTypes: []string{"image/png"},
UTI: "public.png",
CanWrite: true,
},
{
Extensions: []string{".wbmp"},
MimeTypes: []string{"image/vnd.wap.wbmp"},
UTI: "com.adobe.wbmp",
},
{
Extensions: []string{".webp"},
MimeTypes: []string{"image/webp"},
UTI: "org.webmproject.webp",
CanWrite: true,
},
}
var (
// KnownImageFormatFormats holds the list of known image file formats.
KnownImageFormatFormats = make([]EncodedImageFormat, len(knownImageFormats))
// KnownImageFormatExtensions holds the list of known image file format extensions.
KnownImageFormatExtensions []string
mimeTypeToImageFormat = make(map[string]EncodedImageFormat)
extensionToImageFormat = make(map[string]EncodedImageFormat)
)
func init() {
for i, one := range knownImageFormats {
KnownImageFormatFormats[i] = EncodedImageFormat(i)
for _, ext := range one.Extensions {
extensionToImageFormat[ext] = EncodedImageFormat(i)
KnownImageFormatExtensions = append(KnownImageFormatExtensions, ext)
}
for _, mimeType := range one.MimeTypes {
mimeTypeToImageFormat[mimeType] = EncodedImageFormat(i)
}
}
}
func (e EncodedImageFormat) String() string {
if e < knownEncodedImageFormatCount {
return knownImageFormats[e].Extensions[0][1:]
}
return "unknown format"
}
// CanRead returns true if the format can be read.
func (e EncodedImageFormat) CanRead() bool {
return e < knownEncodedImageFormatCount
}
// CanWrite returns true if the format can be written.
func (e EncodedImageFormat) CanWrite() bool {
if e < knownEncodedImageFormatCount {
return knownImageFormats[e].CanWrite
}
return false
}
// Extensions returns the list of valid extensions for the format. An unknown / invalid format will return nil.
func (e EncodedImageFormat) Extensions() []string {
if e < knownEncodedImageFormatCount {
return knownImageFormats[e].Extensions
}
return nil
}
// Extension returns the primary extension for the format. An unknown / invalid format will return InvalidImageFormatStr.
func (e EncodedImageFormat) Extension() string {
if e < knownEncodedImageFormatCount {
return knownImageFormats[e].Extensions[0]
}
return InvalidImageFormatStr
}
// MimeTypes returns the list of valid mime types for the format. An unknown / invalid format will return nil.
func (e EncodedImageFormat) MimeTypes() []string {
if e < knownEncodedImageFormatCount {
return knownImageFormats[e].MimeTypes
}
return nil
}
// MimeType returns the primary mime type for the format. An unknown / invalid format will return InvalidImageFormatStr.
func (e EncodedImageFormat) MimeType() string {
if e < knownEncodedImageFormatCount {
return knownImageFormats[e].MimeTypes[0]
}
return InvalidImageFormatStr
}
// UTI returns the uniform type identifier for the format. An unknown / invalid format will return
// InvalidImageFormatStr.
func (e EncodedImageFormat) UTI() string {
if e < knownEncodedImageFormatCount {
return knownImageFormats[e].UTI
}
return InvalidImageFormatStr
}
// EncodedImageFormatForPath returns the EncodedImageFormat associated with the extension of the given path.
func EncodedImageFormatForPath(p string) EncodedImageFormat {
return EncodedImageFormatForExtension(path.Ext(p))
}
// EncodedImageFormatForExtension returns the EncodedImageFormat associated with the extension.
func EncodedImageFormatForExtension(ext string) EncodedImageFormat {
if !strings.HasPrefix(ext, ".") {
ext = "." + ext
}
if e, ok := extensionToImageFormat[strings.ToLower(ext)]; ok {
return e
}
return UnknownEncodedImageFormat
}
// EncodedImageFormatForMimeType returns the EncodedImageFormat associated with the mime type.
func EncodedImageFormatForMimeType(mimeType string) EncodedImageFormat {
if e, ok := mimeTypeToImageFormat[strings.ToLower(mimeType)]; ok {
return e
}
return UnknownEncodedImageFormat
}
// DistillImageSpecFor distills a file path or URL string into one that likely has an image we can read, or an empty
// string.
func DistillImageSpecFor(filePathOrURL string) string {
u := mylog.Check2(url.Parse(filePathOrURL))
switch u.Scheme {
case "file":
if e := EncodedImageFormatForPath(filePathOrURL); e.CanRead() {
return filePathOrURL
}
return ""
case "http", "https":
if e := EncodedImageFormatForPath(u.Path); e.CanRead() {
return filePathOrURL
}
if alt, ok := u.Query()["imgurl"]; ok && len(alt) > 0 {
return DistillImageSpecFor(alt[0])
}
const revisionLatest = "/revision/latest"
if strings.HasSuffix(u.Path, revisionLatest) {
u.RawPath = ""
u.Path = u.Path[:len(u.Path)-len(revisionLatest)]
return DistillImageSpecFor(u.String())
}
return ""
default:
}
// We may have been passed a raw file path... so try to open that
if e := EncodedImageFormatForPath(filePathOrURL); e.CanRead() {
return filePathOrURL
}
return ""
}