diff --git a/v2/common/type.go b/v2/common/type.go index f08edab..1949cc3 100644 --- a/v2/common/type.go +++ b/v2/common/type.go @@ -130,13 +130,21 @@ var ( typeNamesR = map[string]TagTypePrimitive{} ) +// Rational describes an unsigned rational value. type Rational struct { - Numerator uint32 + // Numerator is the numerator of the rational value. + Numerator uint32 + + // Denominator is the numerator of the rational value. Denominator uint32 } +// SignedRational describes a signed rational value. type SignedRational struct { - Numerator int32 + // Numerator is the numerator of the rational value. + Numerator int32 + + // Denominator is the numerator of the rational value. Denominator int32 } @@ -425,6 +433,18 @@ func GetTypeByName(typeName string) (tagType TagTypePrimitive, found bool) { return tagType, found } +// BasicTag describes a single tag for any purpose. +type BasicTag struct { + // FqIfdPath is the fully-qualified IFD-path. + FqIfdPath string + + // IfdPath is the unindexed IFD-path. + IfdPath string + + // TagId is the tag-ID. + TagId uint16 +} + func init() { for typeId, typeName := range TypeNames { typeNamesR[typeName] = typeId diff --git a/v2/exif-read-tool/main.go b/v2/exif-read-tool/main.go index 3fef894..c3a92ed 100644 --- a/v2/exif-read-tool/main.go +++ b/v2/exif-read-tool/main.go @@ -105,7 +105,7 @@ func main() { // Run the parse. - entries, err := exif.GetFlatExifData(rawExif) + entries, _, err := exif.GetExifData(rawExif, true) log.PanicIf(err) // Write the thumbnail is requested and present. diff --git a/v2/tags.go b/v2/tags.go index 416c315..422ff97 100644 --- a/v2/tags.go +++ b/v2/tags.go @@ -272,7 +272,7 @@ var ( // Things *can* end badly here, in that the same tag-ID in different IFDs might // describe different data and different ata-types, and our decode might then // produce binary and non-printable data. -func (ti *TagIndex) FindFirst(id uint16, ifdIdentities []*exifcommon.IfdIdentity) (it *IndexedTag, err error) { +func (ti *TagIndex) FindFirst(id uint16, typeId exifcommon.TagTypePrimitive, ifdIdentities []*exifcommon.IfdIdentity) (it *IndexedTag, err error) { defer func() { if state := recover(); state != nil { err = log.Wrap(state.(error)) @@ -293,7 +293,15 @@ func (ti *TagIndex) FindFirst(id uint16, ifdIdentities []*exifcommon.IfdIdentity log.Panic(err) } - return it, nil + // Even though the tag might be mislocated, the type should still be the + // same. Check this so we don't accidentally end-up on a complete + // irrelevant tag with a totally different data type. This attempts to + // mitigate producing garbage. + for _, supportedType := range it.SupportedTypes { + if supportedType == typeId { + return it, nil + } + } } return nil, ErrTagNotFound diff --git a/v2/tags_test.go b/v2/tags_test.go index 75c28c4..0f85f9c 100644 --- a/v2/tags_test.go +++ b/v2/tags_test.go @@ -272,7 +272,7 @@ func TestTagIndex_FindFirst_HitOnFirst(t *testing.T) { ti := NewTagIndex() // ExifVersion - it, err := ti.FindFirst(0x9000, searchOrder) + it, err := ti.FindFirst(0x9000, exifcommon.TypeUndefined, searchOrder) log.PanicIf(err) if it.Is("IFD/Exif", 0x9000) != true { @@ -290,7 +290,7 @@ func TestTagIndex_FindFirst_HitOnSecond(t *testing.T) { ti := NewTagIndex() // ProcessingSoftware - it, err := ti.FindFirst(0x000b, searchOrder) + it, err := ti.FindFirst(0x000b, exifcommon.TypeAscii, searchOrder) log.PanicIf(err) if it.Is("IFD", 0x000b) != true { @@ -307,7 +307,7 @@ func TestTagIndex_FindFirst_DefaultOrder_Miss(t *testing.T) { ti := NewTagIndex() - _, err := ti.FindFirst(0x1234, searchOrder) + _, err := ti.FindFirst(0x1234, exifcommon.TypeRational, searchOrder) if err == nil { t.Fatalf("Expected error for invalid tag.") } else if err != ErrTagNotFound { @@ -325,7 +325,7 @@ func TestTagIndex_FindFirst_ReverseDefaultOrder_HitOnSecond(t *testing.T) { ti := NewTagIndex() // ExifVersion - it, err := ti.FindFirst(0x9000, reverseSearchOrder) + it, err := ti.FindFirst(0x9000, exifcommon.TypeUndefined, reverseSearchOrder) log.PanicIf(err) if it.Is("IFD/Exif", 0x9000) != true { @@ -343,7 +343,7 @@ func TestTagIndex_FindFirst_ReverseDefaultOrder_HitOnFirst(t *testing.T) { ti := NewTagIndex() // ProcessingSoftware - it, err := ti.FindFirst(0x000b, reverseSearchOrder) + it, err := ti.FindFirst(0x000b, exifcommon.TypeAscii, reverseSearchOrder) log.PanicIf(err) if it.Is("IFD", 0x000b) != true { @@ -360,7 +360,7 @@ func TestTagIndex_FindFirst_ReverseDefaultOrder_Miss(t *testing.T) { ti := NewTagIndex() - _, err := ti.FindFirst(0x1234, reverseSearchOrder) + _, err := ti.FindFirst(0x1234, exifcommon.TypeRational, reverseSearchOrder) if err == nil { t.Fatalf("Expected error for invalid tag.") } else if err != ErrTagNotFound { diff --git a/v2/utility.go b/v2/utility.go index 5133861..66e8853 100644 --- a/v2/utility.go +++ b/v2/utility.go @@ -116,10 +116,20 @@ type ExifTag struct { // String returns a string representation. func (et ExifTag) String() string { - return fmt.Sprintf("ExifTag