Added tag lookup. Only a minimal number of tags are currently known.

pull/3/head
Dustin Oprea 2018-04-14 20:04:35 -04:00
parent 685d801489
commit 05fe72f929
5 changed files with 218 additions and 2 deletions

31
assets/tags.yaml Normal file
View File

@ -0,0 +1,31 @@
Image:
- id: 0x103
name: Compression
- id: 0x10f
name: Make
- id: 0x110
name: Model
- id: 0x112
name: Orientation
- id: 0x11a
name: XResolution
- id: 0x11b
name: YResolution
- id: 0x128
name: ResolutionUnit
- id: 0x132
name: DateTime
- id: 0x13b
name: Artist
- id: 0x201
name: JPEGInterchangeFormat
- id: 0x202
name: JPEGInterchangeFormatLength
- id: 0x213
name: YCbCrPositioning
- id: 0x8298
name: Copyright
- id: 0x8769
name: ExifTag
- id: 0x8825
name: GPSTag

View File

@ -74,4 +74,3 @@ func init() {
assetsPath = path.Join(goPath, "src", "github.com", "dsoprea", "go-exif", "assets")
}

13
ifd.go
View File

@ -117,12 +117,23 @@ func (ifd *Ifd) parseCurrentIfd() (nextIfdOffset uint32, err error) {
fmt.Printf("IFD: TOTAL TAG COUNT=(%02x)\n", tagCount)
t := NewTagIndex()
for i := uint16(0); i < tagCount; i++ {
// TODO(dustin): !! 0x8769 tag-IDs are child IFDs.
tagId, err := ifd.getUint16()
log.PanicIf(err)
fmt.Printf("IFD: Tag (%d) ID=(%02x)\n", i, tagId)
it, err := t.GetWithTagId(tagId)
if err != nil {
if err == ErrTagNotFound {
log.Panicf("tag (%04x) not known")
} else {
log.Panic(err)
}
}
fmt.Printf("IFD: Tag (%d) ID=(%02x) NAME=[%s] IFD=[%s]\n", i, tagId, it.Name, it.Ifd)
tagType, err := ifd.getUint16()

157
tags.go Normal file
View File

@ -0,0 +1,157 @@
package exif
import (
"os"
"path"
"fmt"
"errors"
"io/ioutil"
"gopkg.in/yaml.v2"
"github.com/dsoprea/go-logging"
)
var (
tagDataFilepath = ""
)
var (
tagsLogger = log.NewLogger("exif.tags")
ErrTagNotFound = errors.New("tag not found")
)
// File structures.
type encodedTag struct {
// id is signed, here, because YAML doesn't have enough information to
// support unsigned.
Id int `yaml:"id"`
Name string `yaml:"name"`
}
// Indexing structures.
type IndexedTag struct {
Id uint16
Name string
Ifd string
}
func (it IndexedTag) String() string {
return fmt.Sprintf("TAG<ID=(0x%04x) NAME=[%s] IFD=[%s]>", it.Id, it.Name, it.Ifd)
}
func (it IndexedTag) IsName(ifd, name string) bool {
return it.Name == name && it.Ifd == ifd
}
func (it IndexedTag) Is(id uint16) bool {
return it.Id == id
}
type TagIndex struct {
tagsByIfd map[string]map[uint16]*IndexedTag
tagsById map[uint16]*IndexedTag
}
func NewTagIndex() *TagIndex {
ti := new(TagIndex)
err := ti.load()
log.PanicIf(err)
return ti
}
func (ti *TagIndex) load() (err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()
// Read static data.
f, err := os.Open(tagDataFilepath)
log.PanicIf(err)
data, err := ioutil.ReadAll(f)
log.PanicIf(err)
encodedIfds := make(map[string][]encodedTag)
err = yaml.Unmarshal(data, &encodedIfds)
log.PanicIf(err)
// Load structure.
tagsById := make(map[uint16]*IndexedTag)
tagsByIfd := make(map[string]map[uint16]*IndexedTag)
count := 0
for ifdName, tags := range encodedIfds {
for _, tagInfo := range tags {
tagId := uint16(tagInfo.Id)
tagName := tagInfo.Name
tag := &IndexedTag{
Ifd: ifdName,
Id: tagId,
Name: tagName,
}
if _, found := tagsById[tagId]; found == true {
log.Panicf("tag-ID defined more than once: (%02x)", tagId)
}
tagsById[tagId] = tag
family, found := tagsByIfd[ifdName]
if found == false {
family = make(map[uint16]*IndexedTag)
tagsByIfd[ifdName] = family
}
family[tagId] = tag
count++
}
}
ti.tagsById = tagsById
ti.tagsByIfd = tagsByIfd
tagsLogger.Debugf(nil, "(%d) tags loaded.", count)
return nil
}
func (ti *TagIndex) GetWithTagId(id uint16) (it *IndexedTag, err error) {
defer func() {
if state := recover(); state != nil {
err = log.Wrap(state.(error))
}
}()
it, found := ti.tagsById[id]
if found == false {
return nil, ErrTagNotFound
}
return it, nil
}
func init() {
goPath := os.Getenv("GOPATH")
if goPath == "" {
log.Panicf("GOPATH is empty")
}
assetsPath := path.Join(goPath, "src", "github.com", "dsoprea", "go-exif", "assets")
tagDataFilepath = path.Join(assetsPath, "tags.yaml")
}

18
tags_test.go Normal file
View File

@ -0,0 +1,18 @@
package exif
import (
"testing"
"github.com/dsoprea/go-logging"
)
func TestGetWithTagId(t *testing.T) {
ti := NewTagIndex()
it, err := ti.GetWithTagId(0x10f)
log.PanicIf(err)
if it.Is(0x10f) == false || it.IsName("Image", "Make") == false {
t.Fatalf("tag info not correct")
}
}