1 package exif
2
3 import (
4 "bytes"
5 "fmt"
6 "path"
7 "reflect"
8 "testing"
9
10 "io/ioutil"
11
12 "github.com/dsoprea/go-logging"
13
14 "github.com/dsoprea/go-exif/v3/common"
15 )
16
17 func TestIfdTagEntry_RawBytes_RealData(t *testing.T) {
18 defer func() {
19 if state := recover(); state != nil {
20 err := log.Wrap(state.(error))
21 log.PrintErrorf(err, "Test failure.")
22 }
23 }()
24
25 testImageFilepath := getTestImageFilepath()
26
27 rawExif, err := SearchFileAndExtractExif(testImageFilepath)
28 log.PanicIf(err)
29
30 im, err := exifcommon.NewIfdMappingWithStandard()
31 log.PanicIf(err)
32
33 ti := NewTagIndex()
34
35 _, index, err := Collect(im, ti, rawExif)
36 log.PanicIf(err)
37
38 var ite *IfdTagEntry
39 for _, thisIte := range index.RootIfd.entries {
40 if thisIte.TagId() == 0x0110 {
41 ite = thisIte
42 break
43 }
44 }
45
46 if ite == nil {
47 t.Fatalf("Tag not found.")
48 }
49
50 decodedBytes, err := ite.GetRawBytes()
51 log.PanicIf(err)
52
53 expected := []byte("Canon EOS 5D Mark III")
54 expected = append(expected, 0)
55
56 if len(decodedBytes) != int(ite.UnitCount()) {
57 t.Fatalf("Decoded bytes not the right count.")
58 } else if bytes.Compare(decodedBytes, expected) != 0 {
59 t.Fatalf("Decoded bytes not correct.")
60 }
61 }
62
63 func TestIfd_FindTagWithId_Hit(t *testing.T) {
64 testImageFilepath := getTestImageFilepath()
65 rawExif, err := SearchFileAndExtractExif(testImageFilepath)
66 log.PanicIf(err)
67
68 im, err := exifcommon.NewIfdMappingWithStandard()
69 log.PanicIf(err)
70
71 ti := NewTagIndex()
72
73 _, index, err := Collect(im, ti, rawExif)
74 log.PanicIf(err)
75
76 ifd := index.RootIfd
77 results, err := ifd.FindTagWithId(0x011b)
78 log.PanicIf(err)
79
80 if len(results) != 1 {
81 t.Fatalf("Exactly one result was not found: (%d)", len(results))
82 } else if results[0].TagId() != 0x011b {
83 t.Fatalf("The result was not expected: %v", results[0])
84 }
85 }
86
87 func TestIfd_FindTagWithId_Miss(t *testing.T) {
88 testImageFilepath := getTestImageFilepath()
89
90 rawExif, err := SearchFileAndExtractExif(testImageFilepath)
91 log.PanicIf(err)
92
93 im, err := exifcommon.NewIfdMappingWithStandard()
94 log.PanicIf(err)
95
96 ti := NewTagIndex()
97
98 _, index, err := Collect(im, ti, rawExif)
99 log.PanicIf(err)
100
101 ifd := index.RootIfd
102
103 _, err = ifd.FindTagWithId(0xffff)
104 if err == nil {
105 t.Fatalf("Expected error for not-found tag.")
106 } else if log.Is(err, ErrTagNotFound) == false {
107 log.Panic(err)
108 }
109 }
110
111 func TestIfd_FindTagWithName_Hit(t *testing.T) {
112 testImageFilepath := getTestImageFilepath()
113
114 rawExif, err := SearchFileAndExtractExif(testImageFilepath)
115 log.PanicIf(err)
116
117 im, err := exifcommon.NewIfdMappingWithStandard()
118 log.PanicIf(err)
119
120 ti := NewTagIndex()
121
122 _, index, err := Collect(im, ti, rawExif)
123 log.PanicIf(err)
124
125 ifd := index.RootIfd
126
127 results, err := ifd.FindTagWithName("YResolution")
128 log.PanicIf(err)
129
130 if len(results) != 1 {
131 t.Fatalf("Exactly one result was not found: (%d)", len(results))
132 } else if results[0].TagId() != 0x011b {
133 t.Fatalf("The result was not expected: %v", results[0])
134 }
135 }
136
137 func TestIfd_FindTagWithName_Miss(t *testing.T) {
138 testImageFilepath := getTestImageFilepath()
139
140 rawExif, err := SearchFileAndExtractExif(testImageFilepath)
141 log.PanicIf(err)
142
143 im, err := exifcommon.NewIfdMappingWithStandard()
144 log.PanicIf(err)
145
146 ti := NewTagIndex()
147
148 _, index, err := Collect(im, ti, rawExif)
149 log.PanicIf(err)
150
151 ifd := index.RootIfd
152
153 _, err = ifd.FindTagWithName("PlanarConfiguration")
154 if err == nil {
155 t.Fatalf("Expected error for not-found tag.")
156 } else if log.Is(err, ErrTagNotFound) == false {
157 log.Panic(err)
158 }
159 }
160
161 func TestIfd_FindTagWithName_NonStandard(t *testing.T) {
162 testImageFilepath := getTestImageFilepath()
163
164 rawExif, err := SearchFileAndExtractExif(testImageFilepath)
165 log.PanicIf(err)
166
167 im, err := exifcommon.NewIfdMappingWithStandard()
168 log.PanicIf(err)
169
170 ti := NewTagIndex()
171
172 _, index, err := Collect(im, ti, rawExif)
173 log.PanicIf(err)
174
175 ifd := index.RootIfd
176
177 _, err = ifd.FindTagWithName("GeorgeNotAtHome")
178 if err == nil {
179 t.Fatalf("Expected error for not-found tag.")
180 } else if log.Is(err, ErrTagNotKnown) == false {
181 log.Panic(err)
182 }
183 }
184
185 func TestIfd_Thumbnail(t *testing.T) {
186 testImageFilepath := getTestImageFilepath()
187
188 rawExif, err := SearchFileAndExtractExif(testImageFilepath)
189 log.PanicIf(err)
190
191 im, err := exifcommon.NewIfdMappingWithStandard()
192 log.PanicIf(err)
193
194 ti := NewTagIndex()
195
196 _, index, err := Collect(im, ti, rawExif)
197 log.PanicIf(err)
198
199 ifd := index.RootIfd
200
201 if ifd.nextIfd == nil {
202 t.Fatalf("There is no IFD1.")
203 }
204
205
206 actual, err := ifd.nextIfd.Thumbnail()
207 log.PanicIf(err)
208
209 assetsPath := exifcommon.GetTestAssetsPath()
210 expectedFilepath := path.Join(assetsPath, "NDM_8901.jpg.thumbnail")
211
212 expected, err := ioutil.ReadFile(expectedFilepath)
213 log.PanicIf(err)
214
215 if bytes.Compare(actual, expected) != 0 {
216 t.Fatalf("thumbnail not correct")
217 }
218 }
219
220 func TestIfd_GpsInfo(t *testing.T) {
221 defer func() {
222 if state := recover(); state != nil {
223 err := log.Wrap(state.(error))
224 log.PrintErrorf(err, "Test failure.")
225 }
226 }()
227
228 filepath := getTestGpsImageFilepath()
229
230 rawExif, err := SearchFileAndExtractExif(filepath)
231 log.PanicIf(err)
232
233 im, err := exifcommon.NewIfdMappingWithStandard()
234 log.PanicIf(err)
235
236 ti := NewTagIndex()
237
238 _, index, err := Collect(im, ti, rawExif)
239 log.PanicIf(err)
240
241 ifd, err := index.RootIfd.ChildWithIfdPath(exifcommon.IfdGpsInfoStandardIfdIdentity)
242 log.PanicIf(err)
243
244 gi, err := ifd.GpsInfo()
245 log.PanicIf(err)
246
247 if gi.Latitude.Orientation != 'N' || gi.Latitude.Degrees != 26 || gi.Latitude.Minutes != 35 || gi.Latitude.Seconds != 12 {
248 t.Fatalf("latitude not correct")
249 } else if gi.Longitude.Orientation != 'W' || gi.Longitude.Degrees != 80 || gi.Longitude.Minutes != 3 || gi.Longitude.Seconds != 13 {
250 t.Fatalf("longitude not correct")
251 } else if gi.Altitude != 0 {
252 t.Fatalf("altitude not correct")
253 } else if gi.Timestamp.Unix() != 1524964977 {
254 t.Fatalf("timestamp not correct")
255 } else if gi.Altitude != 0 {
256 t.Fatalf("altitude not correct")
257 }
258 }
259
260 func TestIfd_GpsInfo__2_0_0_0(t *testing.T) {
261 defer func() {
262 if state := recover(); state != nil {
263 err := log.Wrap(state.(error))
264 log.PrintErrorf(err, "Test failure.")
265 }
266 }()
267
268 assetsPath := exifcommon.GetTestAssetsPath()
269 filepath := path.Join(assetsPath, "gps-2000-scaled.jpg")
270
271 rawExif, err := SearchFileAndExtractExif(filepath)
272 log.PanicIf(err)
273
274 im, err := exifcommon.NewIfdMappingWithStandard()
275 log.PanicIf(err)
276
277 ti := NewTagIndex()
278
279 _, index, err := Collect(im, ti, rawExif)
280 log.PanicIf(err)
281
282 ifd, err := index.RootIfd.ChildWithIfdPath(exifcommon.IfdGpsInfoStandardIfdIdentity)
283 log.PanicIf(err)
284
285 gi, err := ifd.GpsInfo()
286 log.PanicIf(err)
287
288 expectedLatitude := GpsDegrees{
289 Orientation: 'S',
290 Degrees: 38.0,
291 Minutes: 24.311687,
292 Seconds: 0.0,
293 }
294
295 expectedLongitude := GpsDegrees{
296 Orientation: 'E',
297 Degrees: 144.0,
298 Minutes: 11.33748,
299 Seconds: 0.0,
300 }
301
302 if GpsDegreesEquals(gi.Latitude, expectedLatitude) != true {
303 t.Fatalf("Latitude not correct: %v", gi.Latitude)
304 } else if GpsDegreesEquals(gi.Longitude, expectedLongitude) != true {
305 t.Fatalf("Longitude not correct: %v", gi.Longitude)
306 } else if gi.Altitude != 0 {
307 t.Fatalf("Altitude not correct: (%d)", gi.Altitude)
308 } else if gi.Timestamp.Unix() != -62135596800 {
309 t.Fatalf("Timestamp not correct: (%d)", gi.Timestamp.Unix())
310 }
311 }
312
313 func TestIfd_EnumerateTagsRecursively(t *testing.T) {
314 testImageFilepath := getTestImageFilepath()
315
316 rawExif, err := SearchFileAndExtractExif(testImageFilepath)
317 log.PanicIf(err)
318
319 im, err := exifcommon.NewIfdMappingWithStandard()
320 log.PanicIf(err)
321
322 ti := NewTagIndex()
323
324 _, index, err := Collect(im, ti, rawExif)
325 log.PanicIf(err)
326
327 collected := make([][2]interface{}, 0)
328
329 cb := func(ifd *Ifd, ite *IfdTagEntry) error {
330 item := [2]interface{}{
331 ifd.ifdIdentity.UnindexedString(),
332 int(ite.TagId()),
333 }
334
335 collected = append(collected, item)
336
337 return nil
338 }
339
340 err = index.RootIfd.EnumerateTagsRecursively(cb)
341 log.PanicIf(err)
342
343 expected := [][2]interface{}{
344 {"IFD", 0x010f},
345 {"IFD", 0x0110},
346 {"IFD", 0x0112},
347 {"IFD", 0x011a},
348 {"IFD", 0x011b},
349 {"IFD", 0x0128},
350 {"IFD", 0x0132},
351 {"IFD", 0x013b},
352 {"IFD", 0x0213},
353 {"IFD", 0x8298},
354 {"IFD/Exif", 0x829a},
355 {"IFD/Exif", 0x829d},
356 {"IFD/Exif", 0x8822},
357 {"IFD/Exif", 0x8827},
358 {"IFD/Exif", 0x8830},
359 {"IFD/Exif", 0x8832},
360 {"IFD/Exif", 0x9000},
361 {"IFD/Exif", 0x9003},
362 {"IFD/Exif", 0x9004},
363 {"IFD/Exif", 0x9101},
364 {"IFD/Exif", 0x9201},
365 {"IFD/Exif", 0x9202},
366 {"IFD/Exif", 0x9204},
367 {"IFD/Exif", 0x9207},
368 {"IFD/Exif", 0x9209},
369 {"IFD/Exif", 0x920a},
370 {"IFD/Exif", 0x927c},
371 {"IFD/Exif", 0x9286},
372 {"IFD/Exif", 0x9290},
373 {"IFD/Exif", 0x9291},
374 {"IFD/Exif", 0x9292},
375 {"IFD/Exif", 0xa000},
376 {"IFD/Exif", 0xa001},
377 {"IFD/Exif", 0xa002},
378 {"IFD/Exif", 0xa003},
379 {"IFD/Exif/Iop", 0x0001},
380 {"IFD/Exif/Iop", 0x0002},
381 {"IFD/Exif", 0xa20e},
382 {"IFD/Exif", 0xa20f},
383 {"IFD/Exif", 0xa210},
384 {"IFD/Exif", 0xa401},
385 {"IFD/Exif", 0xa402},
386 {"IFD/Exif", 0xa403},
387 {"IFD/Exif", 0xa406},
388 {"IFD/Exif", 0xa430},
389 {"IFD/Exif", 0xa431},
390 {"IFD/Exif", 0xa432},
391 {"IFD/Exif", 0xa434},
392 {"IFD/Exif", 0xa435},
393 {"IFD/GPSInfo", 0x0000},
394 {"IFD", 0x010f},
395 {"IFD", 0x0110},
396 {"IFD", 0x0112},
397 {"IFD", 0x011a},
398 {"IFD", 0x011b},
399 {"IFD", 0x0128},
400 {"IFD", 0x0132},
401 {"IFD", 0x013b},
402 {"IFD", 0x0213},
403 {"IFD", 0x8298},
404 {"IFD/Exif", 0x829a},
405 {"IFD/Exif", 0x829d},
406 {"IFD/Exif", 0x8822},
407 {"IFD/Exif", 0x8827},
408 {"IFD/Exif", 0x8830},
409 {"IFD/Exif", 0x8832},
410 {"IFD/Exif", 0x9000},
411 {"IFD/Exif", 0x9003},
412 {"IFD/Exif", 0x9004},
413 {"IFD/Exif", 0x9101},
414 {"IFD/Exif", 0x9201},
415 {"IFD/Exif", 0x9202},
416 {"IFD/Exif", 0x9204},
417 {"IFD/Exif", 0x9207},
418 {"IFD/Exif", 0x9209},
419 {"IFD/Exif", 0x920a},
420 {"IFD/Exif", 0x927c},
421 {"IFD/Exif", 0x9286},
422 {"IFD/Exif", 0x9290},
423 {"IFD/Exif", 0x9291},
424 {"IFD/Exif", 0x9292},
425 {"IFD/Exif", 0xa000},
426 {"IFD/Exif", 0xa001},
427 {"IFD/Exif", 0xa002},
428 {"IFD/Exif", 0xa003},
429 {"IFD/Exif/Iop", 0x0001},
430 {"IFD/Exif/Iop", 0x0002},
431 {"IFD/Exif", 0xa20e},
432 {"IFD/Exif", 0xa20f},
433 {"IFD/Exif", 0xa210},
434 {"IFD/Exif", 0xa401},
435 {"IFD/Exif", 0xa402},
436 {"IFD/Exif", 0xa403},
437 {"IFD/Exif", 0xa406},
438 {"IFD/Exif", 0xa430},
439 {"IFD/Exif", 0xa431},
440 {"IFD/Exif", 0xa432},
441 {"IFD/Exif", 0xa434},
442 {"IFD/Exif", 0xa435},
443 {"IFD/GPSInfo", 0x0000},
444 }
445
446 if reflect.DeepEqual(collected, expected) != true {
447 fmt.Printf("ACTUAL:\n")
448 fmt.Printf("\n")
449
450 for _, item := range collected {
451 fmt.Printf("[2]interface{} { \"%s\", 0x%04x },\n", item[0], item[1])
452 }
453
454 fmt.Printf("\n")
455
456 fmt.Printf("EXPECTED:\n")
457 fmt.Printf("\n")
458
459 for _, item := range expected {
460 fmt.Printf("[2]interface{} { \"%s\", 0x%04x },\n", item[0], item[1])
461 }
462
463 fmt.Printf("\n")
464
465 t.Fatalf("tags not visited correctly")
466 }
467 }
468
469 func ExampleIfd_EnumerateTagsRecursively() {
470 testImageFilepath := getTestImageFilepath()
471
472 rawExif, err := SearchFileAndExtractExif(testImageFilepath)
473 log.PanicIf(err)
474
475 im, err := exifcommon.NewIfdMappingWithStandard()
476 log.PanicIf(err)
477
478 ti := NewTagIndex()
479
480 _, index, err := Collect(im, ti, rawExif)
481 log.PanicIf(err)
482
483 cb := func(ifd *Ifd, ite *IfdTagEntry) error {
484
485
486
487 return nil
488 }
489
490 err = index.RootIfd.EnumerateTagsRecursively(cb)
491 log.PanicIf(err)
492
493
494 }
495
496 func ExampleIfd_GpsInfo() {
497 filepath := getTestGpsImageFilepath()
498
499 rawExif, err := SearchFileAndExtractExif(filepath)
500 log.PanicIf(err)
501
502 im, err := exifcommon.NewIfdMappingWithStandard()
503 log.PanicIf(err)
504
505 ti := NewTagIndex()
506
507 _, index, err := Collect(im, ti, rawExif)
508 log.PanicIf(err)
509
510 ifd, err := index.RootIfd.ChildWithIfdPath(exifcommon.IfdGpsInfoStandardIfdIdentity)
511 log.PanicIf(err)
512
513 gi, err := ifd.GpsInfo()
514 log.PanicIf(err)
515
516 fmt.Printf("%s\n", gi)
517
518
519
520 }
521
522 func ExampleIfd_FindTagWithName() {
523 testImageFilepath := getTestImageFilepath()
524
525 rawExif, err := SearchFileAndExtractExif(testImageFilepath)
526 log.PanicIf(err)
527
528 im, err := exifcommon.NewIfdMappingWithStandard()
529 log.PanicIf(err)
530
531 ti := NewTagIndex()
532
533 _, index, err := Collect(im, ti, rawExif)
534 log.PanicIf(err)
535
536 tagName := "Model"
537
538 rootIfd := index.RootIfd
539
540
541 results, err := rootIfd.FindTagWithName(tagName)
542 log.PanicIf(err)
543
544
545 if len(results) != 1 {
546 log.Panicf("there wasn't exactly one result")
547 }
548
549 ite := results[0]
550
551 valueRaw, err := ite.Value()
552 log.PanicIf(err)
553
554 value := valueRaw.(string)
555 fmt.Println(value)
556
557
558
559 }
560
View as plain text