1 package exif
2
3 import (
4 "bytes"
5 "fmt"
6 "strings"
7 "testing"
8
9 "github.com/dsoprea/go-logging"
10
11 "github.com/dsoprea/go-exif/v3/common"
12 )
13
14 func Test_ByteWriter_writeAsBytes_uint8(t *testing.T) {
15 b := new(bytes.Buffer)
16 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
17
18 err := bw.writeAsBytes(uint8(0x12))
19 log.PanicIf(err)
20
21 if bytes.Compare(b.Bytes(), []byte{0x12}) != 0 {
22 t.Fatalf("uint8 not encoded correctly.")
23 }
24 }
25
26 func Test_ByteWriter_writeAsBytes_uint16(t *testing.T) {
27 b := new(bytes.Buffer)
28 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
29
30 err := bw.writeAsBytes(uint16(0x1234))
31 log.PanicIf(err)
32
33 if bytes.Compare(b.Bytes(), []byte{0x12, 0x34}) != 0 {
34 t.Fatalf("uint16 not encoded correctly.")
35 }
36 }
37
38 func Test_ByteWriter_writeAsBytes_uint32(t *testing.T) {
39 b := new(bytes.Buffer)
40 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
41
42 err := bw.writeAsBytes(uint32(0x12345678))
43 log.PanicIf(err)
44
45 if bytes.Compare(b.Bytes(), []byte{0x12, 0x34, 0x56, 0x78}) != 0 {
46 t.Fatalf("uint32 not encoded correctly.")
47 }
48 }
49
50 func Test_ByteWriter_WriteUint16(t *testing.T) {
51 b := new(bytes.Buffer)
52 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
53
54 err := bw.WriteUint16(uint16(0x1234))
55 log.PanicIf(err)
56
57 if bytes.Compare(b.Bytes(), []byte{0x12, 0x34}) != 0 {
58 t.Fatalf("uint16 not encoded correctly (as bytes).")
59 }
60 }
61
62 func Test_ByteWriter_WriteUint32(t *testing.T) {
63 b := new(bytes.Buffer)
64 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
65
66 err := bw.WriteUint32(uint32(0x12345678))
67 log.PanicIf(err)
68
69 if bytes.Compare(b.Bytes(), []byte{0x12, 0x34, 0x56, 0x78}) != 0 {
70 t.Fatalf("uint32 not encoded correctly (as bytes).")
71 }
72 }
73
74 func Test_ByteWriter_WriteFourBytes(t *testing.T) {
75 b := new(bytes.Buffer)
76 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
77
78 err := bw.WriteFourBytes([]byte{0x11, 0x22, 0x33, 0x44})
79 log.PanicIf(err)
80
81 if bytes.Compare(b.Bytes(), []byte{0x11, 0x22, 0x33, 0x44}) != 0 {
82 t.Fatalf("four-bytes not encoded correctly.")
83 }
84 }
85
86 func Test_ByteWriter_WriteFourBytes_TooMany(t *testing.T) {
87 b := new(bytes.Buffer)
88 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
89
90 err := bw.WriteFourBytes([]byte{0x11, 0x22, 0x33, 0x44, 0x55})
91 if err == nil {
92 t.Fatalf("expected error for not exactly four-bytes")
93 } else if err.Error() != "value is not four-bytes: (5)" {
94 t.Fatalf("wrong error for not exactly four bytes: %v", err)
95 }
96 }
97
98 func Test_IfdDataAllocator_Allocate_InitialOffset1(t *testing.T) {
99 addressableOffset := uint32(0)
100 ida := newIfdDataAllocator(addressableOffset)
101
102 if ida.NextOffset() != addressableOffset {
103 t.Fatalf("initial offset not correct: (%d) != (%d)", ida.NextOffset(), addressableOffset)
104 } else if len(ida.Bytes()) != 0 {
105 t.Fatalf("initial buffer not empty")
106 }
107
108 data := []byte{0x1, 0x2, 0x3}
109 offset, err := ida.Allocate(data)
110 log.PanicIf(err)
111
112 expected := uint32(addressableOffset + 0)
113 if offset != expected {
114 t.Fatalf("offset not bumped correctly (2): (%d) != (%d)", offset, expected)
115 } else if ida.NextOffset() != offset+uint32(3) {
116 t.Fatalf("position counter not advanced properly")
117 } else if bytes.Compare(ida.Bytes(), []byte{0x1, 0x2, 0x3}) != 0 {
118 t.Fatalf("buffer not correct after write (1)")
119 }
120
121 data = []byte{0x4, 0x5, 0x6}
122 offset, err = ida.Allocate(data)
123 log.PanicIf(err)
124
125 expected = uint32(addressableOffset + 3)
126 if offset != expected {
127 t.Fatalf("offset not bumped correctly (3): (%d) != (%d)", offset, expected)
128 } else if ida.NextOffset() != offset+uint32(3) {
129 t.Fatalf("position counter not advanced properly")
130 } else if bytes.Compare(ida.Bytes(), []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}) != 0 {
131 t.Fatalf("buffer not correct after write (2)")
132 }
133 }
134
135 func Test_IfdDataAllocator_Allocate_InitialOffset2(t *testing.T) {
136 addressableOffset := uint32(10)
137 ida := newIfdDataAllocator(addressableOffset)
138
139 if ida.NextOffset() != addressableOffset {
140 t.Fatalf("initial offset not correct: (%d) != (%d)", ida.NextOffset(), addressableOffset)
141 } else if len(ida.Bytes()) != 0 {
142 t.Fatalf("initial buffer not empty")
143 }
144
145 data := []byte{0x1, 0x2, 0x3}
146 offset, err := ida.Allocate(data)
147 log.PanicIf(err)
148
149 expected := uint32(addressableOffset + 0)
150 if offset != expected {
151 t.Fatalf("offset not bumped correctly (2): (%d) != (%d)", offset, expected)
152 } else if ida.NextOffset() != offset+uint32(3) {
153 t.Fatalf("position counter not advanced properly")
154 } else if bytes.Compare(ida.Bytes(), []byte{0x1, 0x2, 0x3}) != 0 {
155 t.Fatalf("buffer not correct after write (1)")
156 }
157
158 data = []byte{0x4, 0x5, 0x6}
159 offset, err = ida.Allocate(data)
160 log.PanicIf(err)
161
162 expected = uint32(addressableOffset + 3)
163 if offset != expected {
164 t.Fatalf("offset not bumped correctly (3): (%d) != (%d)", offset, expected)
165 } else if ida.NextOffset() != offset+uint32(3) {
166 t.Fatalf("position counter not advanced properly")
167 } else if bytes.Compare(ida.Bytes(), []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}) != 0 {
168 t.Fatalf("buffer not correct after write (2)")
169 }
170 }
171
172 func Test_IfdByteEncoder__Arithmetic(t *testing.T) {
173 ibe := NewIfdByteEncoder()
174
175 if (ibe.TableSize(1) - ibe.TableSize(0)) != IfdTagEntrySize {
176 t.Fatalf("table-size/entry-size not consistent (1)")
177 } else if (ibe.TableSize(11) - ibe.TableSize(10)) != IfdTagEntrySize {
178 t.Fatalf("table-size/entry-size not consistent (2)")
179 }
180 }
181
182 func Test_IfdByteEncoder_encodeTagToBytes_bytes_embedded1(t *testing.T) {
183 defer func() {
184 if state := recover(); state != nil {
185 err := log.Wrap(state.(error))
186 log.PrintError(err)
187 t.Fatalf("Test failed.")
188 }
189 }()
190
191 ibe := NewIfdByteEncoder()
192
193 im, err := exifcommon.NewIfdMappingWithStandard()
194 log.PanicIf(err)
195
196 ti := NewTagIndex()
197 ib := NewIfdBuilder(im, ti, exifcommon.IfdGpsInfoStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
198
199 it, err := ti.Get(ib.IfdIdentity(), uint16(0x0000))
200 log.PanicIf(err)
201
202 bt := NewStandardBuilderTag(exifcommon.IfdGpsInfoStandardIfdIdentity.UnindexedString(), it, exifcommon.TestDefaultByteOrder, []uint8{uint8(0x12)})
203
204 b := new(bytes.Buffer)
205 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
206
207 addressableOffset := uint32(0x1234)
208 ida := newIfdDataAllocator(addressableOffset)
209
210 childIfdBlock, err := ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
211 log.PanicIf(err)
212
213 if childIfdBlock != nil {
214 t.Fatalf("no child-IFDs were expected to be allocated")
215 } else if bytes.Compare(b.Bytes(), []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00}) != 0 {
216 t.Fatalf("encoded tag-entry bytes not correct")
217 } else if ida.NextOffset() != addressableOffset {
218 t.Fatalf("allocation was done but not expected")
219 }
220 }
221
222 func Test_IfdByteEncoder_encodeTagToBytes_bytes_embedded2(t *testing.T) {
223 ibe := NewIfdByteEncoder()
224
225 im, err := exifcommon.NewIfdMappingWithStandard()
226 log.PanicIf(err)
227
228 ti := NewTagIndex()
229 ib := NewIfdBuilder(im, ti, exifcommon.IfdGpsInfoStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
230
231 it, err := ti.Get(ib.IfdIdentity(), uint16(0x0000))
232 log.PanicIf(err)
233
234 bt := NewStandardBuilderTag(exifcommon.IfdGpsInfoStandardIfdIdentity.UnindexedString(), it, exifcommon.TestDefaultByteOrder, []uint8{uint8(0x12), uint8(0x34), uint8(0x56), uint8(0x78)})
235
236 b := new(bytes.Buffer)
237 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
238
239 addressableOffset := uint32(0x1234)
240 ida := newIfdDataAllocator(addressableOffset)
241
242 childIfdBlock, err := ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
243 log.PanicIf(err)
244
245 if childIfdBlock != nil {
246 t.Fatalf("no child-IFDs were expected to be allocated")
247 } else if bytes.Compare(b.Bytes(), []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78}) != 0 {
248 t.Fatalf("encoded tag-entry bytes not correct")
249 } else if ida.NextOffset() != addressableOffset {
250 t.Fatalf("allocation was done but not expected")
251 }
252 }
253
254 func Test_IfdByteEncoder_encodeTagToBytes_bytes_allocated(t *testing.T) {
255 ibe := NewIfdByteEncoder()
256
257 im, err := exifcommon.NewIfdMappingWithStandard()
258 log.PanicIf(err)
259
260 ti := NewTagIndex()
261 ib := NewIfdBuilder(im, ti, exifcommon.IfdGpsInfoStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
262
263 b := new(bytes.Buffer)
264 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
265
266 addressableOffset := uint32(0x1234)
267 ida := newIfdDataAllocator(addressableOffset)
268
269 it, err := ti.Get(ib.IfdIdentity(), uint16(0x0000))
270 log.PanicIf(err)
271
272 bt := NewStandardBuilderTag(exifcommon.IfdGpsInfoStandardIfdIdentity.UnindexedString(), it, exifcommon.TestDefaultByteOrder, []uint8{uint8(0x12), uint8(0x34), uint8(0x56), uint8(0x78), uint8(0x9a)})
273
274 childIfdBlock, err := ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
275 log.PanicIf(err)
276
277 if childIfdBlock != nil {
278 t.Fatalf("no child-IFDs were expected to be allocated (1)")
279 } else if bytes.Compare(b.Bytes(), []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x12, 0x34}) != 0 {
280 t.Fatalf("encoded tag-entry bytes not correct (1)")
281 } else if ida.NextOffset() != addressableOffset+uint32(5) {
282 t.Fatalf("allocation offset not expected (1)")
283 } else if bytes.Compare(ida.Bytes(), []byte{0x12, 0x34, 0x56, 0x78, 0x9A}) != 0 {
284 t.Fatalf("allocated data not correct (1)")
285 }
286
287
288
289 bt = NewStandardBuilderTag(exifcommon.IfdGpsInfoStandardIfdIdentity.UnindexedString(), it, exifcommon.TestDefaultByteOrder, []uint8{uint8(0xbc), uint8(0xde), uint8(0xf0), uint8(0x12), uint8(0x34)})
290
291 childIfdBlock, err = ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
292 log.PanicIf(err)
293
294 if childIfdBlock != nil {
295 t.Fatalf("no child-IFDs were expected to be allocated (2)")
296 } else if bytes.Compare(b.Bytes(), []byte{
297 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x12, 0x34,
298 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x12, 0x39,
299 }) != 0 {
300 t.Fatalf("encoded tag-entry bytes not correct (2)")
301 } else if ida.NextOffset() != addressableOffset+uint32(10) {
302 t.Fatalf("allocation offset not expected (2)")
303 } else if bytes.Compare(ida.Bytes(), []byte{
304 0x12, 0x34, 0x56, 0x78, 0x9A,
305 0xbc, 0xde, 0xf0, 0x12, 0x34,
306 }) != 0 {
307 t.Fatalf("allocated data not correct (2)")
308 }
309 }
310
311 func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withoutAllocate(t *testing.T) {
312 ibe := NewIfdByteEncoder()
313
314 im, err := exifcommon.NewIfdMappingWithStandard()
315 log.PanicIf(err)
316
317 ti := NewTagIndex()
318 ib := NewIfdBuilder(im, ti, exifcommon.IfdStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
319
320 b := new(bytes.Buffer)
321 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
322
323 addressableOffset := uint32(0x1234)
324 ida := newIfdDataAllocator(addressableOffset)
325
326 childIb := NewIfdBuilder(im, ti, exifcommon.IfdExifStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
327 tagValue := NewIfdBuilderTagValueFromIfdBuilder(childIb)
328 bt := NewChildIfdBuilderTag(exifcommon.IfdStandardIfdIdentity.UnindexedString(), exifcommon.IfdExifStandardIfdIdentity.TagId(), tagValue)
329
330 nextIfdOffsetToWrite := uint32(0)
331 childIfdBlock, err := ibe.encodeTagToBytes(ib, bt, bw, ida, nextIfdOffsetToWrite)
332 log.PanicIf(err)
333
334 if childIfdBlock != nil {
335 t.Fatalf("no child-IFDs were expected to be allocated")
336 } else if bytes.Compare(b.Bytes(), []byte{0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}) != 0 {
337 t.Fatalf("encoded tag-entry with child-IFD not correct")
338 } else if ida.NextOffset() != addressableOffset {
339 t.Fatalf("allocation offset not expected")
340 }
341 }
342
343 func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withAllocate(t *testing.T) {
344 defer func() {
345 if state := recover(); state != nil {
346 err := log.Wrap(state.(error))
347 log.PrintError(err)
348 t.Fatalf("Test failed.")
349 }
350 }()
351
352
353
354
355
356 im, err := exifcommon.NewIfdMappingWithStandard()
357 log.PanicIf(err)
358
359 ti := NewTagIndex()
360 childIb := NewIfdBuilder(im, ti, exifcommon.IfdExifStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
361
362 childIbTestTag := &BuilderTag{
363 ifdPath: exifcommon.IfdExifStandardIfdIdentity.UnindexedString(),
364 tagId: 0x8822,
365 typeId: exifcommon.TypeShort,
366 value: NewIfdBuilderTagValueFromBytes([]byte{0x12, 0x34}),
367 }
368
369 childIb.Add(childIbTestTag)
370
371
372
373 tagValue := NewIfdBuilderTagValueFromIfdBuilder(childIb)
374 bt := NewChildIfdBuilderTag(exifcommon.IfdStandardIfdIdentity.UnindexedString(), exifcommon.IfdExifStandardIfdIdentity.TagId(), tagValue)
375
376
377
378
379
380
381 ibe := NewIfdByteEncoder()
382
383 ib := NewIfdBuilder(im, ti, exifcommon.IfdStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
384
385 b := new(bytes.Buffer)
386 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
387
388
389
390
391
392
393 addressableOffset := uint32(0x1234)
394 ida := newIfdDataAllocator(addressableOffset)
395
396
397
398 nextIfdOffsetToWrite := uint32(2000)
399
400 childIfdBlock, err := ibe.encodeTagToBytes(ib, bt, bw, ida, nextIfdOffsetToWrite)
401 log.PanicIf(err)
402
403 if ida.NextOffset() != addressableOffset {
404 t.Fatalf("IDA offset changed but no allocations where expected: (0x%02x)", ida.NextOffset())
405 }
406
407 tagBytes := b.Bytes()
408
409 if len(tagBytes) != 12 {
410 t.Fatalf("Tag not encoded to the right number of bytes: (%d)", len(tagBytes))
411 } else if len(childIfdBlock) != 18 {
412 t.Fatalf("Child IFD is not the right size: (%d)", len(childIfdBlock))
413 }
414
415 iteV, err := parseOneTag(im, ti, exifcommon.IfdStandardIfdIdentity, exifcommon.TestDefaultByteOrder, tagBytes)
416 log.PanicIf(err)
417
418 if iteV.TagId() != exifcommon.IfdExifStandardIfdIdentity.TagId() {
419 t.Fatalf("IFD first tag-ID not correct: (0x%02x)", iteV.TagId())
420 } else if iteV.tagIndex != 0 {
421 t.Fatalf("IFD first tag index not correct: (%d)", iteV.tagIndex)
422 } else if iteV.TagType() != exifcommon.TypeLong {
423 t.Fatalf("IFD first tag type not correct: (%d)", iteV.TagType())
424 } else if iteV.UnitCount() != 1 {
425 t.Fatalf("IFD first tag unit-count not correct: (%d)", iteV.UnitCount())
426 } else if iteV.getValueOffset() != nextIfdOffsetToWrite {
427 t.Fatalf("IFD's child-IFD offset (as offset) is not correct: (%d) != (%d)", iteV.getValueOffset(), nextIfdOffsetToWrite)
428 } else if iteV.ChildIfdPath() != exifcommon.IfdExifStandardIfdIdentity.UnindexedString() {
429 t.Fatalf("IFD first tag IFD-name name not correct: [%s]", iteV.ChildIfdPath())
430 } else if iteV.IfdPath() != exifcommon.IfdStandardIfdIdentity.UnindexedString() {
431 t.Fatalf("IFD first tag parent IFD not correct: %v", iteV.IfdPath())
432 }
433
434
435
436 childNextIfdOffset, childEntries, err := parseOneIfd(im, ti, exifcommon.IfdExifStandardIfdIdentity, exifcommon.TestDefaultByteOrder, childIfdBlock, nil)
437 log.PanicIf(err)
438
439 if childNextIfdOffset != uint32(0) {
440 t.Fatalf("Child IFD: Next IFD offset should be (0): (0x%08x)", childNextIfdOffset)
441 } else if len(childEntries) != 1 {
442 t.Fatalf("Child IFD: Expected exactly one entry: (%d)", len(childEntries))
443 }
444
445 ite := childEntries[0]
446
447 if ite.TagId() != 0x8822 {
448 t.Fatalf("Child IFD first tag-ID not correct: (0x%02x)", ite.TagId())
449 } else if ite.tagIndex != 0 {
450 t.Fatalf("Child IFD first tag index not correct: (%d)", ite.tagIndex)
451 } else if ite.TagType() != exifcommon.TypeShort {
452 t.Fatalf("Child IFD first tag type not correct: (%d)", ite.TagType())
453 } else if ite.UnitCount() != 1 {
454 t.Fatalf("Child IFD first tag unit-count not correct: (%d)", ite.UnitCount())
455 } else if ite.ChildIfdPath() != "" {
456 t.Fatalf("Child IFD first tag IFD-name name not empty: [%s]", ite.ChildIfdPath())
457 } else if ite.IfdPath() != exifcommon.IfdExifStandardIfdIdentity.UnindexedString() {
458 t.Fatalf("Child IFD first tag parent IFD not correct: %v", ite.IfdPath())
459 }
460 }
461
462 func Test_IfdByteEncoder_encodeTagToBytes_simpleTag_allocate(t *testing.T) {
463 defer func() {
464 if state := recover(); state != nil {
465 err := log.Wrap(state.(error))
466 log.PrintError(err)
467 t.Fatalf("Test failed.")
468 }
469 }()
470
471
472
473
474
475
476 ibe := NewIfdByteEncoder()
477
478 im, err := exifcommon.NewIfdMappingWithStandard()
479 log.PanicIf(err)
480
481 ti := NewTagIndex()
482 ib := NewIfdBuilder(im, ti, exifcommon.IfdStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
483
484 it, err := ib.tagIndex.Get(ib.IfdIdentity(), uint16(0x000b))
485 log.PanicIf(err)
486
487 valueString := "testvalue"
488 bt := NewStandardBuilderTag(exifcommon.IfdStandardIfdIdentity.UnindexedString(), it, exifcommon.TestDefaultByteOrder, valueString)
489
490 b := new(bytes.Buffer)
491 bw := NewByteWriter(b, exifcommon.TestDefaultByteOrder)
492
493
494
495
496
497
498 addressableOffset := uint32(0x1234)
499 ida := newIfdDataAllocator(addressableOffset)
500
501 childIfdBlock, err := ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
502 log.PanicIf(err)
503
504 if ida.NextOffset() == addressableOffset {
505 t.Fatalf("IDA offset did not change even though there should've been an allocation.")
506 }
507
508 tagBytes := b.Bytes()
509
510 if len(tagBytes) != 12 {
511 t.Fatalf("Tag not encoded to the right number of bytes: (%d)", len(tagBytes))
512 } else if len(childIfdBlock) != 0 {
513 t.Fatalf("Child IFD not have been allocated.")
514 }
515
516 ite, err := parseOneTag(im, ti, exifcommon.IfdStandardIfdIdentity, exifcommon.TestDefaultByteOrder, tagBytes)
517 log.PanicIf(err)
518
519 if ite.TagId() != 0x000b {
520 t.Fatalf("Tag-ID not correct: (0x%02x)", ite.TagId())
521 } else if ite.tagIndex != 0 {
522 t.Fatalf("Tag index not correct: (%d)", ite.tagIndex)
523 } else if ite.TagType() != exifcommon.TypeAscii {
524 t.Fatalf("Tag type not correct: (%d)", ite.TagType())
525 } else if ite.UnitCount() != (uint32(len(valueString) + 1)) {
526 t.Fatalf("Tag unit-count not correct: (%d)", ite.UnitCount())
527 } else if ite.ChildIfdPath() != "" {
528 t.Fatalf("Tag's IFD-name should be empty: [%s]", ite.ChildIfdPath())
529 } else if ite.IfdPath() != exifcommon.IfdStandardIfdIdentity.UnindexedString() {
530 t.Fatalf("Tag's parent IFD is not correct: %v", ite.IfdPath())
531 }
532
533 expectedBuffer := bytes.NewBufferString(valueString)
534 expectedBuffer.Write([]byte{0x0})
535 expectedBytes := expectedBuffer.Bytes()
536
537 allocatedBytes := ida.Bytes()
538
539 if bytes.Compare(allocatedBytes, expectedBytes) != 0 {
540 t.Fatalf("Allocated bytes not correct: %v != %v", allocatedBytes, expectedBytes)
541 }
542 }
543
544 func Test_IfdByteEncoder_encodeIfdToBytes_simple(t *testing.T) {
545 ib := getExifSimpleTestIb()
546
547
548
549 ibe := NewIfdByteEncoder()
550
551
552
553
554
555
556 addressableOffset := uint32(0x1234)
557
558 tableAndAllocated, tableSize, allocatedDataSize, childIfdSizes, err := ibe.encodeIfdToBytes(ib, addressableOffset, uint32(0), false)
559 log.PanicIf(err)
560
561 expectedTableSize := ibe.TableSize(4)
562 if tableSize != expectedTableSize {
563 t.Fatalf("Table-size not the right size: (%d) != (%d)", tableSize, expectedTableSize)
564 } else if len(childIfdSizes) != 0 {
565 t.Fatalf("One or more child IFDs were allocated but shouldn't have been: (%d)", len(childIfdSizes))
566 }
567
568
569 expectedAllocatedSize := 11 + 8
570
571 if int(allocatedDataSize) != expectedAllocatedSize {
572 t.Fatalf("Allocated data size not correct: (%d)", allocatedDataSize)
573 }
574
575 expectedIfdAndDataBytes := []byte{
576
577
578
579 0x00, 0x04,
580
581
582 0x00, 0x0b, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x12, 0x34,
583 0x00, 0xff, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x11, 0x22, 0x00, 0x00,
584 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x33, 0x44, 0x55, 0x66,
585 0x01, 0x3e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x12, 0x3f,
586
587
588 0x00, 0x00, 0x00, 0x00,
589
590
591
592
593 0x61, 0x73, 0x63, 0x69, 0x69, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00,
594
595
596 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44,
597 }
598
599 if bytes.Compare(tableAndAllocated, expectedIfdAndDataBytes) != 0 {
600 t.Fatalf("IFD table and allocated data not correct: %v", exifcommon.DumpBytesClauseToString(tableAndAllocated))
601 }
602 }
603
604 func Test_IfdByteEncoder_encodeIfdToBytes_fullExif(t *testing.T) {
605 defer func() {
606 if state := recover(); state != nil {
607 err := log.Wrap(state.(error))
608 log.PrintError(err)
609 t.Fatalf("Test failed.")
610 }
611 }()
612
613 ib := getExifSimpleTestIb()
614
615
616
617 ibe := NewIfdByteEncoder()
618
619
620 _, tableSize, allocatedDataSize, _, err := ibe.encodeIfdToBytes(ib, uint32(0), uint32(0), false)
621 log.PanicIf(err)
622
623 addressableOffset := ExifDefaultFirstIfdOffset + tableSize
624 nextIfdOffsetToWrite := addressableOffset + allocatedDataSize
625
626
627 tableAndAllocated, _, _, _, err := ibe.encodeIfdToBytes(ib, addressableOffset, uint32(nextIfdOffsetToWrite), false)
628 log.PanicIf(err)
629
630 if len(tableAndAllocated) != (int(tableSize) + int(allocatedDataSize)) {
631 t.Fatalf("Table-and-data size doesn't match what was expected: (%d) != (%d + %d)", len(tableAndAllocated), tableSize, allocatedDataSize)
632 }
633
634
635
636 b := new(bytes.Buffer)
637
638 headerBytes, err := BuildExifHeader(exifcommon.TestDefaultByteOrder, ExifDefaultFirstIfdOffset)
639 log.PanicIf(err)
640
641 _, err = b.Write(headerBytes)
642 log.PanicIf(err)
643
644 _, err = b.Write(tableAndAllocated)
645 log.PanicIf(err)
646
647
648
649
650 exifData := b.Bytes()
651 validateExifSimpleTestIb(exifData, t)
652 }
653
654 func Test_IfdByteEncoder_EncodeToExifPayload(t *testing.T) {
655 defer func() {
656 if state := recover(); state != nil {
657 err := log.Wrap(state.(error))
658 log.PrintError(err)
659 t.Fatalf("Test failed.")
660 }
661 }()
662
663 ib := getExifSimpleTestIb()
664
665
666
667 ibe := NewIfdByteEncoder()
668
669 encodedIfds, err := ibe.EncodeToExifPayload(ib)
670 log.PanicIf(err)
671
672
673
674 b := new(bytes.Buffer)
675
676 headerBytes, err := BuildExifHeader(exifcommon.TestDefaultByteOrder, ExifDefaultFirstIfdOffset)
677 log.PanicIf(err)
678
679 _, err = b.Write(headerBytes)
680 log.PanicIf(err)
681
682 _, err = b.Write(encodedIfds)
683 log.PanicIf(err)
684
685
686
687
688 exifData := b.Bytes()
689 validateExifSimpleTestIb(exifData, t)
690 }
691
692 func Test_IfdByteEncoder_EncodeToExif(t *testing.T) {
693 ib := getExifSimpleTestIb()
694
695
696
697 ibe := NewIfdByteEncoder()
698
699 exifData, err := ibe.EncodeToExif(ib)
700 log.PanicIf(err)
701
702 validateExifSimpleTestIb(exifData, t)
703 }
704
705 func Test_IfdByteEncoder_EncodeToExif_WithChildAndSibling(t *testing.T) {
706 defer func() {
707 if state := recover(); state != nil {
708 err := log.Wrap(state.(error))
709 log.PrintError(err)
710 t.Fatalf("Test failed.")
711 }
712 }()
713
714 im, err := exifcommon.NewIfdMappingWithStandard()
715 log.PanicIf(err)
716
717 ti := NewTagIndex()
718 ib := NewIfdBuilder(im, ti, exifcommon.IfdStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
719
720 err = ib.AddStandard(0x000b, "asciivalue")
721 log.PanicIf(err)
722
723 err = ib.AddStandard(0x00ff, []uint16{0x1122})
724 log.PanicIf(err)
725
726
727
728 childIb := NewIfdBuilder(im, ti, exifcommon.IfdExifStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
729
730 err = childIb.AddStandardWithName("ISOSpeedRatings", []uint16{0x1122})
731 log.PanicIf(err)
732
733 err = childIb.AddStandardWithName("ISOSpeed", []uint32{0x33445566})
734 log.PanicIf(err)
735
736 err = ib.AddChildIb(childIb)
737 log.PanicIf(err)
738
739 err = ib.AddStandard(0x0100, []uint32{0x33445566})
740 log.PanicIf(err)
741
742
743
744
745 childIb2 := NewIfdBuilder(im, ti, exifcommon.IfdGpsInfoStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
746
747 err = childIb2.AddStandardWithName("GPSAltitudeRef", []uint8{0x11, 0x22})
748 log.PanicIf(err)
749
750 err = ib.AddChildIb(childIb2)
751 log.PanicIf(err)
752
753 err = ib.AddStandard(0x013e, []exifcommon.Rational{{Numerator: 0x11112222, Denominator: 0x33334444}})
754 log.PanicIf(err)
755
756
757
758
759 nextIb := NewIfdBuilder(im, ti, exifcommon.IfdStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
760
761 err = nextIb.AddStandard(0x0101, []uint32{0x11223344})
762 log.PanicIf(err)
763
764 err = nextIb.AddStandard(0x0102, []uint16{0x5566})
765 log.PanicIf(err)
766
767 ib.SetNextIb(nextIb)
768
769
770
771 ibe := NewIfdByteEncoder()
772
773 exifData, err := ibe.EncodeToExif(ib)
774 log.PanicIf(err)
775
776
777
778 _, index, err := Collect(im, ti, exifData)
779 log.PanicIf(err)
780
781 tagsDump := index.RootIfd.DumpTree()
782
783 actual := strings.Join(tagsDump, "\n")
784
785 expected :=
786 `> IFD [ROOT]->[IFD]:(0) TOP
787 - (0x000b)
788 - (0x00ff)
789 - (0x8769)
790 > IFD [IFD]->[IFD/Exif]:(0) TOP
791 - (0x8827)
792 - (0x8833)
793 < IFD [IFD]->[IFD/Exif]:(0) BOTTOM
794 - (0x0100)
795 - (0x8825)
796 > IFD [IFD]->[IFD/GPSInfo]:(0) TOP
797 - (0x0005)
798 < IFD [IFD]->[IFD/GPSInfo]:(0) BOTTOM
799 - (0x013e)
800 < IFD [ROOT]->[IFD]:(0) BOTTOM
801 * LINKING TO SIBLING IFD [IFD]:(1)
802 > IFD [ROOT]->[IFD]:(1) TOP
803 - (0x0101)
804 - (0x0102)
805 < IFD [ROOT]->[IFD]:(1) BOTTOM`
806
807 if actual != expected {
808 fmt.Printf("\n")
809
810 fmt.Printf("Actual:\n")
811 fmt.Printf("\n")
812 fmt.Printf("%s\n", actual)
813 fmt.Printf("\n")
814
815 fmt.Printf("Expected:\n")
816 fmt.Printf("\n")
817 fmt.Printf("%s\n", expected)
818 fmt.Printf("\n")
819
820 t.Fatalf("IFD hierarchy not correct.")
821 }
822 }
823
824 func ExampleIfdByteEncoder_EncodeToExif() {
825
826
827 im, err := exifcommon.NewIfdMappingWithStandard()
828 log.PanicIf(err)
829
830 ti := NewTagIndex()
831 ib := NewIfdBuilder(im, ti, exifcommon.IfdStandardIfdIdentity, exifcommon.TestDefaultByteOrder)
832
833 err = ib.AddStandardWithName("ProcessingSoftware", "asciivalue")
834 log.PanicIf(err)
835
836 err = ib.AddStandardWithName("DotRange", []uint8{0x11})
837 log.PanicIf(err)
838
839 err = ib.AddStandardWithName("SubfileType", []uint16{0x2233})
840 log.PanicIf(err)
841
842 err = ib.AddStandardWithName("ImageWidth", []uint32{0x44556677})
843 log.PanicIf(err)
844
845 err = ib.AddStandardWithName("WhitePoint", []exifcommon.Rational{{Numerator: 0x11112222, Denominator: 0x33334444}})
846 log.PanicIf(err)
847
848 err = ib.AddStandardWithName("ShutterSpeedValue", []exifcommon.SignedRational{{Numerator: 0x11112222, Denominator: 0x33334444}})
849 log.PanicIf(err)
850
851
852
853 ibe := NewIfdByteEncoder()
854
855 exifData, err := ibe.EncodeToExif(ib)
856 log.PanicIf(err)
857
858
859
860 _, index, err := Collect(im, ti, exifData)
861 log.PanicIf(err)
862
863 for i, ite := range index.RootIfd.Entries() {
864 value, err := ite.Value()
865 log.PanicIf(err)
866
867 fmt.Printf("%d: %s [%v]\n", i, ite, value)
868 }
869
870
871
872
873
874
875
876
877
878 }
879
View as plain text