generated from bep/golibtemplate
-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathimagedecoder_jpg.go
134 lines (113 loc) · 2.54 KB
/
imagedecoder_jpg.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
// Copyright 2024 Bjørn Erik Pedersen
// SPDX-License-Identifier: MIT
package imagemeta
import (
"bytes"
"io"
)
type imageDecoderJPEG struct {
*baseStreamingDecoder
}
func (e *imageDecoderJPEG) decode() error {
// JPEG SOI marker.
soi, err := e.read2E()
if err != nil {
return nil
}
if soi != markerSOI {
return nil
}
// These are the sources we support.
sourceSet := EXIF | IPTC | XMP
// Remove sources that are not requested.
sourceSet = sourceSet & e.opts.Sources
for {
if sourceSet.IsZero() {
// Done.
return nil
}
marker := e.read2()
if e.isEOF {
return nil
}
if marker == 0 {
continue
}
if marker == markerSOS {
// Start of scan. We're done.
return nil
}
// Read the 16-bit length of the segment. The value includes the 2 bytes for the
// length itself, so we subtract 2 to get the number of remaining bytes.
length := e.read2()
if length < 2 {
return errInvalidFormat
}
length -= 2
if marker == markerApp1EXIF && sourceSet.Has(EXIF) {
sourceSet = sourceSet.Remove(EXIF)
if err := e.handleEXIF(int64(length)); err != nil {
return err
}
continue
}
if marker == markerApp13 && sourceSet.Has(IPTC) {
sourceSet = sourceSet.Remove(IPTC)
if err := e.handleIPTC(int(length)); err != nil {
return err
}
continue
}
if marker == markerrApp1XMP && sourceSet.Has(XMP) {
const xmpMarkerLen = 29
oldPos := e.pos()
b, err := e.readBytesVolatileE(xmpMarkerLen)
if err != nil && err != io.ErrUnexpectedEOF {
return err
}
if err == nil && bytes.Equal(b, markerXMP) {
length -= xmpMarkerLen
sourceSet = sourceSet.Remove(XMP)
r := io.LimitReader(e.r, int64(length))
if err := decodeXMP(r, e.opts); err != nil {
return err
}
continue
} else {
// Not XMP, rewind.
e.seek(oldPos)
}
}
e.skip(int64(length))
}
}
func (e *imageDecoderJPEG) handleEXIF(length int64) error {
thumbnailOffset := e.pos()
r, err := e.bufferedReader(length)
if err != nil {
return err
}
defer r.Close()
exifr := newMetaDecoderEXIF(r, e.byteOrder, thumbnailOffset, e.opts)
header := exifr.read4()
if header != exifHeader {
return err
}
exifr.skip(2)
if err := exifr.decode(); err != nil {
return err
}
return nil
}
func (e *imageDecoderJPEG) handleIPTC(length int) error {
const headerLength = 14
// Skip the IPTC header.
e.skip(headerLength)
r, err := e.bufferedReader(int64(length - headerLength))
if err != nil {
return err
}
defer r.Close()
dec := newMetaDecoderIPTC(r, e.opts)
return dec.decodeBlocks()
}