-
Notifications
You must be signed in to change notification settings - Fork 0
/
img.go
107 lines (88 loc) · 2.42 KB
/
img.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
package dirsyn
/*
JPEG returns an error following an analysis of x in the context of a JFIF
enveloped payload, which resembles the following:
+- NULL (CTRL+@)
/ +- DATA LINK ESCAPE (CTRL+P)
/ / +- ENVELOPE LITERAL
+ + |
ÿ Ø ÿ à | | | ÿ Ù
-- -- -- -- -- -- ---- -- --
<SOF> FF D8 FF 0E 00 10 JFIF <variable image data> FF D9 <EOF>
Note that only the envelope elements -- specifically the header and footer --
are read. Actual image data is skipped for performance reasons.
Valid input values are string and []byte.
If the input value is a string, it is assumed the value leads to a path
and filename of a JPEG image file.
If the input value is a []byte instance, it may be raw JPEG data, or Base64
encoded JPEG data. If Base64 encoded, it is decoded and processed.
All other input types result in an error.
Aside from the error instance, there is no return type for parsed JPEG
content, as this would not serve any useful purpose to end users in any
of the intended use cases for this package.
See also [§ 3.3.17 of RFC 4517].
[§ 3.3.17 of RFC 4517]: https://datatracker.ietf.org/doc/html/rfc4517#section-3.3.17
*/
func (r RFC4517) JPEG(x any) error {
return marshalJPEG(x)
}
func jPEG(x any) (result Boolean) {
result.Set(marshalJPEG(x))
return
}
func marshalJPEG(x any) (err error) {
var raw []uint8
switch tv := x.(type) {
case string:
// Read from file
if raw, err = readFile(tv); err == nil {
// Self-execute using the byte payload
err = marshalJPEG(raw)
return
}
case []uint8:
if len(tv) <= 12 {
err = errorBadLength("JPEG", len(tv))
} else {
if isBase64(string(tv)) {
var dec []byte
dec, err = b64dec(tv)
raw = dec
} else {
raw = tv
}
}
default:
err = errorBadType("JPEG")
}
if err != nil {
return
}
header := []rune{
'\u00FF',
'\u00D8',
'\u00FF',
'\u00E0',
'\u0000',
'\u0010',
'J',
'F',
'I',
'F',
}
for idx, h := range header {
if h != rune(raw[idx]) {
err = errorTxt("Incompatible character for JPEG header: " + string(h))
return
}
}
footer := []rune{
'\u00FF', // len-2
'\u00D9', // len-1
}
if rune(raw[len(raw)-2]) != footer[0] ||
rune(raw[len(raw)-1]) != footer[1] {
err = errorTxt("Incompatible character for JPEG footer: " + string(raw[len(raw)-2:]))
}
return
}