mirror of https://github.com/dsoprea/go-exif.git
Added tag lookup. Only a minimal number of tags are currently known.
parent
685d801489
commit
05fe72f929
|
@ -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
|
|
@ -74,4 +74,3 @@ func init() {
|
|||
|
||||
assetsPath = path.Join(goPath, "src", "github.com", "dsoprea", "go-exif", "assets")
|
||||
}
|
||||
|
||||
|
|
13
ifd.go
13
ifd.go
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue