backwards incompatible: ifd_enumerate.go: Stop exporting Ifd fields

Finally.
dustin/master
Dustin Oprea 2020-07-11 13:04:59 -04:00
parent dcd29a9733
commit f2c3d1c0ec
7 changed files with 188 additions and 138 deletions

View File

@ -267,10 +267,10 @@ func TestCollect(t *testing.T) {
tree := index.Tree tree := index.Tree
lookup := index.Lookup lookup := index.Lookup
if rootIfd.Offset != uint32(0x0008) { if rootIfd.Offset() != uint32(0x0008) {
t.Fatalf("Root-IFD not correct: (0x%04d).", rootIfd.Offset) t.Fatalf("Root-IFD not correct: (0x%04d).", rootIfd.Offset())
} else if rootIfd.Id != 0 { } else if rootIfd.id != 0 {
t.Fatalf("Root-IFD does not have the right ID: (%d)", rootIfd.Id) t.Fatalf("Root-IFD does not have the right ID: (%d)", rootIfd.id)
} else if tree[0] != rootIfd { } else if tree[0] != rootIfd {
t.Fatalf("Root-IFD is not indexed properly.") t.Fatalf("Root-IFD is not indexed properly.")
} else if len(ifds) != 5 { } else if len(ifds) != 5 {
@ -300,26 +300,26 @@ func TestCollect(t *testing.T) {
t.Fatalf("The IFD lookup is not the right size: %v", actualIfdPaths) t.Fatalf("The IFD lookup is not the right size: %v", actualIfdPaths)
} }
if rootIfd.NextIfdOffset != 0x2c54 { if rootIfd.nextIfdOffset != 0x2c54 {
t.Fatalf("Root IFD does not continue correctly: (0x%04x)", rootIfd.NextIfdOffset) t.Fatalf("Root IFD does not continue correctly: (0x%04x)", rootIfd.nextIfdOffset)
} else if rootIfd.NextIfd.Offset != rootIfd.NextIfdOffset { } else if rootIfd.nextIfd.Offset() != rootIfd.nextIfdOffset {
t.Fatalf("Root IFD neighbor object does not have the right offset: (0x%04x != 0x%04x)", rootIfd.NextIfd.Offset, rootIfd.NextIfdOffset) t.Fatalf("Root IFD neighbor object does not have the right offset: (0x%04x != 0x%04x)", rootIfd.nextIfd.Offset(), rootIfd.nextIfdOffset)
} else if rootIfd.NextIfd.NextIfdOffset != 0 { } else if rootIfd.nextIfd.nextIfdOffset != 0 {
t.Fatalf("Root IFD chain not terminated correctly (1).") t.Fatalf("Root IFD chain not terminated correctly (1).")
} else if rootIfd.NextIfd.NextIfd != nil { } else if rootIfd.nextIfd.nextIfd != nil {
t.Fatalf("Root IFD chain not terminated correctly (2).") t.Fatalf("Root IFD chain not terminated correctly (2).")
} }
if rootIfd.ifdIdentity.UnindexedString() != exifcommon.IfdStandardIfdIdentity.UnindexedString() { if rootIfd.ifdIdentity.UnindexedString() != exifcommon.IfdStandardIfdIdentity.UnindexedString() {
t.Fatalf("Root IFD is not labeled correctly: [%s]", rootIfd.ifdIdentity.UnindexedString()) t.Fatalf("Root IFD is not labeled correctly: [%s]", rootIfd.ifdIdentity.UnindexedString())
} else if rootIfd.NextIfd.ifdIdentity.UnindexedString() != exifcommon.IfdStandardIfdIdentity.UnindexedString() { } else if rootIfd.nextIfd.ifdIdentity.UnindexedString() != exifcommon.IfdStandardIfdIdentity.UnindexedString() {
t.Fatalf("Root IFD sibling is not labeled correctly: [%s]", rootIfd.ifdIdentity.UnindexedString()) t.Fatalf("Root IFD sibling is not labeled correctly: [%s]", rootIfd.ifdIdentity.UnindexedString())
} else if rootIfd.Children[0].ifdIdentity.UnindexedString() != exifcommon.IfdExifStandardIfdIdentity.UnindexedString() { } else if rootIfd.Children()[0].ifdIdentity.UnindexedString() != exifcommon.IfdExifStandardIfdIdentity.UnindexedString() {
t.Fatalf("Root IFD child (0) is not labeled correctly: [%s]", rootIfd.Children[0].ifdIdentity.UnindexedString()) t.Fatalf("Root IFD child (0) is not labeled correctly: [%s]", rootIfd.Children()[0].ifdIdentity.UnindexedString())
} else if rootIfd.Children[1].ifdIdentity.UnindexedString() != exifcommon.IfdGpsInfoStandardIfdIdentity.UnindexedString() { } else if rootIfd.Children()[1].ifdIdentity.UnindexedString() != exifcommon.IfdGpsInfoStandardIfdIdentity.UnindexedString() {
t.Fatalf("Root IFD child (1) is not labeled correctly: [%s]", rootIfd.Children[1].ifdIdentity.UnindexedString()) t.Fatalf("Root IFD child (1) is not labeled correctly: [%s]", rootIfd.Children()[1].ifdIdentity.UnindexedString())
} else if rootIfd.Children[0].Children[0].ifdIdentity.UnindexedString() != exifcommon.IfdExifIopStandardIfdIdentity.UnindexedString() { } else if rootIfd.Children()[0].children[0].ifdIdentity.UnindexedString() != exifcommon.IfdExifIopStandardIfdIdentity.UnindexedString() {
t.Fatalf("Exif IFD child is not an IOP IFD: [%s]", rootIfd.Children[0].Children[0].ifdIdentity.UnindexedString()) t.Fatalf("Exif IFD child is not an IOP IFD: [%s]", rootIfd.Children()[0].children[0].ifdIdentity.UnindexedString())
} }
if lookup[exifcommon.IfdStandardIfdIdentity.UnindexedString()].ifdIdentity.UnindexedString() != exifcommon.IfdStandardIfdIdentity.UnindexedString() { if lookup[exifcommon.IfdStandardIfdIdentity.UnindexedString()].ifdIdentity.UnindexedString() != exifcommon.IfdStandardIfdIdentity.UnindexedString() {
@ -342,7 +342,7 @@ func TestCollect(t *testing.T) {
foundExif := 0 foundExif := 0
foundGps := 0 foundGps := 0
for _, ite := range lookup[exifcommon.IfdStandardIfdIdentity.UnindexedString()].Entries { for _, ite := range lookup[exifcommon.IfdStandardIfdIdentity.UnindexedString()].entries {
if ite.ChildIfdPath() == exifcommon.IfdExifStandardIfdIdentity.UnindexedString() { if ite.ChildIfdPath() == exifcommon.IfdExifStandardIfdIdentity.UnindexedString() {
foundExif++ foundExif++
@ -367,7 +367,7 @@ func TestCollect(t *testing.T) {
} }
foundIop := 0 foundIop := 0
for _, ite := range lookup[exifcommon.IfdExifStandardIfdIdentity.UnindexedString()].Entries { for _, ite := range lookup[exifcommon.IfdExifStandardIfdIdentity.UnindexedString()].entries {
if ite.ChildIfdPath() == exifcommon.IfdExifIopStandardIfdIdentity.UnindexedString() { if ite.ChildIfdPath() == exifcommon.IfdExifIopStandardIfdIdentity.UnindexedString() {
foundIop++ foundIop++

View File

@ -262,8 +262,8 @@ func NewIfdBuilderWithExistingIfd(ifd *Ifd) (ib *IfdBuilder) {
ib = &IfdBuilder{ ib = &IfdBuilder{
ifdIdentity: ifd.IfdIdentity(), ifdIdentity: ifd.IfdIdentity(),
byteOrder: ifd.ByteOrder, byteOrder: ifd.ByteOrder(),
existingOffset: ifd.Offset, existingOffset: ifd.Offset(),
ifdMapping: ifd.ifdMapping, ifdMapping: ifd.ifdMapping,
tagIndex: ifd.tagIndex, tagIndex: ifd.tagIndex,
} }
@ -276,12 +276,12 @@ func NewIfdBuilderWithExistingIfd(ifd *Ifd) (ib *IfdBuilder) {
func NewIfdBuilderFromExistingChain(rootIfd *Ifd) (firstIb *IfdBuilder) { func NewIfdBuilderFromExistingChain(rootIfd *Ifd) (firstIb *IfdBuilder) {
var lastIb *IfdBuilder var lastIb *IfdBuilder
i := 0 i := 0
for thisExistingIfd := rootIfd; thisExistingIfd != nil; thisExistingIfd = thisExistingIfd.NextIfd { for thisExistingIfd := rootIfd; thisExistingIfd != nil; thisExistingIfd = thisExistingIfd.nextIfd {
newIb := NewIfdBuilder( newIb := NewIfdBuilder(
rootIfd.ifdMapping, rootIfd.ifdMapping,
rootIfd.tagIndex, rootIfd.tagIndex,
rootIfd.ifdIdentity, rootIfd.ifdIdentity,
thisExistingIfd.ByteOrder) thisExistingIfd.ByteOrder())
if firstIb == nil { if firstIb == nil {
firstIb = newIb firstIb = newIb
@ -1005,7 +1005,7 @@ func (ib *IfdBuilder) AddTagsFromExisting(ifd *Ifd, includeTagIds []uint16, excl
log.Panic(err) log.Panic(err)
} }
for i, ite := range ifd.Entries { for i, ite := range ifd.Entries() {
if ite.IsThumbnailOffset() == true || ite.IsThumbnailSize() { if ite.IsThumbnailOffset() == true || ite.IsThumbnailSize() {
// These will be added on-the-fly when we encode. // These will be added on-the-fly when we encode.
continue continue
@ -1051,11 +1051,11 @@ func (ib *IfdBuilder) AddTagsFromExisting(ifd *Ifd, includeTagIds []uint16, excl
// this IFD represents this specific child IFD. // this IFD represents this specific child IFD.
var childIfd *Ifd var childIfd *Ifd
for _, thisChildIfd := range ifd.Children { for _, thisChildIfd := range ifd.Children() {
if thisChildIfd.ParentTagIndex != i { if thisChildIfd.ParentTagIndex() != i {
continue continue
} else if thisChildIfd.ifdIdentity.TagId() != 0xffff && thisChildIfd.ifdIdentity.TagId() != ite.TagId() { } else if thisChildIfd.ifdIdentity.TagId() != 0xffff && thisChildIfd.ifdIdentity.TagId() != ite.TagId() {
log.Panicf("child-IFD tag is not correct: TAG-POSITION=(%d) ITE=%s CHILD-IFD=%s", thisChildIfd.ParentTagIndex, ite, thisChildIfd) log.Panicf("child-IFD tag is not correct: TAG-POSITION=(%d) ITE=%s CHILD-IFD=%s", thisChildIfd.ParentTagIndex(), ite, thisChildIfd)
} }
childIfd = thisChildIfd childIfd = thisChildIfd
@ -1063,9 +1063,9 @@ func (ib *IfdBuilder) AddTagsFromExisting(ifd *Ifd, includeTagIds []uint16, excl
} }
if childIfd == nil { if childIfd == nil {
childTagIds := make([]string, len(ifd.Children)) childTagIds := make([]string, len(ifd.Children()))
for j, childIfd := range ifd.Children { for j, childIfd := range ifd.Children() {
childTagIds[j] = fmt.Sprintf("0x%04x (parent tag-position %d)", childIfd.ifdIdentity.TagId(), childIfd.ParentTagIndex) childTagIds[j] = fmt.Sprintf("0x%04x (parent tag-position %d)", childIfd.ifdIdentity.TagId(), childIfd.ParentTagIndex())
} }
log.Panicf("could not find child IFD for child ITE: IFD-PATH=[%s] TAG-ID=(0x%04x) CURRENT-TAG-POSITION=(%d) CHILDREN=%v", ite.IfdPath(), ite.TagId(), i, childTagIds) log.Panicf("could not find child IFD for child ITE: IFD-PATH=[%s] TAG-ID=(0x%04x) CURRENT-TAG-POSITION=(%d) CHILDREN=%v", ite.IfdPath(), ite.TagId(), i, childTagIds)

View File

@ -860,7 +860,7 @@ func ExampleIfdByteEncoder_EncodeToExif() {
_, index, err := Collect(im, ti, exifData) _, index, err := Collect(im, ti, exifData)
log.PanicIf(err) log.PanicIf(err)
for i, ite := range index.RootIfd.Entries { for i, ite := range index.RootIfd.Entries() {
value, err := ite.Value() value, err := ite.Value()
log.PanicIf(err) log.PanicIf(err)

View File

@ -1584,7 +1584,7 @@ func TestIfdBuilder_NewIfdBuilderFromExistingChain_RealData(t *testing.T) {
_, originalIndex, err := Collect(im, ti, rawExif) _, originalIndex, err := Collect(im, ti, rawExif)
log.PanicIf(err) log.PanicIf(err)
originalThumbnailData, err := originalIndex.RootIfd.NextIfd.Thumbnail() originalThumbnailData, err := originalIndex.RootIfd.nextIfd.Thumbnail()
log.PanicIf(err) log.PanicIf(err)
originalTags := originalIndex.RootIfd.DumpTags() originalTags := originalIndex.RootIfd.DumpTags()
@ -1605,7 +1605,7 @@ func TestIfdBuilder_NewIfdBuilderFromExistingChain_RealData(t *testing.T) {
recoveredTags := recoveredIndex.RootIfd.DumpTags() recoveredTags := recoveredIndex.RootIfd.DumpTags()
recoveredThumbnailData, err := recoveredIndex.RootIfd.NextIfd.Thumbnail() recoveredThumbnailData, err := recoveredIndex.RootIfd.nextIfd.Thumbnail()
log.PanicIf(err) log.PanicIf(err)
// Check the thumbnail. // Check the thumbnail.
@ -1740,7 +1740,7 @@ func TestIfdBuilder_NewIfdBuilderFromExistingChain_RealData(t *testing.T) {
// _, originalIndex, err := Collect(im, ti, rawExif) // _, originalIndex, err := Collect(im, ti, rawExif)
// log.PanicIf(err) // log.PanicIf(err)
// originalThumbnailData, err := originalIndex.RootIfd.NextIfd.Thumbnail() // originalThumbnailData, err := originalIndex.RootIfd.nextIfd.Thumbnail()
// log.PanicIf(err) // log.PanicIf(err)
// originalTags := originalIndex.RootIfd.DumpTags() // originalTags := originalIndex.RootIfd.DumpTags()
@ -1779,7 +1779,7 @@ func TestIfdBuilder_NewIfdBuilderFromExistingChain_RealData(t *testing.T) {
// recoveredTags := recoveredIndex.RootIfd.DumpTags() // recoveredTags := recoveredIndex.RootIfd.DumpTags()
// recoveredThumbnailData, err := recoveredIndex.RootIfd.NextIfd.Thumbnail() // recoveredThumbnailData, err := recoveredIndex.RootIfd.nextIfd.Thumbnail()
// log.PanicIf(err) // log.PanicIf(err)
// // Check the thumbnail. // // Check the thumbnail.
@ -1845,10 +1845,10 @@ func TestIfdBuilder_NewIfdBuilderFromExistingChain_RealData(t *testing.T) {
// t.Fatalf("Tag-type not as expected: %d != %d ITE=%s", recoveredIte.TagType(), originalIte.TagType(), recoveredIte) // t.Fatalf("Tag-type not as expected: %d != %d ITE=%s", recoveredIte.TagType(), originalIte.TagType(), recoveredIte)
// } // }
// originalValueBytes, err := originalIte.ValueBytes(originalIndex.RootIfd.addressableData, originalIndex.RootIfd.ByteOrder) // originalValueBytes, err := originalIte.ValueBytes(originalIndex.RootIfd.addressableData, originalIndex.RootIfd.ByteOrder())
// log.PanicIf(err) // log.PanicIf(err)
// recoveredValueBytes, err := recoveredIte.ValueBytes(recoveredIndex.RootIfd.addressableData, recoveredIndex.RootIfd.ByteOrder) // recoveredValueBytes, err := recoveredIte.ValueBytes(recoveredIndex.RootIfd.addressableData, recoveredIndex.RootIfd.ByteOrder())
// log.PanicIf(err) // log.PanicIf(err)
// if recoveredIte.TagId() == 0x9286 { // if recoveredIte.TagId() == 0x9286 {
@ -1882,7 +1882,7 @@ func ExampleIfd_Thumbnail() {
// This returns the raw bytes that you will be looking for, but there's no // This returns the raw bytes that you will be looking for, but there's no
// use for them at this point in the example. // use for them at this point in the example.
_, err = index.RootIfd.NextIfd.Thumbnail() _, err = index.RootIfd.nextIfd.Thumbnail()
log.PanicIf(err) log.PanicIf(err)
// Output: // Output:
@ -2036,9 +2036,9 @@ func TestIfdBuilder_CreateIfdBuilderWithExistingIfd(t *testing.T) {
ifd := &Ifd{ ifd := &Ifd{
ifdIdentity: exifcommon.IfdGpsInfoStandardIfdIdentity, ifdIdentity: exifcommon.IfdGpsInfoStandardIfdIdentity,
ByteOrder: exifcommon.TestDefaultByteOrder, byteOrder: exifcommon.TestDefaultByteOrder,
Offset: 0x123, offset: 0x123,
ParentIfd: parentIfd, parentIfd: parentIfd,
ifdMapping: im, ifdMapping: im,
tagIndex: ti, tagIndex: ti,
@ -2050,9 +2050,9 @@ func TestIfdBuilder_CreateIfdBuilderWithExistingIfd(t *testing.T) {
t.Fatalf("IFD-name not correct.") t.Fatalf("IFD-name not correct.")
} else if ib.IfdIdentity().TagId() != tagId { } else if ib.IfdIdentity().TagId() != tagId {
t.Fatalf("IFD tag-ID not correct.") t.Fatalf("IFD tag-ID not correct.")
} else if ib.byteOrder != ifd.ByteOrder { } else if ib.byteOrder != ifd.ByteOrder() {
t.Fatalf("IFD byte-order not correct.") t.Fatalf("IFD byte-order not correct.")
} else if ib.existingOffset != ifd.Offset { } else if ib.existingOffset != ifd.Offset() {
t.Fatalf("IFD offset not correct.") t.Fatalf("IFD offset not correct.")
} }
} }

View File

@ -627,39 +627,32 @@ func (ie *IfdEnumerate) Scan(iiRoot *exifcommon.IfdIdentity, ifdOffset uint32, v
// Ifd represents a single, parsed IFD. // Ifd represents a single, parsed IFD.
type Ifd struct { type Ifd struct {
// RELEASE(dustin): !! Why are all of these exported? Stop doing this in the next release.
// TODO(dustin): Add NextIfd().
ifdIdentity *exifcommon.IfdIdentity ifdIdentity *exifcommon.IfdIdentity
ByteOrder binary.ByteOrder ifdMapping *exifcommon.IfdMapping
tagIndex *TagIndex
Id int offset uint32
byteOrder binary.ByteOrder
id int
ParentIfd *Ifd parentIfd *Ifd
// ParentTagIndex is our tag position in the parent IFD, if we had a parent // ParentTagIndex is our tag position in the parent IFD, if we had a parent
// (if `ParentIfd` is not nil and we weren't an IFD referenced as a sibling // (if `ParentIfd` is not nil and we weren't an IFD referenced as a sibling
// instead of as a child). // instead of as a child).
ParentTagIndex int parentTagIndex int
Offset uint32 entries []*IfdTagEntry
entriesByTagId map[uint16][]*IfdTagEntry
Entries []*IfdTagEntry children []*Ifd
EntriesByTagId map[uint16][]*IfdTagEntry childIfdIndex map[string]*Ifd
Children []*Ifd
ChildIfdIndex map[string]*Ifd
NextIfdOffset uint32
NextIfd *Ifd
thumbnailData []byte thumbnailData []byte
ifdMapping *exifcommon.IfdMapping nextIfdOffset uint32
tagIndex *TagIndex nextIfd *Ifd
} }
// IfdIdentity returns IFD identity that this struct represents. // IfdIdentity returns IFD identity that this struct represents.
@ -667,6 +660,63 @@ func (ifd *Ifd) IfdIdentity() *exifcommon.IfdIdentity {
return ifd.ifdIdentity return ifd.ifdIdentity
} }
// Entries returns a flat list of all tags for this IFD.
func (ifd *Ifd) Entries() []*IfdTagEntry {
// TODO(dustin): Add test
return ifd.entries
}
// EntriesByTagId returns a map of all tags for this IFD.
func (ifd *Ifd) EntriesByTagId() map[uint16][]*IfdTagEntry {
// TODO(dustin): Add test
return ifd.entriesByTagId
}
// Children returns a flat list of all child IFDs of this IFD.
func (ifd *Ifd) Children() []*Ifd {
// TODO(dustin): Add test
return ifd.children
}
// ChildWithIfdPath returns a map of all child IFDs of this IFD.
func (ifd *Ifd) ChildIfdIndex() map[string]*Ifd {
// TODO(dustin): Add test
return ifd.childIfdIndex
}
// ParentTagIndex returns the position of this IFD's tag in its parent IFD (*if*
// there is a parent).
func (ifd *Ifd) ParentTagIndex() int {
// TODO(dustin): Add test
return ifd.parentTagIndex
}
// Offset returns the offset of the IFD in the stream.
func (ifd *Ifd) Offset() uint32 {
// TODO(dustin): Add test
return ifd.offset
}
// Offset returns the offset of the IFD in the stream.
func (ifd *Ifd) ByteOrder() binary.ByteOrder {
// TODO(dustin): Add test
return ifd.byteOrder
}
// ChildWithIfdPath returns an `Ifd` struct for the given child of the current // ChildWithIfdPath returns an `Ifd` struct for the given child of the current
// IFD. // IFD.
func (ifd *Ifd) ChildWithIfdPath(iiChild *exifcommon.IfdIdentity) (childIfd *Ifd, err error) { func (ifd *Ifd) ChildWithIfdPath(iiChild *exifcommon.IfdIdentity) (childIfd *Ifd, err error) {
@ -679,7 +729,7 @@ func (ifd *Ifd) ChildWithIfdPath(iiChild *exifcommon.IfdIdentity) (childIfd *Ifd
// TODO(dustin): This is a bridge while we're introducing the IFD type-system. We should be able to use the (IfdIdentity).Equals() method for this. // TODO(dustin): This is a bridge while we're introducing the IFD type-system. We should be able to use the (IfdIdentity).Equals() method for this.
ifdPath := iiChild.UnindexedString() ifdPath := iiChild.UnindexedString()
for _, childIfd := range ifd.Children { for _, childIfd := range ifd.children {
if childIfd.ifdIdentity.UnindexedString() == ifdPath { if childIfd.ifdIdentity.UnindexedString() == ifdPath {
return childIfd, nil return childIfd, nil
} }
@ -698,7 +748,7 @@ func (ifd *Ifd) FindTagWithId(tagId uint16) (results []*IfdTagEntry, err error)
} }
}() }()
results, found := ifd.EntriesByTagId[tagId] results, found := ifd.entriesByTagId[tagId]
if found != true { if found != true {
log.Panic(ErrTagNotFound) log.Panic(ErrTagNotFound)
} }
@ -723,7 +773,7 @@ func (ifd *Ifd) FindTagWithName(tagName string) (results []*IfdTagEntry, err err
} }
results = make([]*IfdTagEntry, 0) results = make([]*IfdTagEntry, 0)
for _, ite := range ifd.Entries { for _, ite := range ifd.entries {
if ite.TagId() == it.Id { if ite.TagId() == it.Id {
results = append(results, ite) results = append(results, ite)
} }
@ -739,11 +789,11 @@ func (ifd *Ifd) FindTagWithName(tagName string) (results []*IfdTagEntry, err err
// String returns a description string. // String returns a description string.
func (ifd *Ifd) String() string { func (ifd *Ifd) String() string {
parentOffset := uint32(0) parentOffset := uint32(0)
if ifd.ParentIfd != nil { if ifd.parentIfd != nil {
parentOffset = ifd.ParentIfd.Offset parentOffset = ifd.parentIfd.offset
} }
return fmt.Sprintf("Ifd<ID=(%d) IFD-PATH=[%s] INDEX=(%d) COUNT=(%d) OFF=(0x%04x) CHILDREN=(%d) PARENT=(0x%04x) NEXT-IFD=(0x%04x)>", ifd.Id, ifd.ifdIdentity.UnindexedString(), ifd.ifdIdentity.Index(), len(ifd.Entries), ifd.Offset, len(ifd.Children), parentOffset, ifd.NextIfdOffset) return fmt.Sprintf("Ifd<ID=(%d) IFD-PATH=[%s] INDEX=(%d) COUNT=(%d) OFF=(0x%04x) CHILDREN=(%d) PARENT=(0x%04x) NEXT-IFD=(0x%04x)>", ifd.id, ifd.ifdIdentity.UnindexedString(), ifd.ifdIdentity.Index(), len(ifd.entries), ifd.offset, len(ifd.children), parentOffset, ifd.nextIfdOffset)
} }
// Thumbnail returns the raw thumbnail bytes. This is typically directly // Thumbnail returns the raw thumbnail bytes. This is typically directly
@ -767,14 +817,14 @@ func (ifd *Ifd) dumpTags(tags []*IfdTagEntry) []*IfdTagEntry {
ifdsFoundCount := 0 ifdsFoundCount := 0
for _, ite := range ifd.Entries { for _, ite := range ifd.entries {
tags = append(tags, ite) tags = append(tags, ite)
childIfdPath := ite.ChildIfdPath() childIfdPath := ite.ChildIfdPath()
if childIfdPath != "" { if childIfdPath != "" {
ifdsFoundCount++ ifdsFoundCount++
childIfd, found := ifd.ChildIfdIndex[childIfdPath] childIfd, found := ifd.childIfdIndex[childIfdPath]
if found != true { if found != true {
log.Panicf("alien child IFD referenced by a tag: [%s]", childIfdPath) log.Panicf("alien child IFD referenced by a tag: [%s]", childIfdPath)
} }
@ -783,12 +833,12 @@ func (ifd *Ifd) dumpTags(tags []*IfdTagEntry) []*IfdTagEntry {
} }
} }
if len(ifd.Children) != ifdsFoundCount { if len(ifd.children) != ifdsFoundCount {
log.Panicf("have one or more dangling child IFDs: (%d) != (%d)", len(ifd.Children), ifdsFoundCount) log.Panicf("have one or more dangling child IFDs: (%d) != (%d)", len(ifd.children), ifdsFoundCount)
} }
if ifd.NextIfd != nil { if ifd.nextIfd != nil {
tags = ifd.NextIfd.dumpTags(tags) tags = ifd.nextIfd.dumpTags(tags)
} }
return tags return tags
@ -813,7 +863,7 @@ func (ifd *Ifd) printTagTree(populateValues bool, index, level int, nextLink boo
ifdsFoundCount := 0 ifdsFoundCount := 0
for _, ite := range ifd.Entries { for _, ite := range ifd.entries {
if ite.ChildIfdPath() != "" { if ite.ChildIfdPath() != "" {
fmt.Printf("%s - TAG: %s\n", indent, ite) fmt.Printf("%s - TAG: %s\n", indent, ite)
} else { } else {
@ -857,7 +907,7 @@ func (ifd *Ifd) printTagTree(populateValues bool, index, level int, nextLink boo
if childIfdPath != "" { if childIfdPath != "" {
ifdsFoundCount++ ifdsFoundCount++
childIfd, found := ifd.ChildIfdIndex[childIfdPath] childIfd, found := ifd.childIfdIndex[childIfdPath]
if found != true { if found != true {
log.Panicf("alien child IFD referenced by a tag: [%s]", childIfdPath) log.Panicf("alien child IFD referenced by a tag: [%s]", childIfdPath)
} }
@ -866,12 +916,12 @@ func (ifd *Ifd) printTagTree(populateValues bool, index, level int, nextLink boo
} }
} }
if len(ifd.Children) != ifdsFoundCount { if len(ifd.children) != ifdsFoundCount {
log.Panicf("have one or more dangling child IFDs: (%d) != (%d)", len(ifd.Children), ifdsFoundCount) log.Panicf("have one or more dangling child IFDs: (%d) != (%d)", len(ifd.children), ifdsFoundCount)
} }
if ifd.NextIfd != nil { if ifd.nextIfd != nil {
ifd.NextIfd.printTagTree(populateValues, index+1, level, true) ifd.nextIfd.printTagTree(populateValues, index+1, level, true)
} }
} }
@ -894,12 +944,12 @@ func (ifd *Ifd) printIfdTree(level int, nextLink bool) {
ifdsFoundCount := 0 ifdsFoundCount := 0
for _, ite := range ifd.Entries { for _, ite := range ifd.entries {
childIfdPath := ite.ChildIfdPath() childIfdPath := ite.ChildIfdPath()
if childIfdPath != "" { if childIfdPath != "" {
ifdsFoundCount++ ifdsFoundCount++
childIfd, found := ifd.ChildIfdIndex[childIfdPath] childIfd, found := ifd.childIfdIndex[childIfdPath]
if found != true { if found != true {
log.Panicf("alien child IFD referenced by a tag: [%s]", childIfdPath) log.Panicf("alien child IFD referenced by a tag: [%s]", childIfdPath)
} }
@ -908,12 +958,12 @@ func (ifd *Ifd) printIfdTree(level int, nextLink bool) {
} }
} }
if len(ifd.Children) != ifdsFoundCount { if len(ifd.children) != ifdsFoundCount {
log.Panicf("have one or more dangling child IFDs: (%d) != (%d)", len(ifd.Children), ifdsFoundCount) log.Panicf("have one or more dangling child IFDs: (%d) != (%d)", len(ifd.children), ifdsFoundCount)
} }
if ifd.NextIfd != nil { if ifd.nextIfd != nil {
ifd.NextIfd.printIfdTree(level, true) ifd.nextIfd.printIfdTree(level, true)
} }
} }
@ -930,8 +980,8 @@ func (ifd *Ifd) dumpTree(tagsDump []string, level int) []string {
indent := strings.Repeat(" ", level*2) indent := strings.Repeat(" ", level*2)
var ifdPhrase string var ifdPhrase string
if ifd.ParentIfd != nil { if ifd.parentIfd != nil {
ifdPhrase = fmt.Sprintf("[%s]->[%s]:(%d)", ifd.ParentIfd.ifdIdentity.UnindexedString(), ifd.ifdIdentity.UnindexedString(), ifd.ifdIdentity.Index()) ifdPhrase = fmt.Sprintf("[%s]->[%s]:(%d)", ifd.parentIfd.ifdIdentity.UnindexedString(), ifd.ifdIdentity.UnindexedString(), ifd.ifdIdentity.Index())
} else { } else {
ifdPhrase = fmt.Sprintf("[ROOT]->[%s]:(%d)", ifd.ifdIdentity.UnindexedString(), ifd.ifdIdentity.Index()) ifdPhrase = fmt.Sprintf("[ROOT]->[%s]:(%d)", ifd.ifdIdentity.UnindexedString(), ifd.ifdIdentity.Index())
} }
@ -940,14 +990,14 @@ func (ifd *Ifd) dumpTree(tagsDump []string, level int) []string {
tagsDump = append(tagsDump, startBlurb) tagsDump = append(tagsDump, startBlurb)
ifdsFoundCount := 0 ifdsFoundCount := 0
for _, ite := range ifd.Entries { for _, ite := range ifd.entries {
tagsDump = append(tagsDump, fmt.Sprintf("%s - (0x%04x)", indent, ite.TagId())) tagsDump = append(tagsDump, fmt.Sprintf("%s - (0x%04x)", indent, ite.TagId()))
childIfdPath := ite.ChildIfdPath() childIfdPath := ite.ChildIfdPath()
if childIfdPath != "" { if childIfdPath != "" {
ifdsFoundCount++ ifdsFoundCount++
childIfd, found := ifd.ChildIfdIndex[childIfdPath] childIfd, found := ifd.childIfdIndex[childIfdPath]
if found != true { if found != true {
log.Panicf("alien child IFD referenced by a tag: [%s]", childIfdPath) log.Panicf("alien child IFD referenced by a tag: [%s]", childIfdPath)
} }
@ -956,18 +1006,18 @@ func (ifd *Ifd) dumpTree(tagsDump []string, level int) []string {
} }
} }
if len(ifd.Children) != ifdsFoundCount { if len(ifd.children) != ifdsFoundCount {
log.Panicf("have one or more dangling child IFDs: (%d) != (%d)", len(ifd.Children), ifdsFoundCount) log.Panicf("have one or more dangling child IFDs: (%d) != (%d)", len(ifd.children), ifdsFoundCount)
} }
finishBlurb := fmt.Sprintf("%s< IFD %s BOTTOM", indent, ifdPhrase) finishBlurb := fmt.Sprintf("%s< IFD %s BOTTOM", indent, ifdPhrase)
tagsDump = append(tagsDump, finishBlurb) tagsDump = append(tagsDump, finishBlurb)
if ifd.NextIfd != nil { if ifd.nextIfd != nil {
siblingBlurb := fmt.Sprintf("%s* LINKING TO SIBLING IFD [%s]:(%d)", indent, ifd.NextIfd.ifdIdentity.UnindexedString(), ifd.NextIfd.ifdIdentity.Index()) siblingBlurb := fmt.Sprintf("%s* LINKING TO SIBLING IFD [%s]:(%d)", indent, ifd.nextIfd.ifdIdentity.UnindexedString(), ifd.nextIfd.ifdIdentity.Index())
tagsDump = append(tagsDump, siblingBlurb) tagsDump = append(tagsDump, siblingBlurb)
tagsDump = ifd.NextIfd.dumpTree(tagsDump, level) tagsDump = ifd.nextIfd.dumpTree(tagsDump, level)
} }
return tagsDump return tagsDump
@ -993,7 +1043,7 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
log.Panicf("GPS can only be read on GPS IFD: [%s] != [%s]", ifd.ifdIdentity.UnindexedString(), exifcommon.IfdGpsInfoStandardIfdIdentity.UnindexedString()) log.Panicf("GPS can only be read on GPS IFD: [%s] != [%s]", ifd.ifdIdentity.UnindexedString(), exifcommon.IfdGpsInfoStandardIfdIdentity.UnindexedString())
} }
if tags, found := ifd.EntriesByTagId[TagGpsVersionId]; found == false { if tags, found := ifd.entriesByTagId[TagGpsVersionId]; found == false {
// We've seen this. We'll just have to default to assuming we're in a // We've seen this. We'll just have to default to assuming we're in a
// 2.2.0.0 format. // 2.2.0.0 format.
ifdEnumerateLogger.Warningf(nil, "No GPS version tag (0x%04x) found.", TagGpsVersionId) ifdEnumerateLogger.Warningf(nil, "No GPS version tag (0x%04x) found.", TagGpsVersionId)
@ -1015,7 +1065,7 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
} }
} }
tags, found := ifd.EntriesByTagId[TagLatitudeId] tags, found := ifd.entriesByTagId[TagLatitudeId]
if found == false { if found == false {
ifdEnumerateLogger.Warningf(nil, "latitude not found") ifdEnumerateLogger.Warningf(nil, "latitude not found")
log.Panic(ErrNoGpsTags) log.Panic(ErrNoGpsTags)
@ -1025,7 +1075,7 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
log.PanicIf(err) log.PanicIf(err)
// Look for whether North or South. // Look for whether North or South.
tags, found = ifd.EntriesByTagId[TagLatitudeRefId] tags, found = ifd.entriesByTagId[TagLatitudeRefId]
if found == false { if found == false {
ifdEnumerateLogger.Warningf(nil, "latitude-ref not found") ifdEnumerateLogger.Warningf(nil, "latitude-ref not found")
log.Panic(ErrNoGpsTags) log.Panic(ErrNoGpsTags)
@ -1034,7 +1084,7 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
latitudeRefValue, err := tags[0].Value() latitudeRefValue, err := tags[0].Value()
log.PanicIf(err) log.PanicIf(err)
tags, found = ifd.EntriesByTagId[TagLongitudeId] tags, found = ifd.entriesByTagId[TagLongitudeId]
if found == false { if found == false {
ifdEnumerateLogger.Warningf(nil, "longitude not found") ifdEnumerateLogger.Warningf(nil, "longitude not found")
log.Panic(ErrNoGpsTags) log.Panic(ErrNoGpsTags)
@ -1044,7 +1094,7 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
log.PanicIf(err) log.PanicIf(err)
// Look for whether West or East. // Look for whether West or East.
tags, found = ifd.EntriesByTagId[TagLongitudeRefId] tags, found = ifd.entriesByTagId[TagLongitudeRefId]
if found == false { if found == false {
ifdEnumerateLogger.Warningf(nil, "longitude-ref not found") ifdEnumerateLogger.Warningf(nil, "longitude-ref not found")
log.Panic(ErrNoGpsTags) log.Panic(ErrNoGpsTags)
@ -1067,8 +1117,8 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
// Parse altitude. // Parse altitude.
altitudeTags, foundAltitude := ifd.EntriesByTagId[TagAltitudeId] altitudeTags, foundAltitude := ifd.entriesByTagId[TagAltitudeId]
altitudeRefTags, foundAltitudeRef := ifd.EntriesByTagId[TagAltitudeRefId] altitudeRefTags, foundAltitudeRef := ifd.entriesByTagId[TagAltitudeRefId]
if foundAltitude == true && foundAltitudeRef == true { if foundAltitude == true && foundAltitudeRef == true {
altitudeValue, err := altitudeTags[0].Value() altitudeValue, err := altitudeTags[0].Value()
@ -1089,8 +1139,8 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
// Parse time. // Parse time.
timestampTags, foundTimestamp := ifd.EntriesByTagId[TagTimestampId] timestampTags, foundTimestamp := ifd.entriesByTagId[TagTimestampId]
datestampTags, foundDatestamp := ifd.EntriesByTagId[TagDatestampId] datestampTags, foundDatestamp := ifd.entriesByTagId[TagDatestampId]
if foundTimestamp == true && foundDatestamp == true { if foundTimestamp == true && foundDatestamp == true {
datestampValue, err := datestampTags[0].Value() datestampValue, err := datestampTags[0].Value()
@ -1132,11 +1182,11 @@ func (ifd *Ifd) EnumerateTagsRecursively(visitor ParsedTagVisitor) (err error) {
} }
}() }()
for ptr := ifd; ptr != nil; ptr = ptr.NextIfd { for ptr := ifd; ptr != nil; ptr = ptr.nextIfd {
for _, ite := range ifd.Entries { for _, ite := range ifd.entries {
childIfdPath := ite.ChildIfdPath() childIfdPath := ite.ChildIfdPath()
if childIfdPath != "" { if childIfdPath != "" {
childIfd := ifd.ChildIfdIndex[childIfdPath] childIfd := ifd.childIfdIndex[childIfdPath]
err := childIfd.EnumerateTagsRecursively(visitor) err := childIfd.EnumerateTagsRecursively(visitor)
log.PanicIf(err) log.PanicIf(err)
@ -1247,21 +1297,21 @@ func (ie *IfdEnumerate) Collect(rootIfdOffset uint32) (index IfdIndex, err error
ifd := &Ifd{ ifd := &Ifd{
ifdIdentity: ii, ifdIdentity: ii,
ByteOrder: ie.byteOrder, byteOrder: ie.byteOrder,
Id: id, id: id,
ParentIfd: parentIfd, parentIfd: parentIfd,
ParentTagIndex: qi.ParentTagIndex, parentTagIndex: qi.ParentTagIndex,
Offset: offset, offset: offset,
Entries: entries, entries: entries,
EntriesByTagId: entriesByTagId, entriesByTagId: entriesByTagId,
// This is populated as each child is processed. // This is populated as each child is processed.
Children: make([]*Ifd, 0), children: make([]*Ifd, 0),
NextIfdOffset: nextIfdOffset, nextIfdOffset: nextIfdOffset,
thumbnailData: thumbnailData, thumbnailData: thumbnailData,
ifdMapping: ie.ifdMapping, ifdMapping: ie.ifdMapping,
@ -1279,13 +1329,13 @@ func (ie *IfdEnumerate) Collect(rootIfdOffset uint32) (index IfdIndex, err error
// Add a link from the previous IFD in the chain to us. // Add a link from the previous IFD in the chain to us.
if previousIfd, found := edges[offset]; found == true { if previousIfd, found := edges[offset]; found == true {
previousIfd.NextIfd = ifd previousIfd.nextIfd = ifd
} }
// Attach as a child to our parent (where we appeared as a tag in // Attach as a child to our parent (where we appeared as a tag in
// that IFD). // that IFD).
if parentIfd != nil { if parentIfd != nil {
parentIfd.Children = append(parentIfd.Children, ifd) parentIfd.children = append(parentIfd.children, ifd)
} }
// Determine if any of our entries is a child IFD and queue it. // Determine if any of our entries is a child IFD and queue it.
@ -1355,13 +1405,13 @@ func (ie *IfdEnumerate) setChildrenIndex(ifd *Ifd) (err error) {
}() }()
childIfdIndex := make(map[string]*Ifd) childIfdIndex := make(map[string]*Ifd)
for _, childIfd := range ifd.Children { for _, childIfd := range ifd.children {
childIfdIndex[childIfd.ifdIdentity.UnindexedString()] = childIfd childIfdIndex[childIfd.ifdIdentity.UnindexedString()] = childIfd
} }
ifd.ChildIfdIndex = childIfdIndex ifd.childIfdIndex = childIfdIndex
for _, childIfd := range ifd.Children { for _, childIfd := range ifd.children {
err := ie.setChildrenIndex(childIfd) err := ie.setChildrenIndex(childIfd)
log.PanicIf(err) log.PanicIf(err)
} }
@ -1493,16 +1543,16 @@ func FindIfdFromRootIfd(rootIfd *Ifd, ifdPath string) (ifd *Ifd, err error) {
// TODO(dustin): !! <-- However, we're not sure whether we shouldn't store a secondary IFD-path with the indices. Some IFDs may not necessarily restrict which IFD indices they can be a child of (only the IFD itself matters). Validation should be delegated to the caller. // TODO(dustin): !! <-- However, we're not sure whether we shouldn't store a secondary IFD-path with the indices. Some IFDs may not necessarily restrict which IFD indices they can be a child of (only the IFD itself matters). Validation should be delegated to the caller.
thisIfd := rootIfd thisIfd := rootIfd
for currentRootIndex := 0; currentRootIndex < desiredRootIndex; currentRootIndex++ { for currentRootIndex := 0; currentRootIndex < desiredRootIndex; currentRootIndex++ {
if thisIfd.NextIfd == nil { if thisIfd.nextIfd == nil {
log.Panicf("Root-IFD index (%d) does not exist in the data.", currentRootIndex) log.Panicf("Root-IFD index (%d) does not exist in the data.", currentRootIndex)
} }
thisIfd = thisIfd.NextIfd thisIfd = thisIfd.nextIfd
} }
for _, itii := range lineage { for _, itii := range lineage {
var hit *Ifd var hit *Ifd
for _, childIfd := range thisIfd.Children { for _, childIfd := range thisIfd.children {
if childIfd.ifdIdentity.TagId() == itii.TagId { if childIfd.ifdIdentity.TagId() == itii.TagId {
hit = childIfd hit = childIfd
break break
@ -1511,18 +1561,18 @@ func FindIfdFromRootIfd(rootIfd *Ifd, ifdPath string) (ifd *Ifd, err error) {
// If we didn't find the child, add it. // If we didn't find the child, add it.
if hit == nil { if hit == nil {
log.Panicf("IFD [%s] in [%s] not found: %s", itii.Name, ifdPath, thisIfd.Children) log.Panicf("IFD [%s] in [%s] not found: %s", itii.Name, ifdPath, thisIfd.children)
} }
thisIfd = hit thisIfd = hit
// If we didn't find the sibling, add it. // If we didn't find the sibling, add it.
for i := 0; i < itii.Index; i++ { for i := 0; i < itii.Index; i++ {
if thisIfd.NextIfd == nil { if thisIfd.nextIfd == nil {
log.Panicf("IFD [%s] does not have (%d) occurrences/siblings", thisIfd.ifdIdentity.UnindexedString(), itii.Index) log.Panicf("IFD [%s] does not have (%d) occurrences/siblings", thisIfd.ifdIdentity.UnindexedString(), itii.Index)
} }
thisIfd = thisIfd.NextIfd thisIfd = thisIfd.nextIfd
} }
} }

View File

@ -36,7 +36,7 @@ func TestIfdTagEntry_RawBytes_RealData(t *testing.T) {
log.PanicIf(err) log.PanicIf(err)
var ite *IfdTagEntry var ite *IfdTagEntry
for _, thisIte := range index.RootIfd.Entries { for _, thisIte := range index.RootIfd.entries {
if thisIte.TagId() == 0x0110 { if thisIte.TagId() == 0x0110 {
ite = thisIte ite = thisIte
break break
@ -198,12 +198,12 @@ func TestIfd_Thumbnail(t *testing.T) {
ifd := index.RootIfd ifd := index.RootIfd
if ifd.NextIfd == nil { if ifd.nextIfd == nil {
t.Fatalf("There is no IFD1.") t.Fatalf("There is no IFD1.")
} }
// The thumbnail is in IFD1 (The second root IFD). // The thumbnail is in IFD1 (The second root IFD).
actual, err := ifd.NextIfd.Thumbnail() actual, err := ifd.nextIfd.Thumbnail()
log.PanicIf(err) log.PanicIf(err)
assetsPath := exifcommon.GetTestAssetsPath() assetsPath := exifcommon.GetTestAssetsPath()

View File

@ -113,19 +113,19 @@ func validateExifSimpleTestIb(exifData []byte, t *testing.T) {
ifd := index.RootIfd ifd := index.RootIfd
if ifd.ByteOrder != exifcommon.TestDefaultByteOrder { if ifd.ByteOrder() != exifcommon.TestDefaultByteOrder {
t.Fatalf("IFD byte-order not correct.") t.Fatalf("IFD byte-order not correct.")
} else if ifd.ifdIdentity.UnindexedString() != exifcommon.IfdStandardIfdIdentity.UnindexedString() { } else if ifd.ifdIdentity.UnindexedString() != exifcommon.IfdStandardIfdIdentity.UnindexedString() {
t.Fatalf("IFD name not correct.") t.Fatalf("IFD name not correct.")
} else if ifd.ifdIdentity.Index() != 0 { } else if ifd.ifdIdentity.Index() != 0 {
t.Fatalf("IFD index not zero: (%d)", ifd.ifdIdentity.Index()) t.Fatalf("IFD index not zero: (%d)", ifd.ifdIdentity.Index())
} else if ifd.Offset != uint32(0x0008) { } else if ifd.Offset() != uint32(0x0008) {
t.Fatalf("IFD offset not correct.") t.Fatalf("IFD offset not correct.")
} else if len(ifd.Entries) != 4 { } else if len(ifd.Entries()) != 4 {
t.Fatalf("IFD number of entries not correct: (%d)", len(ifd.Entries)) t.Fatalf("IFD number of entries not correct: (%d)", len(ifd.Entries()))
} else if ifd.NextIfdOffset != uint32(0) { } else if ifd.nextIfdOffset != uint32(0) {
t.Fatalf("Next-IFD offset is non-zero.") t.Fatalf("Next-IFD offset is non-zero.")
} else if ifd.NextIfd != nil { } else if ifd.nextIfd != nil {
t.Fatalf("Next-IFD pointer is non-nil.") t.Fatalf("Next-IFD pointer is non-nil.")
} }
@ -141,7 +141,7 @@ func validateExifSimpleTestIb(exifData []byte, t *testing.T) {
{tagId: 0x013e, value: []exifcommon.Rational{{Numerator: 0x11112222, Denominator: 0x33334444}}}, {tagId: 0x013e, value: []exifcommon.Rational{{Numerator: 0x11112222, Denominator: 0x33334444}}},
} }
for i, ite := range ifd.Entries { for i, ite := range ifd.Entries() {
if ite.TagId() != expected[i].tagId { if ite.TagId() != expected[i].tagId {
t.Fatalf("Tag-ID for entry (%d) not correct: (0x%02x) != (0x%02x)", i, ite.TagId(), expected[i].tagId) t.Fatalf("Tag-ID for entry (%d) not correct: (0x%02x) != (0x%02x)", i, ite.TagId(), expected[i].tagId)
} }