forked from jurgen-kluft/Golem
/
JPEG.go
110 lines (93 loc) · 2.24 KB
/
JPEG.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
package ImgMeta
import (
"encoding/binary"
"fmt"
"os"
)
// ============================================== JPEG ==============================================
type exifError struct {
descr string
}
func (e *exifError) Error() string {
return fmt.Sprintf("%s", e.descr)
}
// ReadJpeg will read all sections from the image data
func ReadJpeg(fhnd *os.File) (image Image, err error) {
image = Image{apps: map[string]APP{}}
reader, n, err := newJpegReader(fhnd)
if n == 0 || err != nil {
return
}
marker := uint16(0)
binary.Read(reader, binary.BigEndian, &marker)
if marker != cSOI {
return image, &exifError{"Wrong format"}
}
//fmt.Println("Reading JPEG APP segments")
appHeader := make([]byte, 2)
for true {
n, err = reader.Read(appHeader)
if n != len(appHeader) || err != nil {
break
}
if appHeader[0] == 0xFF {
for appHeader[1] == 0xFF {
appHeader[1] = reader.ReadByte()
}
marker = binary.BigEndian.Uint16(appHeader)
segment, ok := aSegments[marker]
if !ok {
return image, &exifError{"Unidentified APP marker encountered"}
}
//fmt.Printf("Encountered marker %s\n", segment.name)
app, err := segment.reader(marker, reader)
if err != nil {
return image, err
}
if app == nil {
break
}
//fmt.Printf("Registering APP %s, Length:%v\n", app.Name(), app.Length())
image.apps[app.Name()] = app
if segment.name == "IPTC" {
break
}
} else {
// Not a section marker
marker = binary.BigEndian.Uint16(appHeader)
return image, &exifError{fmt.Sprintf("Encountered invalid section marker 0x%X", marker)}
}
}
return image, nil
}
type JpegReader struct {
cursor uint64
data []byte
}
func (b *JpegReader) Read(p []byte) (n int, err error) {
for i := 0; i < len(p); i++ {
p[i] = b.data[b.cursor]
b.cursor++
}
return len(p), nil
}
func (b *JpegReader) ReadByte() byte {
v := b.data[b.cursor]
b.cursor++
return v
}
func newJpegReader(fhnd *os.File) (reader *JpegReader, n int, err error) {
stat, err := fhnd.Stat()
reader = &JpegReader{cursor: 0, data: nil}
if err != nil {
return reader, 0, err
}
size := stat.Size()
reader.cursor = 0
reader.data = make([]byte, size)
n, err = fhnd.Read(reader.data)
return
}
func (b *JpegReader) pos() uint64 {
return b.cursor
}