mirror of https://github.com/dsoprea/go-exif.git
TagIndex: Refactored to prepare for custom tags.
- More specifically, to prepare the way to register non-standard IFDs and tags.pull/3/head
parent
2349792faa
commit
d8cdf29fa6
140
tags.go
140
tags.go
|
@ -83,94 +83,47 @@ type TagIndex struct {
|
||||||
|
|
||||||
func NewTagIndex() *TagIndex {
|
func NewTagIndex() *TagIndex {
|
||||||
ti := new(TagIndex)
|
ti := new(TagIndex)
|
||||||
|
|
||||||
|
ti.tagsByIfd = make(map[string]map[uint16]*IndexedTag)
|
||||||
|
ti.tagsByIfdR = make(map[string]map[string]*IndexedTag)
|
||||||
|
|
||||||
return ti
|
return ti
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ti *TagIndex) load() (err error) {
|
func (ti *TagIndex) Add(it *IndexedTag) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if state := recover(); state != nil {
|
if state := recover(); state != nil {
|
||||||
err = log.Wrap(state.(error))
|
err = log.Wrap(state.(error))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Already loaded.
|
|
||||||
if ti.tagsByIfd != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read static data.
|
|
||||||
|
|
||||||
encodedIfds := make(map[string][]encodedTag)
|
|
||||||
|
|
||||||
err = yaml.Unmarshal([]byte(tagsYaml), encodedIfds)
|
|
||||||
log.PanicIf(err)
|
|
||||||
|
|
||||||
// Load structure.
|
|
||||||
|
|
||||||
tagsByIfd := make(map[string]map[uint16]*IndexedTag)
|
|
||||||
tagsByIfdR := make(map[string]map[string]*IndexedTag)
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
for ifdName, tags := range encodedIfds {
|
|
||||||
for _, tagInfo := range tags {
|
|
||||||
tagId := uint16(tagInfo.Id)
|
|
||||||
tagName := tagInfo.Name
|
|
||||||
tagTypeName := tagInfo.TypeName
|
|
||||||
|
|
||||||
// TODO(dustin): !! Non-standard types, but found in real data. Ignore for right now.
|
|
||||||
if tagTypeName == "SSHORT" || tagTypeName == "FLOAT" || tagTypeName == "DOUBLE" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
tagTypeId, found := TypeNamesR[tagTypeName]
|
|
||||||
if found == false {
|
|
||||||
log.Panicf("type [%s] for [%s] not valid", tagTypeName, tagName)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
tag := &IndexedTag{
|
|
||||||
Ifd: ifdName,
|
|
||||||
Id: tagId,
|
|
||||||
Name: tagName,
|
|
||||||
Type: tagTypeId,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store by ID.
|
// Store by ID.
|
||||||
|
|
||||||
family, found := tagsByIfd[ifdName]
|
family, found := ti.tagsByIfd[it.Ifd]
|
||||||
if found == false {
|
if found == false {
|
||||||
family = make(map[uint16]*IndexedTag)
|
family = make(map[uint16]*IndexedTag)
|
||||||
tagsByIfd[ifdName] = family
|
ti.tagsByIfd[it.Ifd] = family
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, found := family[tagId]; found == true {
|
if _, found := family[it.Id]; found == true {
|
||||||
log.Panicf("tag-ID defined more than once for IFD [%s]: (%02x)", ifdName, tagId)
|
log.Panicf("tag-ID defined more than once for IFD [%s]: (%02x)", it.Ifd, it.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
family[tagId] = tag
|
family[it.Id] = it
|
||||||
|
|
||||||
// Store by name.
|
// Store by name.
|
||||||
|
|
||||||
familyR, found := tagsByIfdR[ifdName]
|
familyR, found := ti.tagsByIfdR[it.Ifd]
|
||||||
if found == false {
|
if found == false {
|
||||||
familyR = make(map[string]*IndexedTag)
|
familyR = make(map[string]*IndexedTag)
|
||||||
tagsByIfdR[ifdName] = familyR
|
ti.tagsByIfdR[it.Ifd] = familyR
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, found := familyR[tagName]; found == true {
|
if _, found := familyR[it.Name]; found == true {
|
||||||
log.Panicf("tag-name defined more than once for IFD [%s]: (%s)", ifdName, tagName)
|
log.Panicf("tag-name defined more than once for IFD [%s]: (%s)", it.Ifd, it.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
familyR[tagName] = tag
|
familyR[it.Name] = it
|
||||||
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ti.tagsByIfd = tagsByIfd
|
|
||||||
ti.tagsByIfdR = tagsByIfdR
|
|
||||||
|
|
||||||
tagsLogger.Debugf(nil, "(%d) tags loaded.", count)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -183,8 +136,10 @@ func (ti *TagIndex) Get(ii IfdIdentity, id uint16) (it *IndexedTag, err error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = ti.load()
|
if len(ti.tagsByIfd) == 0 {
|
||||||
|
err := LoadStandardTags(ti)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
}
|
||||||
|
|
||||||
family, found := ti.tagsByIfd[ii.IfdName]
|
family, found := ti.tagsByIfd[ii.IfdName]
|
||||||
if found == false {
|
if found == false {
|
||||||
|
@ -207,8 +162,10 @@ func (ti *TagIndex) GetWithName(ii IfdIdentity, name string) (it *IndexedTag, er
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = ti.load()
|
if len(ti.tagsByIfdR) == 0 {
|
||||||
|
err := LoadStandardTags(ti)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
}
|
||||||
|
|
||||||
it, found := ti.tagsByIfdR[ii.IfdName][name]
|
it, found := ti.tagsByIfdR[ii.IfdName][name]
|
||||||
if found != true {
|
if found != true {
|
||||||
|
@ -218,6 +175,61 @@ func (ti *TagIndex) GetWithName(ii IfdIdentity, name string) (it *IndexedTag, er
|
||||||
return it, nil
|
return it, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadStandardTags registers the tags that all devices/applications should
|
||||||
|
// support.
|
||||||
|
func LoadStandardTags(ti *TagIndex) (err error) {
|
||||||
|
defer func() {
|
||||||
|
if state := recover(); state != nil {
|
||||||
|
err = log.Wrap(state.(error))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Read static data.
|
||||||
|
|
||||||
|
encodedIfds := make(map[string][]encodedTag)
|
||||||
|
|
||||||
|
err = yaml.Unmarshal([]byte(tagsYaml), encodedIfds)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
// Load structure.
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
for ifdName, tags := range encodedIfds {
|
||||||
|
for _, tagInfo := range tags {
|
||||||
|
tagId := uint16(tagInfo.Id)
|
||||||
|
tagName := tagInfo.Name
|
||||||
|
tagTypeName := tagInfo.TypeName
|
||||||
|
|
||||||
|
// TODO(dustin): !! Non-standard types, but found in real data. Ignore for right now.
|
||||||
|
if tagTypeName == "SSHORT" || tagTypeName == "FLOAT" || tagTypeName == "DOUBLE" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tagTypeId, found := TypeNamesR[tagTypeName]
|
||||||
|
if found == false {
|
||||||
|
log.Panicf("type [%s] for [%s] not valid", tagTypeName, tagName)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
it := &IndexedTag{
|
||||||
|
Ifd: ifdName,
|
||||||
|
Id: tagId,
|
||||||
|
Name: tagName,
|
||||||
|
Type: tagTypeId,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ti.Add(it)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tagsLogger.Debugf(nil, "(%d) tags loaded.", count)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// IfdTagWithId returns true if the given tag points to a child IFD block.
|
// IfdTagWithId returns true if the given tag points to a child IFD block.
|
||||||
func IfdTagNameWithIdOrFail(parentIfdName string, tagId uint16) string {
|
func IfdTagNameWithIdOrFail(parentIfdName string, tagId uint16) string {
|
||||||
name, found := IfdTagNameWithId(parentIfdName, tagId)
|
name, found := IfdTagNameWithId(parentIfdName, tagId)
|
||||||
|
|
Loading…
Reference in New Issue