mirror of https://github.com/dsoprea/go-exif.git
ifd_enumerate: Refactored for reusability from a collector loop.
parent
33e3f2e4eb
commit
acbda6d1e1
|
@ -126,7 +126,7 @@ visitor := func(indexedIfdName string, tagId uint16, tagType exif.TagType, value
|
|||
return nil
|
||||
}
|
||||
|
||||
err = e.Parse(data[foundAt:], visitor)
|
||||
err = e.Visit(data[foundAt:], visitor)
|
||||
log.PanicIf(err)
|
||||
```
|
||||
|
||||
|
|
|
@ -93,6 +93,6 @@ func main() {
|
|||
return nil
|
||||
}
|
||||
|
||||
err = e.Parse(data[foundAt:], visitor)
|
||||
err = e.Visit(data[foundAt:], visitor)
|
||||
log.PanicIf(err)
|
||||
}
|
||||
|
|
38
exif.go
38
exif.go
|
@ -11,7 +11,11 @@ import (
|
|||
|
||||
var (
|
||||
exifLogger = log.NewLogger("exif.exif")
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotExif = errors.New("not exif data")
|
||||
ErrExifHeaderError = errors.New("exif header error")
|
||||
)
|
||||
|
||||
type Exif struct {
|
||||
|
@ -30,7 +34,13 @@ func (e *Exif) IsExif(data []byte) (ok bool) {
|
|||
return false
|
||||
}
|
||||
|
||||
func (e *Exif) Parse(data []byte, visitor TagVisitor) (err error) {
|
||||
|
||||
type ExifHeader struct {
|
||||
ByteOrder binary.ByteOrder
|
||||
FirstIfdOffset uint32
|
||||
}
|
||||
|
||||
func (e *Exif) ParseExifHeader(data []byte) (eh ExifHeader, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
|
@ -57,8 +67,8 @@ func (e *Exif) Parse(data []byte, visitor TagVisitor) (err error) {
|
|||
|
||||
fixedBytes := data[8:10]
|
||||
if fixedBytes[0] != 0x2a || fixedBytes[1] != 0x00 {
|
||||
exifLogger.Warningf(nil, "EXIF app-data header fixed-bytes should be 0x002a but are: [%v]", fixedBytes)
|
||||
return nil
|
||||
exifLogger.Warningf(nil, "EXIF header fixed-bytes should be 0x002a but are: [%v]", fixedBytes)
|
||||
log.Panic(ErrExifHeaderError)
|
||||
}
|
||||
|
||||
firstIfdOffset := uint32(0)
|
||||
|
@ -68,9 +78,27 @@ func (e *Exif) Parse(data []byte, visitor TagVisitor) (err error) {
|
|||
firstIfdOffset = binary.LittleEndian.Uint32(data[10:14])
|
||||
}
|
||||
|
||||
ie := NewIfdEnumerate(data, byteOrder)
|
||||
eh = ExifHeader{
|
||||
ByteOrder: byteOrder,
|
||||
FirstIfdOffset: firstIfdOffset,
|
||||
}
|
||||
|
||||
err = ie.Scan(IfdStandard, firstIfdOffset, visitor)
|
||||
return eh, nil
|
||||
}
|
||||
|
||||
func (e *Exif) Visit(data []byte, visitor TagVisitor) (err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
}
|
||||
}()
|
||||
|
||||
eh, err := e.ParseExifHeader(data)
|
||||
log.PanicIf(err)
|
||||
|
||||
ie := NewIfdEnumerate(data, eh.ByteOrder)
|
||||
|
||||
err = ie.Scan(IfdStandard, eh.FirstIfdOffset, visitor)
|
||||
log.PanicIf(err)
|
||||
|
||||
return nil
|
||||
|
|
|
@ -33,7 +33,7 @@ func TestIsExif_False(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
func TestVisit(t *testing.T) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err := log.Wrap(state.(error))
|
||||
|
@ -113,7 +113,7 @@ func TestParse(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
|
||||
err = e.Parse(data[foundAt:], visitor)
|
||||
err = e.Visit(data[foundAt:], visitor)
|
||||
log.PanicIf(err)
|
||||
|
||||
// for _, line := range tags {
|
||||
|
|
|
@ -124,9 +124,21 @@ func (ie *IfdEnumerate) getTagEnumerator(ifdOffset uint32) (ite *IfdTagEnumerato
|
|||
// the offsets of all IFDs and values are calculated from).
|
||||
type TagVisitor func(indexedIfdName string, tagId uint16, tagType TagType, valueContext ValueContext) (err error)
|
||||
|
||||
// parseIfd decodes the IFD block that we're currently sitting on the first
|
||||
|
||||
type IfdTagEntry struct {
|
||||
TagId uint16
|
||||
TagIndex int
|
||||
TagType uint16
|
||||
UnitCount uint32
|
||||
ValueOffset uint32
|
||||
RawValueOffset []byte
|
||||
IsIfd bool
|
||||
}
|
||||
|
||||
|
||||
// ParseIfd decodes the IFD block that we're currently sitting on the first
|
||||
// byte of.
|
||||
func (ie *IfdEnumerate) parseIfd(ifdName string, ifdIndex int, ifdOffset uint32, visitor TagVisitor) (nextIfdOffset uint32, err error) {
|
||||
func (ie *IfdEnumerate) ParseIfd(ifdName string, ifdIndex int, ifdOffset uint32, visitor TagVisitor, doDescend bool) (nextIfdOffset uint32, entries []IfdTagEntry, err error) {
|
||||
defer func() {
|
||||
if state := recover(); state != nil {
|
||||
err = log.Wrap(state.(error))
|
||||
|
@ -155,6 +167,8 @@ func (ie *IfdEnumerate) parseIfd(ifdName string, ifdIndex int, ifdOffset uint32,
|
|||
|
||||
ifdLogger.Debugf(nil, "Current IFD tag-count: (%d)", tagCount)
|
||||
|
||||
entries = make([]IfdTagEntry, tagCount)
|
||||
|
||||
for i := uint16(0); i < tagCount; i++ {
|
||||
tagId, _, err := ite.getUint16()
|
||||
log.PanicIf(err)
|
||||
|
@ -182,13 +196,28 @@ func (ie *IfdEnumerate) parseIfd(ifdName string, ifdIndex int, ifdOffset uint32,
|
|||
log.PanicIf(err)
|
||||
}
|
||||
|
||||
tag := IfdTagEntry{
|
||||
TagId: tagId,
|
||||
TagIndex: int(i),
|
||||
TagType: tagType,
|
||||
UnitCount: unitCount,
|
||||
ValueOffset: valueOffset,
|
||||
RawValueOffset: rawValueOffset,
|
||||
}
|
||||
|
||||
childIfdName, isIfd := IsIfdTag(tagId)
|
||||
if isIfd == true {
|
||||
ifdLogger.Debugf(nil, "Descending to IFD [%s].", childIfdName)
|
||||
tag.IsIfd = true
|
||||
|
||||
err := ie.Scan(childIfdName, valueOffset, visitor)
|
||||
log.PanicIf(err)
|
||||
if doDescend == true {
|
||||
ifdLogger.Debugf(nil, "Descending to IFD [%s].", childIfdName)
|
||||
|
||||
err := ie.Scan(childIfdName, valueOffset, visitor)
|
||||
log.PanicIf(err)
|
||||
}
|
||||
}
|
||||
|
||||
entries[i] = tag
|
||||
}
|
||||
|
||||
nextIfdOffset, _, err = ite.getUint32()
|
||||
|
@ -196,7 +225,7 @@ func (ie *IfdEnumerate) parseIfd(ifdName string, ifdIndex int, ifdOffset uint32,
|
|||
|
||||
ifdLogger.Debugf(nil, "Next IFD at offset: (%08x)", nextIfdOffset)
|
||||
|
||||
return nextIfdOffset, nil
|
||||
return nextIfdOffset, entries, nil
|
||||
}
|
||||
|
||||
// Scan enumerates the different EXIF blocks (called IFDs).
|
||||
|
@ -208,7 +237,7 @@ func (ie *IfdEnumerate) Scan(ifdName string, ifdOffset uint32, visitor TagVisito
|
|||
}()
|
||||
|
||||
for ifdIndex := 0;; ifdIndex++ {
|
||||
nextIfdOffset, err := ie.parseIfd(ifdName, ifdIndex, ifdOffset, visitor)
|
||||
nextIfdOffset, _, err := ie.ParseIfd(ifdName, ifdIndex, ifdOffset, visitor, true)
|
||||
log.PanicIf(err)
|
||||
|
||||
if nextIfdOffset == 0 {
|
||||
|
|
Loading…
Reference in New Issue