1 package exif
2
3 import (
4 "fmt"
5 "io"
6
7 "encoding/binary"
8
9 "github.com/dsoprea/go-logging"
10
11 "github.com/dsoprea/go-exif/v3/common"
12 "github.com/dsoprea/go-exif/v3/undefined"
13 )
14
15 var (
16 iteLogger = log.NewLogger("exif.ifd_tag_entry")
17 )
18
19
20 type IfdTagEntry struct {
21 tagId uint16
22 tagIndex int
23 tagType exifcommon.TagTypePrimitive
24 unitCount uint32
25 valueOffset uint32
26 rawValueOffset []byte
27
28
29
30 childIfdName string
31
32
33
34 childIfdPath string
35
36
37
38 childFqIfdPath string
39
40
41
42 ifdIdentity *exifcommon.IfdIdentity
43
44 isUnhandledUnknown bool
45
46 rs io.ReadSeeker
47 byteOrder binary.ByteOrder
48
49 tagName string
50 }
51
52 func newIfdTagEntry(ii *exifcommon.IfdIdentity, tagId uint16, tagIndex int, tagType exifcommon.TagTypePrimitive, unitCount uint32, valueOffset uint32, rawValueOffset []byte, rs io.ReadSeeker, byteOrder binary.ByteOrder) *IfdTagEntry {
53 return &IfdTagEntry{
54 ifdIdentity: ii,
55 tagId: tagId,
56 tagIndex: tagIndex,
57 tagType: tagType,
58 unitCount: unitCount,
59 valueOffset: valueOffset,
60 rawValueOffset: rawValueOffset,
61 rs: rs,
62 byteOrder: byteOrder,
63 }
64 }
65
66
67 func (ite *IfdTagEntry) String() string {
68 return fmt.Sprintf("IfdTagEntry<TAG-IFD-PATH=[%s] TAG-ID=(0x%04x) TAG-TYPE=[%s] UNIT-COUNT=(%d)>", ite.ifdIdentity.String(), ite.tagId, ite.tagType.String(), ite.unitCount)
69 }
70
71
72
73
74
75 func (ite *IfdTagEntry) TagName() string {
76 return ite.tagName
77 }
78
79
80
81
82 func (ite *IfdTagEntry) setTagName(tagName string) {
83 ite.tagName = tagName
84 }
85
86
87 func (ite *IfdTagEntry) IfdPath() string {
88 return ite.ifdIdentity.String()
89 }
90
91
92
93 func (ite *IfdTagEntry) TagId() uint16 {
94 return ite.tagId
95 }
96
97
98
99 func (ite *IfdTagEntry) IsThumbnailOffset() bool {
100 return ite.tagId == ThumbnailOffsetTagId && ite.ifdIdentity.String() == ThumbnailFqIfdPath
101 }
102
103
104
105 func (ite *IfdTagEntry) IsThumbnailSize() bool {
106 return ite.tagId == ThumbnailSizeTagId && ite.ifdIdentity.String() == ThumbnailFqIfdPath
107 }
108
109
110 func (ite *IfdTagEntry) TagType() exifcommon.TagTypePrimitive {
111 return ite.tagType
112 }
113
114
115 func (ite *IfdTagEntry) updateTagType(tagType exifcommon.TagTypePrimitive) {
116 ite.tagType = tagType
117 }
118
119
120 func (ite *IfdTagEntry) UnitCount() uint32 {
121 return ite.unitCount
122 }
123
124
125 func (ite *IfdTagEntry) updateUnitCount(unitCount uint32) {
126 ite.unitCount = unitCount
127 }
128
129
130
131
132 func (ite *IfdTagEntry) getValueOffset() uint32 {
133 return ite.valueOffset
134 }
135
136
137 func (ite *IfdTagEntry) GetRawBytes() (rawBytes []byte, err error) {
138 defer func() {
139 if state := recover(); state != nil {
140 err = log.Wrap(state.(error))
141 }
142 }()
143
144 valueContext := ite.getValueContext()
145
146 if ite.tagType == exifcommon.TypeUndefined {
147 value, err := exifundefined.Decode(valueContext)
148 if err != nil {
149 if err == exifcommon.ErrUnhandledUndefinedTypedTag {
150 ite.setIsUnhandledUnknown(true)
151 return nil, exifundefined.ErrUnparseableValue
152 } else if err == exifundefined.ErrUnparseableValue {
153 return nil, err
154 } else {
155 log.Panic(err)
156 }
157 }
158
159
160
161
162 rawBytes, _, err := exifundefined.Encode(value, ite.byteOrder)
163 log.PanicIf(err)
164
165 return rawBytes, nil
166 }
167
168 rawBytes, err = valueContext.ReadRawEncoded()
169 log.PanicIf(err)
170
171 return rawBytes, nil
172 }
173
174
175 func (ite *IfdTagEntry) Value() (value interface{}, err error) {
176 defer func() {
177 if state := recover(); state != nil {
178 err = log.Wrap(state.(error))
179 }
180 }()
181
182 valueContext := ite.getValueContext()
183
184 if ite.tagType == exifcommon.TypeUndefined {
185 var err error
186
187 value, err = exifundefined.Decode(valueContext)
188 if err != nil {
189 if err == exifcommon.ErrUnhandledUndefinedTypedTag || err == exifundefined.ErrUnparseableValue {
190 return nil, err
191 }
192
193 log.Panic(err)
194 }
195 } else {
196 var err error
197
198 value, err = valueContext.Values()
199 log.PanicIf(err)
200 }
201
202 return value, nil
203 }
204
205
206 func (ite *IfdTagEntry) Format() (phrase string, err error) {
207 defer func() {
208 if state := recover(); state != nil {
209 err = log.Wrap(state.(error))
210 }
211 }()
212
213 value, err := ite.Value()
214 if err != nil {
215 if err == exifcommon.ErrUnhandledUndefinedTypedTag {
216 return exifundefined.UnparseableUnknownTagValuePlaceholder, nil
217 } else if err == exifundefined.ErrUnparseableValue {
218 return exifundefined.UnparseableHandledTagValuePlaceholder, nil
219 }
220
221 log.Panic(err)
222 }
223
224 phrase, err = exifcommon.FormatFromType(value, false)
225 log.PanicIf(err)
226
227 return phrase, nil
228 }
229
230
231 func (ite *IfdTagEntry) FormatFirst() (phrase string, err error) {
232 defer func() {
233 if state := recover(); state != nil {
234 err = log.Wrap(state.(error))
235 }
236 }()
237
238
239
240 value, err := ite.Value()
241 if err != nil {
242 if err == exifcommon.ErrUnhandledUndefinedTypedTag {
243 return exifundefined.UnparseableUnknownTagValuePlaceholder, nil
244 }
245
246 log.Panic(err)
247 }
248
249 phrase, err = exifcommon.FormatFromType(value, true)
250 log.PanicIf(err)
251
252 return phrase, nil
253 }
254
255 func (ite *IfdTagEntry) setIsUnhandledUnknown(isUnhandledUnknown bool) {
256 ite.isUnhandledUnknown = isUnhandledUnknown
257 }
258
259
260 func (ite *IfdTagEntry) SetChildIfd(ii *exifcommon.IfdIdentity) {
261 ite.childFqIfdPath = ii.String()
262 ite.childIfdPath = ii.UnindexedString()
263 ite.childIfdName = ii.Name()
264 }
265
266
267 func (ite *IfdTagEntry) ChildIfdName() string {
268 return ite.childIfdName
269 }
270
271
272 func (ite *IfdTagEntry) ChildIfdPath() string {
273 return ite.childIfdPath
274 }
275
276
277
278
279 func (ite *IfdTagEntry) ChildFqIfdPath() string {
280 return ite.childFqIfdPath
281 }
282
283
284 func (ite *IfdTagEntry) IfdIdentity() *exifcommon.IfdIdentity {
285 return ite.ifdIdentity
286 }
287
288 func (ite *IfdTagEntry) getValueContext() *exifcommon.ValueContext {
289 return exifcommon.NewValueContext(
290 ite.ifdIdentity.String(),
291 ite.tagId,
292 ite.unitCount,
293 ite.valueOffset,
294 ite.rawValueOffset,
295 ite.rs,
296 ite.tagType,
297 ite.byteOrder)
298 }
299
View as plain text