...

Source file src/github.com/dsoprea/go-exif/v3/ifd_enumerate_test.go

Documentation: github.com/dsoprea/go-exif/v3

     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  	// The thumbnail is in IFD1 (The second root IFD).
   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  		// Something useful.
   486  
   487  		return nil
   488  	}
   489  
   490  	err = index.RootIfd.EnumerateTagsRecursively(cb)
   491  	log.PanicIf(err)
   492  
   493  	// Output:
   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  	// Output:
   519  	// GpsInfo<LAT=(26.58667) LON=(-80.05361) ALT=(0) TIME=[2018-04-29 01:22:57 +0000 UTC]>
   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  	// We know the tag we want is on IFD0 (the first/root IFD).
   541  	results, err := rootIfd.FindTagWithName(tagName)
   542  	log.PanicIf(err)
   543  
   544  	// This should never happen.
   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  	// Output:
   558  	// Canon EOS 5D Mark III
   559  }
   560  

View as plain text