mirror of
https://github.com/dsoprea/go-exif.git
synced 2025-05-31 11:41:57 +00:00
We now have to pass a specific tag-index in from the top.
- This will allow us to handle custom tags and, with a little more work, custom IFDs.
This commit is contained in:
parent
d8cdf29fa6
commit
d3b45fae77
@ -14,15 +14,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"fmt"
|
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"io/ioutil"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
|
||||||
"github.com/dsoprea/go-exif"
|
"github.com/dsoprea/go-exif"
|
||||||
|
"github.com/dsoprea/go-logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -30,7 +30,6 @@ var (
|
|||||||
printAsJsonArg = false
|
printAsJsonArg = false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type IfdEntry struct {
|
type IfdEntry struct {
|
||||||
IfdName string `json:"ifd_name"`
|
IfdName string `json:"ifd_name"`
|
||||||
ParentIfdName string `json:"parent_ifd_name"`
|
ParentIfdName string `json:"parent_ifd_name"`
|
||||||
@ -131,7 +130,7 @@ func main() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = exif.Visit(rawExif, visitor)
|
_, err = exif.Visit(ti, rawExif, visitor)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if printAsJsonArg == true {
|
if printAsJsonArg == true {
|
||||||
|
8
exif.go
8
exif.go
@ -168,7 +168,7 @@ func ParseExifHeader(data []byte) (eh ExifHeader, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Visit recursively invokes a callback for every tag.
|
// Visit recursively invokes a callback for every tag.
|
||||||
func Visit(exifData []byte, visitor RawTagVisitor) (eh ExifHeader, err error) {
|
func Visit(tagIndex *TagIndex, exifData []byte, visitor RawTagVisitor) (eh ExifHeader, 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))
|
||||||
@ -178,7 +178,7 @@ func Visit(exifData []byte, visitor RawTagVisitor) (eh ExifHeader, err error) {
|
|||||||
eh, err = ParseExifHeader(exifData)
|
eh, err = ParseExifHeader(exifData)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ie := NewIfdEnumerate(exifData, eh.ByteOrder)
|
ie := NewIfdEnumerate(tagIndex, exifData, eh.ByteOrder)
|
||||||
|
|
||||||
err = ie.Scan(eh.FirstIfdOffset, visitor, true)
|
err = ie.Scan(eh.FirstIfdOffset, visitor, true)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -187,7 +187,7 @@ func Visit(exifData []byte, visitor RawTagVisitor) (eh ExifHeader, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Collect recursively builds a static structure of all IFDs and tags.
|
// Collect recursively builds a static structure of all IFDs and tags.
|
||||||
func Collect(exifData []byte) (eh ExifHeader, index IfdIndex, err error) {
|
func Collect(tagIndex *TagIndex, exifData []byte) (eh ExifHeader, index IfdIndex, 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))
|
||||||
@ -197,7 +197,7 @@ func Collect(exifData []byte) (eh ExifHeader, index IfdIndex, err error) {
|
|||||||
eh, err = ParseExifHeader(exifData)
|
eh, err = ParseExifHeader(exifData)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ie := NewIfdEnumerate(exifData, eh.ByteOrder)
|
ie := NewIfdEnumerate(tagIndex, exifData, eh.ByteOrder)
|
||||||
|
|
||||||
index, err = ie.Collect(eh.FirstIfdOffset, true)
|
index, err = ie.Collect(eh.FirstIfdOffset, true)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
22
exif_test.go
22
exif_test.go
@ -1,20 +1,19 @@
|
|||||||
package exif
|
package exif
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"bytes"
|
"testing"
|
||||||
|
|
||||||
"io/ioutil"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func TestVisit(t *testing.T) {
|
func TestVisit(t *testing.T) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if state := recover(); state != nil {
|
if state := recover(); state != nil {
|
||||||
@ -23,6 +22,8 @@ func TestVisit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
ti := NewTagIndex()
|
||||||
|
|
||||||
// Open the file.
|
// Open the file.
|
||||||
|
|
||||||
filepath := path.Join(assetsPath, "NDM_8901.jpg")
|
filepath := path.Join(assetsPath, "NDM_8901.jpg")
|
||||||
@ -63,7 +64,7 @@ func TestVisit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
it, err := tagIndex.Get(ii, tagId)
|
it, err := ti.Get(ii, tagId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if log.Is(err, ErrTagNotFound) {
|
if log.Is(err, ErrTagNotFound) {
|
||||||
fmt.Printf("Unknown tag: [%v] (%04x)\n", ii, tagId)
|
fmt.Printf("Unknown tag: [%v] (%04x)\n", ii, tagId)
|
||||||
@ -94,14 +95,14 @@ func TestVisit(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = Visit(data[foundAt:], visitor)
|
_, err = Visit(ti, data[foundAt:], visitor)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// for _, line := range tags {
|
// for _, line := range tags {
|
||||||
// fmt.Printf("TAGS: %s\n", line)
|
// fmt.Printf("TAGS: %s\n", line)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
expected := []string {
|
expected := []string{
|
||||||
"IFD=[IFD] ID=(0x010f) NAME=[Make] COUNT=(6) TYPE=[ASCII] VALUE=[Canon]",
|
"IFD=[IFD] ID=(0x010f) NAME=[Make] COUNT=(6) TYPE=[ASCII] VALUE=[Canon]",
|
||||||
"IFD=[IFD] ID=(0x0110) NAME=[Model] COUNT=(22) TYPE=[ASCII] VALUE=[Canon EOS 5D Mark III]",
|
"IFD=[IFD] ID=(0x0110) NAME=[Model] COUNT=(22) TYPE=[ASCII] VALUE=[Canon EOS 5D Mark III]",
|
||||||
"IFD=[IFD] ID=(0x0112) NAME=[Orientation] COUNT=(1) TYPE=[SHORT] VALUE=[1]",
|
"IFD=[IFD] ID=(0x0112) NAME=[Orientation] COUNT=(1) TYPE=[SHORT] VALUE=[1]",
|
||||||
@ -203,7 +204,6 @@ func TestSearchAndExtractExif(t *testing.T) {
|
|||||||
imageData, err := ioutil.ReadFile(filepath)
|
imageData, err := ioutil.ReadFile(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
rawExif, err := SearchAndExtractExif(imageData)
|
rawExif, err := SearchAndExtractExif(imageData)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
@ -225,7 +225,9 @@ func TestCollect(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
rootIfd := index.RootIfd
|
rootIfd := index.RootIfd
|
||||||
|
104
ifd_builder.go
104
ifd_builder.go
@ -154,48 +154,12 @@ func (bt *BuilderTag) SetValue(byteOrder binary.ByteOrder, value interface{}) (e
|
|||||||
|
|
||||||
// NewStandardBuilderTag constructs a `BuilderTag` instance. The type is looked
|
// NewStandardBuilderTag constructs a `BuilderTag` instance. The type is looked
|
||||||
// up. `ii` is the type of IFD that owns this tag.
|
// up. `ii` is the type of IFD that owns this tag.
|
||||||
func NewStandardBuilderTag(ii IfdIdentity, tagId uint16, byteOrder binary.ByteOrder, value interface{}) *BuilderTag {
|
func NewStandardBuilderTag(ii IfdIdentity, it *IndexedTag, byteOrder binary.ByteOrder, value interface{}) *BuilderTag {
|
||||||
it, err := tagIndex.Get(ii, tagId)
|
|
||||||
log.PanicIf(err)
|
|
||||||
|
|
||||||
typeId := it.Type
|
typeId := it.Type
|
||||||
tt := NewTagType(typeId, byteOrder)
|
tt := NewTagType(typeId, byteOrder)
|
||||||
|
|
||||||
ve := NewValueEncoder(byteOrder)
|
ve := NewValueEncoder(byteOrder)
|
||||||
|
|
||||||
var ed EncodedData
|
|
||||||
if it.Type == TypeUndefined {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
ed, err = EncodeUndefined(ii, tagId, value)
|
|
||||||
log.PanicIf(err)
|
|
||||||
} else {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
ed, err = ve.EncodeWithType(tt, value)
|
|
||||||
log.PanicIf(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tagValue := NewIfdBuilderTagValueFromBytes(ed.Encoded)
|
|
||||||
|
|
||||||
return NewBuilderTag(
|
|
||||||
ii,
|
|
||||||
tagId,
|
|
||||||
typeId,
|
|
||||||
tagValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewStandardBuilderTagWithName allows us to easily generate solid, consistent
|
|
||||||
// tags for testing with. `ii` is the type of IFD that owns this tag. This can
|
|
||||||
// not be an IFD (IFDs are not associated with standardized, official names).
|
|
||||||
func NewStandardBuilderTagWithName(ii IfdIdentity, tagName string, byteOrder binary.ByteOrder, value interface{}) *BuilderTag {
|
|
||||||
it, err := tagIndex.GetWithName(ii, tagName)
|
|
||||||
log.PanicIf(err)
|
|
||||||
|
|
||||||
tt := NewTagType(it.Type, byteOrder)
|
|
||||||
|
|
||||||
ve := NewValueEncoder(byteOrder)
|
|
||||||
|
|
||||||
var ed EncodedData
|
var ed EncodedData
|
||||||
if it.Type == TypeUndefined {
|
if it.Type == TypeUndefined {
|
||||||
var err error
|
var err error
|
||||||
@ -214,7 +178,7 @@ func NewStandardBuilderTagWithName(ii IfdIdentity, tagName string, byteOrder bin
|
|||||||
return NewBuilderTag(
|
return NewBuilderTag(
|
||||||
ii,
|
ii,
|
||||||
it.Id,
|
it.Id,
|
||||||
it.Type,
|
typeId,
|
||||||
tagValue)
|
tagValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,8 +192,8 @@ type IfdBuilder struct {
|
|||||||
byteOrder binary.ByteOrder
|
byteOrder binary.ByteOrder
|
||||||
|
|
||||||
// Includes both normal tags and IFD tags (which point to child IFDs).
|
// Includes both normal tags and IFD tags (which point to child IFDs).
|
||||||
// TODO(dustin): Keep a separate list of children like with IFd.
|
// TODO(dustin): Keep a separate list of children like with IFd.
|
||||||
// TODO(dustin): Either rename this or `Entries` in Ifd to be the same thing.
|
// TODO(dustin): Either rename this or `Entries` in Ifd to be the same thing.
|
||||||
tags []*BuilderTag
|
tags []*BuilderTag
|
||||||
|
|
||||||
// existingOffset will be the offset that this IFD is currently found at if
|
// existingOffset will be the offset that this IFD is currently found at if
|
||||||
@ -242,9 +206,11 @@ type IfdBuilder struct {
|
|||||||
// thumbnailData is populated with thumbnail data if there was thumbnail
|
// thumbnailData is populated with thumbnail data if there was thumbnail
|
||||||
// data. Otherwise, it's nil.
|
// data. Otherwise, it's nil.
|
||||||
thumbnailData []byte
|
thumbnailData []byte
|
||||||
|
|
||||||
|
tagIndex *TagIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIfdBuilder(ii IfdIdentity, byteOrder binary.ByteOrder) (ib *IfdBuilder) {
|
func NewIfdBuilder(tagIndex *TagIndex, ii IfdIdentity, byteOrder binary.ByteOrder) (ib *IfdBuilder) {
|
||||||
ifdTagId, _ := IfdTagIdWithIdentity(ii)
|
ifdTagId, _ := IfdTagIdWithIdentity(ii)
|
||||||
|
|
||||||
ib = &IfdBuilder{
|
ib = &IfdBuilder{
|
||||||
@ -256,6 +222,8 @@ func NewIfdBuilder(ii IfdIdentity, byteOrder binary.ByteOrder) (ib *IfdBuilder)
|
|||||||
|
|
||||||
byteOrder: byteOrder,
|
byteOrder: byteOrder,
|
||||||
tags: make([]*BuilderTag, 0),
|
tags: make([]*BuilderTag, 0),
|
||||||
|
|
||||||
|
tagIndex: tagIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
return ib
|
return ib
|
||||||
@ -278,6 +246,7 @@ func NewIfdBuilderWithExistingIfd(ifd *Ifd) (ib *IfdBuilder) {
|
|||||||
ifdTagId: ifdTagId,
|
ifdTagId: ifdTagId,
|
||||||
byteOrder: ifd.ByteOrder,
|
byteOrder: ifd.ByteOrder,
|
||||||
existingOffset: ifd.Offset,
|
existingOffset: ifd.Offset,
|
||||||
|
tagIndex: ifd.tagIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
return ib
|
return ib
|
||||||
@ -293,7 +262,7 @@ func NewIfdBuilderFromExistingChain(rootIfd *Ifd, itevr *IfdTagEntryValueResolve
|
|||||||
for thisExistingIfd := rootIfd; thisExistingIfd != nil; thisExistingIfd = thisExistingIfd.NextIfd {
|
for thisExistingIfd := rootIfd; thisExistingIfd != nil; thisExistingIfd = thisExistingIfd.NextIfd {
|
||||||
ii := thisExistingIfd.Identity()
|
ii := thisExistingIfd.Identity()
|
||||||
|
|
||||||
newIb := NewIfdBuilder(ii, thisExistingIfd.ByteOrder)
|
newIb := NewIfdBuilder(rootIfd.tagIndex, ii, thisExistingIfd.ByteOrder)
|
||||||
if firstIb == nil {
|
if firstIb == nil {
|
||||||
firstIb = newIb
|
firstIb = newIb
|
||||||
} else {
|
} else {
|
||||||
@ -340,7 +309,7 @@ func GetOrCreateIbFromRootIb(rootIb *IfdBuilder, ifdDesignation string) (ib *Ifd
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// TODO(dustin): !! Add test.
|
// TODO(dustin): !! Add test.
|
||||||
|
|
||||||
ib = rootIb
|
ib = rootIb
|
||||||
|
|
||||||
@ -350,7 +319,7 @@ func GetOrCreateIbFromRootIb(rootIb *IfdBuilder, ifdDesignation string) (ib *Ifd
|
|||||||
|
|
||||||
case "ifd1":
|
case "ifd1":
|
||||||
if ib.nextIb == nil {
|
if ib.nextIb == nil {
|
||||||
ib.nextIb = NewIfdBuilder(RootIi, ib.byteOrder)
|
ib.nextIb = NewIfdBuilder(ib.tagIndex, RootIi, ib.byteOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ib.nextIb, nil
|
return ib.nextIb, nil
|
||||||
@ -359,7 +328,7 @@ func GetOrCreateIbFromRootIb(rootIb *IfdBuilder, ifdDesignation string) (ib *Ifd
|
|||||||
exifIb, err := ib.ChildWithIfdIdentity(ExifIi)
|
exifIb, err := ib.ChildWithIfdIdentity(ExifIi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if log.Is(err, ErrChildIbNotFound) == true {
|
if log.Is(err, ErrChildIbNotFound) == true {
|
||||||
exifIb = NewIfdBuilder(ExifIi, ib.byteOrder)
|
exifIb = NewIfdBuilder(exifIb.tagIndex, ExifIi, ib.byteOrder)
|
||||||
|
|
||||||
err := ib.AddChildIb(exifIb)
|
err := ib.AddChildIb(exifIb)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -374,7 +343,7 @@ func GetOrCreateIbFromRootIb(rootIb *IfdBuilder, ifdDesignation string) (ib *Ifd
|
|||||||
exifIb, err := ib.ChildWithIfdIdentity(ExifIi)
|
exifIb, err := ib.ChildWithIfdIdentity(ExifIi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if log.Is(err, ErrChildIbNotFound) == true {
|
if log.Is(err, ErrChildIbNotFound) == true {
|
||||||
exifIb = NewIfdBuilder(ExifIi, ib.byteOrder)
|
exifIb = NewIfdBuilder(exifIb.tagIndex, ExifIi, ib.byteOrder)
|
||||||
|
|
||||||
err := ib.AddChildIb(exifIb)
|
err := ib.AddChildIb(exifIb)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -391,7 +360,7 @@ func GetOrCreateIbFromRootIb(rootIb *IfdBuilder, ifdDesignation string) (ib *Ifd
|
|||||||
iopIb, err := exifIb.ChildWithIfdIdentity(ExifIopIi)
|
iopIb, err := exifIb.ChildWithIfdIdentity(ExifIopIi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if log.Is(err, ErrChildIbNotFound) == true {
|
if log.Is(err, ErrChildIbNotFound) == true {
|
||||||
iopIb = NewIfdBuilder(ExifIopIi, ib.byteOrder)
|
iopIb = NewIfdBuilder(iopIb.tagIndex, ExifIopIi, ib.byteOrder)
|
||||||
|
|
||||||
err := exifIb.AddChildIb(iopIb)
|
err := exifIb.AddChildIb(iopIb)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -406,7 +375,7 @@ func GetOrCreateIbFromRootIb(rootIb *IfdBuilder, ifdDesignation string) (ib *Ifd
|
|||||||
gpsIb, err := ib.ChildWithIfdIdentity(GpsIi)
|
gpsIb, err := ib.ChildWithIfdIdentity(GpsIi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if log.Is(err, ErrChildIbNotFound) == true {
|
if log.Is(err, ErrChildIbNotFound) == true {
|
||||||
gpsIb = NewIfdBuilder(GpsIi, ib.byteOrder)
|
gpsIb = NewIfdBuilder(gpsIb.tagIndex, GpsIi, ib.byteOrder)
|
||||||
|
|
||||||
err := ib.AddChildIb(gpsIb)
|
err := ib.AddChildIb(gpsIb)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -463,7 +432,7 @@ func (ib *IfdBuilder) SetThumbnail(data []byte) (err error) {
|
|||||||
log.Panicf("thumbnails can only go into a root Ifd (and only the second one)")
|
log.Panicf("thumbnails can only go into a root Ifd (and only the second one)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dustin): !! Add a test for this function.
|
// TODO(dustin): !! Add a test for this function.
|
||||||
|
|
||||||
if data == nil || len(data) == 0 {
|
if data == nil || len(data) == 0 {
|
||||||
log.Panic("thumbnail is empty")
|
log.Panic("thumbnail is empty")
|
||||||
@ -477,7 +446,10 @@ func (ib *IfdBuilder) SetThumbnail(data []byte) (err error) {
|
|||||||
err = ib.Set(offsetBt)
|
err = ib.Set(offsetBt)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
sizeBt := NewStandardBuilderTag(ib.ii, ThumbnailSizeTagId, ib.byteOrder, []uint32{uint32(len(ib.thumbnailData))})
|
thumbnailSizeIt, err := ib.tagIndex.Get(ib.ii, ThumbnailSizeTagId)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
sizeBt := NewStandardBuilderTag(ib.ii, thumbnailSizeIt, ib.byteOrder, []uint32{uint32(len(ib.thumbnailData))})
|
||||||
|
|
||||||
err = ib.Set(sizeBt)
|
err = ib.Set(sizeBt)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -517,7 +489,7 @@ func (ib *IfdBuilder) printTagTree(levels int) {
|
|||||||
if isChildIb == true {
|
if isChildIb == true {
|
||||||
tagName = "<Child IFD>"
|
tagName = "<Child IFD>"
|
||||||
} else {
|
} else {
|
||||||
it, err := tagIndex.Get(tag.ii, tag.tagId)
|
it, err := ib.tagIndex.Get(tag.ii, tag.tagId)
|
||||||
if log.Is(err, ErrTagNotFound) == true {
|
if log.Is(err, ErrTagNotFound) == true {
|
||||||
tagName = "<UNKNOWN>"
|
tagName = "<UNKNOWN>"
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
@ -817,7 +789,7 @@ func (ib *IfdBuilder) FindTagWithName(tagName string) (bt *BuilderTag, err error
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
it, err := tagIndex.GetWithName(ib.ii, tagName)
|
it, err := ib.tagIndex.GetWithName(ib.ii, tagName)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
found, err := ib.FindN(it.Id, 1)
|
found, err := ib.FindN(it.Id, 1)
|
||||||
@ -1025,9 +997,7 @@ func (ib *IfdBuilder) AddTagsFromExisting(ifd *Ifd, itevr *IfdTagEntryValueResol
|
|||||||
} else {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
// TODO(dustin): !! Not correct. If we're adding from existing and it's an unknown-type tag that we can't parse, we're just going to be seting the placeholder even though there's nothing stopping us from just taking the raw bytes (other than some design decisions that we'd have to make in order to do this).
|
||||||
// TODO(dustin): !! Not correct. If we're adding from existing and it's an unknown-type tag that we can't parse, we're just going to be seting the placeholder even though there's nothing stopping us from just taking the raw bytes (other than some design decisions that we'd have to make in order to do this).
|
|
||||||
|
|
||||||
|
|
||||||
valueBytes, err := itevr.ValueBytes(ite)
|
valueBytes, err := itevr.ValueBytes(ite)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1060,7 +1030,10 @@ func (ib *IfdBuilder) AddStandard(tagId uint16, value interface{}) (err error) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
bt := NewStandardBuilderTag(ib.ii, tagId, ib.byteOrder, value)
|
it, err := ib.tagIndex.Get(ib.ii, tagId)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
bt := NewStandardBuilderTag(ib.ii, it, ib.byteOrder, value)
|
||||||
|
|
||||||
err = ib.add(bt)
|
err = ib.add(bt)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -1078,7 +1051,10 @@ func (ib *IfdBuilder) AddStandardWithName(tagName string, value interface{}) (er
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
bt := NewStandardBuilderTagWithName(ib.ii, tagName, ib.byteOrder, value)
|
it, err := ib.tagIndex.GetWithName(ib.ii, tagName)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
bt := NewStandardBuilderTag(ib.ii, it, ib.byteOrder, value)
|
||||||
|
|
||||||
err = ib.add(bt)
|
err = ib.add(bt)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -1095,9 +1071,12 @@ func (ib *IfdBuilder) SetStandard(tagId uint16, value interface{}) (err error) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// TODO(dustin): !! Add test for this function.
|
// TODO(dustin): !! Add test for this function.
|
||||||
|
|
||||||
bt := NewStandardBuilderTag(ib.ii, tagId, ib.byteOrder, value)
|
it, err := ib.tagIndex.Get(ib.ii, tagId)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
bt := NewStandardBuilderTag(ib.ii, it, ib.byteOrder, value)
|
||||||
|
|
||||||
i, err := ib.Find(tagId)
|
i, err := ib.Find(tagId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1123,9 +1102,12 @@ func (ib *IfdBuilder) SetStandardWithName(tagName string, value interface{}) (er
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// TODO(dustin): !! Add test for this function.
|
// TODO(dustin): !! Add test for this function.
|
||||||
|
|
||||||
bt := NewStandardBuilderTagWithName(ib.ii, tagName, ib.byteOrder, value)
|
it, err := ib.tagIndex.GetWithName(ib.ii, tagName)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
bt := NewStandardBuilderTag(ib.ii, it, ib.byteOrder, value)
|
||||||
|
|
||||||
i, err := ib.Find(bt.tagId)
|
i, err := ib.Find(bt.tagId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package exif
|
package exif
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"reflect"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
)
|
)
|
||||||
@ -17,7 +17,7 @@ func Test_ByteWriter_writeAsBytes_uint8(t *testing.T) {
|
|||||||
err := bw.writeAsBytes(uint8(0x12))
|
err := bw.writeAsBytes(uint8(0x12))
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if bytes.Compare(b.Bytes(), []byte { 0x12 }) != 0 {
|
if bytes.Compare(b.Bytes(), []byte{0x12}) != 0 {
|
||||||
t.Fatalf("uint8 not encoded correctly.")
|
t.Fatalf("uint8 not encoded correctly.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,7 +29,7 @@ func Test_ByteWriter_writeAsBytes_uint16(t *testing.T) {
|
|||||||
err := bw.writeAsBytes(uint16(0x1234))
|
err := bw.writeAsBytes(uint16(0x1234))
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if bytes.Compare(b.Bytes(), []byte { 0x12, 0x34 }) != 0 {
|
if bytes.Compare(b.Bytes(), []byte{0x12, 0x34}) != 0 {
|
||||||
t.Fatalf("uint16 not encoded correctly.")
|
t.Fatalf("uint16 not encoded correctly.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ func Test_ByteWriter_writeAsBytes_uint32(t *testing.T) {
|
|||||||
err := bw.writeAsBytes(uint32(0x12345678))
|
err := bw.writeAsBytes(uint32(0x12345678))
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if bytes.Compare(b.Bytes(), []byte { 0x12, 0x34, 0x56, 0x78 }) != 0 {
|
if bytes.Compare(b.Bytes(), []byte{0x12, 0x34, 0x56, 0x78}) != 0 {
|
||||||
t.Fatalf("uint32 not encoded correctly.")
|
t.Fatalf("uint32 not encoded correctly.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ func Test_ByteWriter_WriteUint16(t *testing.T) {
|
|||||||
err := bw.WriteUint16(uint16(0x1234))
|
err := bw.WriteUint16(uint16(0x1234))
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if bytes.Compare(b.Bytes(), []byte { 0x12, 0x34 }) != 0 {
|
if bytes.Compare(b.Bytes(), []byte{0x12, 0x34}) != 0 {
|
||||||
t.Fatalf("uint16 not encoded correctly (as bytes).")
|
t.Fatalf("uint16 not encoded correctly (as bytes).")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ func Test_ByteWriter_WriteUint32(t *testing.T) {
|
|||||||
err := bw.WriteUint32(uint32(0x12345678))
|
err := bw.WriteUint32(uint32(0x12345678))
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if bytes.Compare(b.Bytes(), []byte { 0x12, 0x34, 0x56, 0x78 }) != 0 {
|
if bytes.Compare(b.Bytes(), []byte{0x12, 0x34, 0x56, 0x78}) != 0 {
|
||||||
t.Fatalf("uint32 not encoded correctly (as bytes).")
|
t.Fatalf("uint32 not encoded correctly (as bytes).")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,10 +74,10 @@ func Test_ByteWriter_WriteFourBytes(t *testing.T) {
|
|||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
bw := NewByteWriter(b, TestDefaultByteOrder)
|
bw := NewByteWriter(b, TestDefaultByteOrder)
|
||||||
|
|
||||||
err := bw.WriteFourBytes([]byte { 0x11, 0x22, 0x33, 0x44 })
|
err := bw.WriteFourBytes([]byte{0x11, 0x22, 0x33, 0x44})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if bytes.Compare(b.Bytes(), []byte { 0x11, 0x22, 0x33, 0x44 }) != 0 {
|
if bytes.Compare(b.Bytes(), []byte{0x11, 0x22, 0x33, 0x44}) != 0 {
|
||||||
t.Fatalf("four-bytes not encoded correctly.")
|
t.Fatalf("four-bytes not encoded correctly.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ func Test_ByteWriter_WriteFourBytes_TooMany(t *testing.T) {
|
|||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
bw := NewByteWriter(b, TestDefaultByteOrder)
|
bw := NewByteWriter(b, TestDefaultByteOrder)
|
||||||
|
|
||||||
err := bw.WriteFourBytes([]byte { 0x11, 0x22, 0x33, 0x44, 0x55 })
|
err := bw.WriteFourBytes([]byte{0x11, 0x22, 0x33, 0x44, 0x55})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("expected error for not exactly four-bytes")
|
t.Fatalf("expected error for not exactly four-bytes")
|
||||||
} else if err.Error() != "value is not four-bytes: (5)" {
|
} else if err.Error() != "value is not four-bytes: (5)" {
|
||||||
@ -94,7 +94,6 @@ func Test_ByteWriter_WriteFourBytes_TooMany(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func Test_IfdDataAllocator_Allocate_InitialOffset1(t *testing.T) {
|
func Test_IfdDataAllocator_Allocate_InitialOffset1(t *testing.T) {
|
||||||
addressableOffset := uint32(0)
|
addressableOffset := uint32(0)
|
||||||
ida := newIfdDataAllocator(addressableOffset)
|
ida := newIfdDataAllocator(addressableOffset)
|
||||||
@ -105,29 +104,29 @@ func Test_IfdDataAllocator_Allocate_InitialOffset1(t *testing.T) {
|
|||||||
t.Fatalf("initial buffer not empty")
|
t.Fatalf("initial buffer not empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
data := []byte { 0x1, 0x2, 0x3 }
|
data := []byte{0x1, 0x2, 0x3}
|
||||||
offset, err := ida.Allocate(data)
|
offset, err := ida.Allocate(data)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
expected := uint32(addressableOffset + 0)
|
expected := uint32(addressableOffset + 0)
|
||||||
if offset != expected {
|
if offset != expected {
|
||||||
t.Fatalf("offset not bumped correctly (2): (%d) != (%d)", offset, expected)
|
t.Fatalf("offset not bumped correctly (2): (%d) != (%d)", offset, expected)
|
||||||
} else if ida.NextOffset() != offset + uint32(3) {
|
} else if ida.NextOffset() != offset+uint32(3) {
|
||||||
t.Fatalf("position counter not advanced properly")
|
t.Fatalf("position counter not advanced properly")
|
||||||
} else if bytes.Compare(ida.Bytes(), []byte { 0x1, 0x2, 0x3 }) != 0 {
|
} else if bytes.Compare(ida.Bytes(), []byte{0x1, 0x2, 0x3}) != 0 {
|
||||||
t.Fatalf("buffer not correct after write (1)")
|
t.Fatalf("buffer not correct after write (1)")
|
||||||
}
|
}
|
||||||
|
|
||||||
data = []byte { 0x4, 0x5, 0x6 }
|
data = []byte{0x4, 0x5, 0x6}
|
||||||
offset, err = ida.Allocate(data)
|
offset, err = ida.Allocate(data)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
expected = uint32(addressableOffset + 3)
|
expected = uint32(addressableOffset + 3)
|
||||||
if offset != expected {
|
if offset != expected {
|
||||||
t.Fatalf("offset not bumped correctly (3): (%d) != (%d)", offset, expected)
|
t.Fatalf("offset not bumped correctly (3): (%d) != (%d)", offset, expected)
|
||||||
} else if ida.NextOffset() != offset + uint32(3) {
|
} else if ida.NextOffset() != offset+uint32(3) {
|
||||||
t.Fatalf("position counter not advanced properly")
|
t.Fatalf("position counter not advanced properly")
|
||||||
} else if bytes.Compare(ida.Bytes(), []byte { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 }) != 0 {
|
} else if bytes.Compare(ida.Bytes(), []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}) != 0 {
|
||||||
t.Fatalf("buffer not correct after write (2)")
|
t.Fatalf("buffer not correct after write (2)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,34 +141,33 @@ func Test_IfdDataAllocator_Allocate_InitialOffset2(t *testing.T) {
|
|||||||
t.Fatalf("initial buffer not empty")
|
t.Fatalf("initial buffer not empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
data := []byte { 0x1, 0x2, 0x3 }
|
data := []byte{0x1, 0x2, 0x3}
|
||||||
offset, err := ida.Allocate(data)
|
offset, err := ida.Allocate(data)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
expected := uint32(addressableOffset + 0)
|
expected := uint32(addressableOffset + 0)
|
||||||
if offset != expected {
|
if offset != expected {
|
||||||
t.Fatalf("offset not bumped correctly (2): (%d) != (%d)", offset, expected)
|
t.Fatalf("offset not bumped correctly (2): (%d) != (%d)", offset, expected)
|
||||||
} else if ida.NextOffset() != offset + uint32(3) {
|
} else if ida.NextOffset() != offset+uint32(3) {
|
||||||
t.Fatalf("position counter not advanced properly")
|
t.Fatalf("position counter not advanced properly")
|
||||||
} else if bytes.Compare(ida.Bytes(), []byte { 0x1, 0x2, 0x3 }) != 0 {
|
} else if bytes.Compare(ida.Bytes(), []byte{0x1, 0x2, 0x3}) != 0 {
|
||||||
t.Fatalf("buffer not correct after write (1)")
|
t.Fatalf("buffer not correct after write (1)")
|
||||||
}
|
}
|
||||||
|
|
||||||
data = []byte { 0x4, 0x5, 0x6 }
|
data = []byte{0x4, 0x5, 0x6}
|
||||||
offset, err = ida.Allocate(data)
|
offset, err = ida.Allocate(data)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
expected = uint32(addressableOffset + 3)
|
expected = uint32(addressableOffset + 3)
|
||||||
if offset != expected {
|
if offset != expected {
|
||||||
t.Fatalf("offset not bumped correctly (3): (%d) != (%d)", offset, expected)
|
t.Fatalf("offset not bumped correctly (3): (%d) != (%d)", offset, expected)
|
||||||
} else if ida.NextOffset() != offset + uint32(3) {
|
} else if ida.NextOffset() != offset+uint32(3) {
|
||||||
t.Fatalf("position counter not advanced properly")
|
t.Fatalf("position counter not advanced properly")
|
||||||
} else if bytes.Compare(ida.Bytes(), []byte { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 }) != 0 {
|
} else if bytes.Compare(ida.Bytes(), []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}) != 0 {
|
||||||
t.Fatalf("buffer not correct after write (2)")
|
t.Fatalf("buffer not correct after write (2)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func Test_IfdByteEncoder__Arithmetic(t *testing.T) {
|
func Test_IfdByteEncoder__Arithmetic(t *testing.T) {
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
|
|
||||||
@ -190,9 +188,13 @@ func Test_IfdByteEncoder_encodeTagToBytes_bytes_embedded1(t *testing.T) {
|
|||||||
|
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
|
|
||||||
ib := NewIfdBuilder(GpsIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, GpsIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := NewStandardBuilderTag(GpsIi, uint16(0x0000), TestDefaultByteOrder, []uint8 { uint8(0x12) })
|
it, err := ti.Get(ib.ii, uint16(0x0000))
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
bt := NewStandardBuilderTag(GpsIi, it, TestDefaultByteOrder, []uint8{uint8(0x12)})
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
bw := NewByteWriter(b, TestDefaultByteOrder)
|
bw := NewByteWriter(b, TestDefaultByteOrder)
|
||||||
@ -205,7 +207,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_bytes_embedded1(t *testing.T) {
|
|||||||
|
|
||||||
if childIfdBlock != nil {
|
if childIfdBlock != nil {
|
||||||
t.Fatalf("no child-IFDs were expected to be allocated")
|
t.Fatalf("no child-IFDs were expected to be allocated")
|
||||||
} else if bytes.Compare(b.Bytes(), []byte { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00 }) != 0 {
|
} else if bytes.Compare(b.Bytes(), []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00}) != 0 {
|
||||||
t.Fatalf("encoded tag-entry bytes not correct")
|
t.Fatalf("encoded tag-entry bytes not correct")
|
||||||
} else if ida.NextOffset() != addressableOffset {
|
} else if ida.NextOffset() != addressableOffset {
|
||||||
t.Fatalf("allocation was done but not expected")
|
t.Fatalf("allocation was done but not expected")
|
||||||
@ -215,9 +217,13 @@ func Test_IfdByteEncoder_encodeTagToBytes_bytes_embedded1(t *testing.T) {
|
|||||||
func Test_IfdByteEncoder_encodeTagToBytes_bytes_embedded2(t *testing.T) {
|
func Test_IfdByteEncoder_encodeTagToBytes_bytes_embedded2(t *testing.T) {
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
|
|
||||||
ib := NewIfdBuilder(GpsIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, GpsIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := NewStandardBuilderTag(GpsIi, uint16(0x0000), TestDefaultByteOrder, []uint8 { uint8(0x12), uint8(0x34), uint8(0x56), uint8(0x78) })
|
it, err := ti.Get(ib.ii, uint16(0x0000))
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
bt := NewStandardBuilderTag(GpsIi, it, TestDefaultByteOrder, []uint8{uint8(0x12), uint8(0x34), uint8(0x56), uint8(0x78)})
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
bw := NewByteWriter(b, TestDefaultByteOrder)
|
bw := NewByteWriter(b, TestDefaultByteOrder)
|
||||||
@ -230,7 +236,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_bytes_embedded2(t *testing.T) {
|
|||||||
|
|
||||||
if childIfdBlock != nil {
|
if childIfdBlock != nil {
|
||||||
t.Fatalf("no child-IFDs were expected to be allocated")
|
t.Fatalf("no child-IFDs were expected to be allocated")
|
||||||
} else if bytes.Compare(b.Bytes(), []byte { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78 }) != 0 {
|
} else if bytes.Compare(b.Bytes(), []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78}) != 0 {
|
||||||
t.Fatalf("encoded tag-entry bytes not correct")
|
t.Fatalf("encoded tag-entry bytes not correct")
|
||||||
} else if ida.NextOffset() != addressableOffset {
|
} else if ida.NextOffset() != addressableOffset {
|
||||||
t.Fatalf("allocation was done but not expected")
|
t.Fatalf("allocation was done but not expected")
|
||||||
@ -240,7 +246,8 @@ func Test_IfdByteEncoder_encodeTagToBytes_bytes_embedded2(t *testing.T) {
|
|||||||
func Test_IfdByteEncoder_encodeTagToBytes_bytes_allocated(t *testing.T) {
|
func Test_IfdByteEncoder_encodeTagToBytes_bytes_allocated(t *testing.T) {
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
|
|
||||||
ib := NewIfdBuilder(GpsIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, GpsIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
bw := NewByteWriter(b, TestDefaultByteOrder)
|
bw := NewByteWriter(b, TestDefaultByteOrder)
|
||||||
@ -248,38 +255,41 @@ func Test_IfdByteEncoder_encodeTagToBytes_bytes_allocated(t *testing.T) {
|
|||||||
addressableOffset := uint32(0x1234)
|
addressableOffset := uint32(0x1234)
|
||||||
ida := newIfdDataAllocator(addressableOffset)
|
ida := newIfdDataAllocator(addressableOffset)
|
||||||
|
|
||||||
bt := NewStandardBuilderTag(GpsIi, uint16(0x0000), TestDefaultByteOrder, []uint8 { uint8(0x12), uint8(0x34), uint8(0x56), uint8(0x78), uint8(0x9a) })
|
it, err := ti.Get(ib.ii, uint16(0x0000))
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
bt := NewStandardBuilderTag(GpsIi, it, TestDefaultByteOrder, []uint8{uint8(0x12), uint8(0x34), uint8(0x56), uint8(0x78), uint8(0x9a)})
|
||||||
|
|
||||||
childIfdBlock, err := ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
|
childIfdBlock, err := ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if childIfdBlock != nil {
|
if childIfdBlock != nil {
|
||||||
t.Fatalf("no child-IFDs were expected to be allocated (1)")
|
t.Fatalf("no child-IFDs were expected to be allocated (1)")
|
||||||
} else if bytes.Compare(b.Bytes(), []byte { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x12, 0x34 }) != 0 {
|
} else if bytes.Compare(b.Bytes(), []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x12, 0x34}) != 0 {
|
||||||
t.Fatalf("encoded tag-entry bytes not correct (1)")
|
t.Fatalf("encoded tag-entry bytes not correct (1)")
|
||||||
} else if ida.NextOffset() != addressableOffset + uint32(5) {
|
} else if ida.NextOffset() != addressableOffset+uint32(5) {
|
||||||
t.Fatalf("allocation offset not expected (1)")
|
t.Fatalf("allocation offset not expected (1)")
|
||||||
} else if bytes.Compare(ida.Bytes(), []byte { 0x12, 0x34, 0x56, 0x78, 0x9A }) != 0 {
|
} else if bytes.Compare(ida.Bytes(), []byte{0x12, 0x34, 0x56, 0x78, 0x9A}) != 0 {
|
||||||
t.Fatalf("allocated data not correct (1)")
|
t.Fatalf("allocated data not correct (1)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that another allocation encodes to the new offset.
|
// Test that another allocation encodes to the new offset.
|
||||||
|
|
||||||
bt = NewStandardBuilderTag(GpsIi, uint16(0x0000), TestDefaultByteOrder, []uint8 { uint8(0xbc), uint8(0xde), uint8(0xf0), uint8(0x12), uint8(0x34) })
|
bt = NewStandardBuilderTag(GpsIi, it, TestDefaultByteOrder, []uint8{uint8(0xbc), uint8(0xde), uint8(0xf0), uint8(0x12), uint8(0x34)})
|
||||||
|
|
||||||
childIfdBlock, err = ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
|
childIfdBlock, err = ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if childIfdBlock != nil {
|
if childIfdBlock != nil {
|
||||||
t.Fatalf("no child-IFDs were expected to be allocated (2)")
|
t.Fatalf("no child-IFDs were expected to be allocated (2)")
|
||||||
} else if bytes.Compare(b.Bytes(), []byte {
|
} else if bytes.Compare(b.Bytes(), []byte{
|
||||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x12, 0x34, // Tag 1
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x12, 0x34, // Tag 1
|
||||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x12, 0x39, // Tag 2
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x12, 0x39, // Tag 2
|
||||||
}) != 0 {
|
}) != 0 {
|
||||||
t.Fatalf("encoded tag-entry bytes not correct (2)")
|
t.Fatalf("encoded tag-entry bytes not correct (2)")
|
||||||
} else if ida.NextOffset() != addressableOffset + uint32(10) {
|
} else if ida.NextOffset() != addressableOffset+uint32(10) {
|
||||||
t.Fatalf("allocation offset not expected (2)")
|
t.Fatalf("allocation offset not expected (2)")
|
||||||
} else if bytes.Compare(ida.Bytes(), []byte {
|
} else if bytes.Compare(ida.Bytes(), []byte{
|
||||||
0x12, 0x34, 0x56, 0x78, 0x9A,
|
0x12, 0x34, 0x56, 0x78, 0x9A,
|
||||||
0xbc, 0xde, 0xf0, 0x12, 0x34,
|
0xbc, 0xde, 0xf0, 0x12, 0x34,
|
||||||
}) != 0 {
|
}) != 0 {
|
||||||
@ -290,7 +300,8 @@ func Test_IfdByteEncoder_encodeTagToBytes_bytes_allocated(t *testing.T) {
|
|||||||
func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withoutAllocate(t *testing.T) {
|
func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withoutAllocate(t *testing.T) {
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
|
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
bw := NewByteWriter(b, TestDefaultByteOrder)
|
bw := NewByteWriter(b, TestDefaultByteOrder)
|
||||||
@ -298,7 +309,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withoutAllocate(t *testing.T
|
|||||||
addressableOffset := uint32(0x1234)
|
addressableOffset := uint32(0x1234)
|
||||||
ida := newIfdDataAllocator(addressableOffset)
|
ida := newIfdDataAllocator(addressableOffset)
|
||||||
|
|
||||||
childIb := NewIfdBuilder(ExifIi, TestDefaultByteOrder)
|
childIb := NewIfdBuilder(ti, ExifIi, TestDefaultByteOrder)
|
||||||
tagValue := NewIfdBuilderTagValueFromIfdBuilder(childIb)
|
tagValue := NewIfdBuilderTagValueFromIfdBuilder(childIb)
|
||||||
bt := NewChildIfdBuilderTag(RootIi, IfdExifId, tagValue)
|
bt := NewChildIfdBuilderTag(RootIi, IfdExifId, tagValue)
|
||||||
|
|
||||||
@ -308,7 +319,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withoutAllocate(t *testing.T
|
|||||||
|
|
||||||
if childIfdBlock != nil {
|
if childIfdBlock != nil {
|
||||||
t.Fatalf("no child-IFDs were expected to be allocated")
|
t.Fatalf("no child-IFDs were expected to be allocated")
|
||||||
} else if bytes.Compare(b.Bytes(), []byte { 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 }) != 0 {
|
} else if bytes.Compare(b.Bytes(), []byte{0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}) != 0 {
|
||||||
t.Fatalf("encoded tag-entry with child-IFD not correct")
|
t.Fatalf("encoded tag-entry with child-IFD not correct")
|
||||||
} else if ida.NextOffset() != addressableOffset {
|
} else if ida.NextOffset() != addressableOffset {
|
||||||
t.Fatalf("allocation offset not expected")
|
t.Fatalf("allocation offset not expected")
|
||||||
@ -320,13 +331,14 @@ func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withAllocate(t *testing.T) {
|
|||||||
// space for and then attach to a tag (which would normally be an entry,
|
// space for and then attach to a tag (which would normally be an entry,
|
||||||
// then, in a higher IFD).
|
// then, in a higher IFD).
|
||||||
|
|
||||||
childIb := NewIfdBuilder(ExifIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
childIb := NewIfdBuilder(ti, ExifIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
childIbTestTag := &BuilderTag{
|
childIbTestTag := &BuilderTag{
|
||||||
ii: ExifIi,
|
ii: ExifIi,
|
||||||
tagId: 0x8822,
|
tagId: 0x8822,
|
||||||
typeId: TypeShort,
|
typeId: TypeShort,
|
||||||
value: NewIfdBuilderTagValueFromBytes([]byte { 0x12, 0x34 }),
|
value: NewIfdBuilderTagValueFromBytes([]byte{0x12, 0x34}),
|
||||||
}
|
}
|
||||||
|
|
||||||
childIb.Add(childIbTestTag)
|
childIb.Add(childIbTestTag)
|
||||||
@ -343,7 +355,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withAllocate(t *testing.T) {
|
|||||||
|
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
|
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
bw := NewByteWriter(b, TestDefaultByteOrder)
|
bw := NewByteWriter(b, TestDefaultByteOrder)
|
||||||
@ -388,7 +400,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withAllocate(t *testing.T) {
|
|||||||
t.Fatalf("IFD first tag unit-count not correct: (%d)", iteV.UnitCount)
|
t.Fatalf("IFD first tag unit-count not correct: (%d)", iteV.UnitCount)
|
||||||
} else if iteV.ValueOffset != nextIfdOffsetToWrite {
|
} else if iteV.ValueOffset != nextIfdOffsetToWrite {
|
||||||
t.Fatalf("IFD's child-IFD offset (as offset) is not correct: (%d) != (%d)", iteV.ValueOffset, nextIfdOffsetToWrite)
|
t.Fatalf("IFD's child-IFD offset (as offset) is not correct: (%d) != (%d)", iteV.ValueOffset, nextIfdOffsetToWrite)
|
||||||
} else if bytes.Compare(iteV.RawValueOffset, []byte { 0x0, 0x0, 0x07, 0xd0 }) != 0 {
|
} else if bytes.Compare(iteV.RawValueOffset, []byte{0x0, 0x0, 0x07, 0xd0}) != 0 {
|
||||||
t.Fatalf("IFD's child-IFD offset (as raw bytes) is not correct: [%x]", iteV.RawValueOffset)
|
t.Fatalf("IFD's child-IFD offset (as raw bytes) is not correct: [%x]", iteV.RawValueOffset)
|
||||||
} else if iteV.ChildIfdName != IfdExif {
|
} else if iteV.ChildIfdName != IfdExif {
|
||||||
t.Fatalf("IFD first tag IFD-name name not correct: [%s]", iteV.ChildIfdName)
|
t.Fatalf("IFD first tag IFD-name name not correct: [%s]", iteV.ChildIfdName)
|
||||||
@ -419,7 +431,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_childIfd__withAllocate(t *testing.T) {
|
|||||||
t.Fatalf("Child IFD first tag unit-count not correct: (%d)", ite.UnitCount)
|
t.Fatalf("Child IFD first tag unit-count not correct: (%d)", ite.UnitCount)
|
||||||
} else if ite.ValueOffset != 0x12340000 {
|
} else if ite.ValueOffset != 0x12340000 {
|
||||||
t.Fatalf("Child IFD first tag value value (as offset) not correct: (0x%02x)", ite.ValueOffset)
|
t.Fatalf("Child IFD first tag value value (as offset) not correct: (0x%02x)", ite.ValueOffset)
|
||||||
} else if bytes.Compare(ite.RawValueOffset, []byte { 0x12, 0x34, 0x0, 0x0 }) != 0 {
|
} else if bytes.Compare(ite.RawValueOffset, []byte{0x12, 0x34, 0x0, 0x0}) != 0 {
|
||||||
t.Fatalf("Child IFD first tag value value (as raw bytes) not correct: [%v]", ite.RawValueOffset)
|
t.Fatalf("Child IFD first tag value value (as raw bytes) not correct: [%v]", ite.RawValueOffset)
|
||||||
} else if ite.ChildIfdName != "" {
|
} else if ite.ChildIfdName != "" {
|
||||||
t.Fatalf("Child IFD first tag IFD-name name not empty: [%s]", ite.ChildIfdName)
|
t.Fatalf("Child IFD first tag IFD-name name not empty: [%s]", ite.ChildIfdName)
|
||||||
@ -443,10 +455,14 @@ func Test_IfdByteEncoder_encodeTagToBytes_simpleTag_allocate(t *testing.T) {
|
|||||||
|
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
|
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
|
it, err := ib.tagIndex.Get(ib.ii, uint16(0x000b))
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
valueString := "testvalue"
|
valueString := "testvalue"
|
||||||
bt := NewStandardBuilderTag(RootIi, uint16(0x000b), TestDefaultByteOrder, valueString)
|
bt := NewStandardBuilderTag(RootIi, it, TestDefaultByteOrder, valueString)
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
bw := NewByteWriter(b, TestDefaultByteOrder)
|
bw := NewByteWriter(b, TestDefaultByteOrder)
|
||||||
@ -474,7 +490,6 @@ func Test_IfdByteEncoder_encodeTagToBytes_simpleTag_allocate(t *testing.T) {
|
|||||||
t.Fatalf("Child IFD not have been allocated.")
|
t.Fatalf("Child IFD not have been allocated.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ite, err := ParseOneTag(RootIi, TestDefaultByteOrder, tagBytes, false)
|
ite, err := ParseOneTag(RootIi, TestDefaultByteOrder, tagBytes, false)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
@ -488,7 +503,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_simpleTag_allocate(t *testing.T) {
|
|||||||
t.Fatalf("Tag unit-count not correct: (%d)", ite.UnitCount)
|
t.Fatalf("Tag unit-count not correct: (%d)", ite.UnitCount)
|
||||||
} else if ite.ValueOffset != addressableOffset {
|
} else if ite.ValueOffset != addressableOffset {
|
||||||
t.Fatalf("Tag's value (as offset) is not correct: (%d) != (%d)", ite.ValueOffset, addressableOffset)
|
t.Fatalf("Tag's value (as offset) is not correct: (%d) != (%d)", ite.ValueOffset, addressableOffset)
|
||||||
} else if bytes.Compare(ite.RawValueOffset, []byte { 0x0, 0x0, 0x12, 0x34 }) != 0 {
|
} else if bytes.Compare(ite.RawValueOffset, []byte{0x0, 0x0, 0x12, 0x34}) != 0 {
|
||||||
t.Fatalf("Tag's value (as raw bytes) is not correct: [%x]", ite.RawValueOffset)
|
t.Fatalf("Tag's value (as raw bytes) is not correct: [%x]", ite.RawValueOffset)
|
||||||
} else if ite.ChildIfdName != "" {
|
} else if ite.ChildIfdName != "" {
|
||||||
t.Fatalf("Tag's IFD-name should be empty: [%s]", ite.ChildIfdName)
|
t.Fatalf("Tag's IFD-name should be empty: [%s]", ite.ChildIfdName)
|
||||||
@ -497,7 +512,7 @@ func Test_IfdByteEncoder_encodeTagToBytes_simpleTag_allocate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expectedBuffer := bytes.NewBufferString(valueString)
|
expectedBuffer := bytes.NewBufferString(valueString)
|
||||||
expectedBuffer.Write([]byte { 0x0 })
|
expectedBuffer.Write([]byte{0x0})
|
||||||
expectedBytes := expectedBuffer.Bytes()
|
expectedBytes := expectedBuffer.Bytes()
|
||||||
|
|
||||||
allocatedBytes := ida.Bytes()
|
allocatedBytes := ida.Bytes()
|
||||||
@ -508,25 +523,28 @@ func Test_IfdByteEncoder_encodeTagToBytes_simpleTag_allocate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getExifSimpleTestIb() *IfdBuilder {
|
func getExifSimpleTestIb() *IfdBuilder {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
err := ib.AddStandard(0x000b, "asciivalue")
|
err := ib.AddStandard(0x000b, "asciivalue")
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddStandard(0x00ff, []uint16 { 0x1122 })
|
err = ib.AddStandard(0x00ff, []uint16{0x1122})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddStandard(0x0100, []uint32 { 0x33445566 })
|
err = ib.AddStandard(0x0100, []uint32{0x33445566})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddStandard(0x013e, []Rational { { Numerator: 0x11112222, Denominator: 0x33334444 } })
|
err = ib.AddStandard(0x013e, []Rational{{Numerator: 0x11112222, Denominator: 0x33334444}})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
return ib
|
return ib
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateExifSimpleTestIb(exifData []byte, t *testing.T) {
|
func validateExifSimpleTestIb(exifData []byte, t *testing.T) {
|
||||||
eh, index, err := Collect(exifData)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
eh, index, err := Collect(ti, exifData)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if eh.ByteOrder != TestDefaultByteOrder {
|
if eh.ByteOrder != TestDefaultByteOrder {
|
||||||
@ -557,19 +575,18 @@ func validateExifSimpleTestIb(exifData []byte, t *testing.T) {
|
|||||||
t.Fatalf("Next-IFD pointer is non-nil.")
|
t.Fatalf("Next-IFD pointer is non-nil.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Verify the values by using the actual, orginal types (this is awesome).
|
// Verify the values by using the actual, orginal types (this is awesome).
|
||||||
|
|
||||||
addressableData := exifData[ExifAddressableAreaStart:]
|
addressableData := exifData[ExifAddressableAreaStart:]
|
||||||
|
|
||||||
expected := []struct{
|
expected := []struct {
|
||||||
tagId uint16
|
tagId uint16
|
||||||
value interface{}
|
value interface{}
|
||||||
}{
|
}{
|
||||||
{ tagId: 0x000b, value: "asciivalue" },
|
{tagId: 0x000b, value: "asciivalue"},
|
||||||
{ tagId: 0x00ff, value: []uint16 { 0x1122 } },
|
{tagId: 0x00ff, value: []uint16{0x1122}},
|
||||||
{ tagId: 0x0100, value: []uint32 { 0x33445566 } },
|
{tagId: 0x0100, value: []uint32{0x33445566}},
|
||||||
{ tagId: 0x013e, value: []Rational {{ Numerator: 0x11112222, Denominator: 0x33334444 }} },
|
{tagId: 0x013e, value: []Rational{{Numerator: 0x11112222, Denominator: 0x33334444}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, e := range ifd.Entries {
|
for i, e := range ifd.Entries {
|
||||||
@ -617,7 +634,7 @@ func Test_IfdByteEncoder_encodeIfdToBytes_simple(t *testing.T) {
|
|||||||
t.Fatalf("Allocated data size not correct: (%d)", allocatedDataSize)
|
t.Fatalf("Allocated data size not correct: (%d)", allocatedDataSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedIfdAndDataBytes := []byte {
|
expectedIfdAndDataBytes := []byte{
|
||||||
// IFD table block.
|
// IFD table block.
|
||||||
|
|
||||||
// - Tag count
|
// - Tag count
|
||||||
@ -632,7 +649,6 @@ func Test_IfdByteEncoder_encodeIfdToBytes_simple(t *testing.T) {
|
|||||||
// - Next IFD offset
|
// - Next IFD offset
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
|
||||||
// IFD data block.
|
// IFD data block.
|
||||||
|
|
||||||
// - The one ASCII value
|
// - The one ASCII value
|
||||||
@ -657,7 +673,6 @@ func Test_IfdByteEncoder_encodeIfdToBytes_fullExif(t *testing.T) {
|
|||||||
|
|
||||||
ib := getExifSimpleTestIb()
|
ib := getExifSimpleTestIb()
|
||||||
|
|
||||||
|
|
||||||
// Encode the IFD to a byte stream.
|
// Encode the IFD to a byte stream.
|
||||||
|
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
@ -677,7 +692,6 @@ func Test_IfdByteEncoder_encodeIfdToBytes_fullExif(t *testing.T) {
|
|||||||
t.Fatalf("Table-and-data size doesn't match what was expected: (%d) != (%d + %d)", len(tableAndAllocated), tableSize, allocatedDataSize)
|
t.Fatalf("Table-and-data size doesn't match what was expected: (%d) != (%d + %d)", len(tableAndAllocated), tableSize, allocatedDataSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Wrap the IFD in a formal EXIF block.
|
// Wrap the IFD in a formal EXIF block.
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
@ -691,7 +705,6 @@ func Test_IfdByteEncoder_encodeIfdToBytes_fullExif(t *testing.T) {
|
|||||||
_, err = b.Write(tableAndAllocated)
|
_, err = b.Write(tableAndAllocated)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// Now, try parsing it as EXIF data, making sure to resolve (read:
|
// Now, try parsing it as EXIF data, making sure to resolve (read:
|
||||||
// dereference) the values (which will include the allocated ones).
|
// dereference) the values (which will include the allocated ones).
|
||||||
|
|
||||||
@ -709,7 +722,6 @@ func Test_IfdByteEncoder_EncodeToExifPayload(t *testing.T) {
|
|||||||
|
|
||||||
ib := getExifSimpleTestIb()
|
ib := getExifSimpleTestIb()
|
||||||
|
|
||||||
|
|
||||||
// Encode the IFD to a byte stream.
|
// Encode the IFD to a byte stream.
|
||||||
|
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
@ -730,7 +742,6 @@ func Test_IfdByteEncoder_EncodeToExifPayload(t *testing.T) {
|
|||||||
_, err = b.Write(encodedIfds)
|
_, err = b.Write(encodedIfds)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// Now, try parsing it as EXIF data, making sure to resolve (read:
|
// Now, try parsing it as EXIF data, making sure to resolve (read:
|
||||||
// dereference) the values (which will include the allocated ones).
|
// dereference) the values (which will include the allocated ones).
|
||||||
|
|
||||||
@ -741,7 +752,7 @@ func Test_IfdByteEncoder_EncodeToExifPayload(t *testing.T) {
|
|||||||
func Test_IfdByteEncoder_EncodeToExif(t *testing.T) {
|
func Test_IfdByteEncoder_EncodeToExif(t *testing.T) {
|
||||||
ib := getExifSimpleTestIb()
|
ib := getExifSimpleTestIb()
|
||||||
|
|
||||||
// TODO(dustin): Do a child-IFD allocation in addition to the tag allocations.
|
// TODO(dustin): Do a child-IFD allocation in addition to the tag allocations.
|
||||||
|
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
|
|
||||||
@ -759,63 +770,58 @@ func Test_IfdByteEncoder_EncodeToExif_WithChildAndSibling(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
err := ib.AddStandard(0x000b, "asciivalue")
|
err := ib.AddStandard(0x000b, "asciivalue")
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddStandard(0x00ff, []uint16 { 0x1122 })
|
err = ib.AddStandard(0x00ff, []uint16{0x1122})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// Add a child IB right in the middle.
|
// Add a child IB right in the middle.
|
||||||
|
|
||||||
childIb := NewIfdBuilder(ExifIi, TestDefaultByteOrder)
|
childIb := NewIfdBuilder(ti, ExifIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
err = childIb.AddStandardWithName("ISOSpeedRatings", []uint16 { 0x1122 })
|
err = childIb.AddStandardWithName("ISOSpeedRatings", []uint16{0x1122})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = childIb.AddStandardWithName("ISOSpeed", []uint32 { 0x33445566 })
|
err = childIb.AddStandardWithName("ISOSpeed", []uint32{0x33445566})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddChildIb(childIb)
|
err = ib.AddChildIb(childIb)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
err = ib.AddStandard(0x0100, []uint32{0x33445566})
|
||||||
err = ib.AddStandard(0x0100, []uint32 { 0x33445566 })
|
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// Add another child IB, just to ensure a little more punishment and make
|
// Add another child IB, just to ensure a little more punishment and make
|
||||||
// sure we're managing our allocation offsets correctly.
|
// sure we're managing our allocation offsets correctly.
|
||||||
|
|
||||||
childIb2 := NewIfdBuilder(GpsIi, TestDefaultByteOrder)
|
childIb2 := NewIfdBuilder(ti, GpsIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
err = childIb2.AddStandardWithName("GPSAltitudeRef", []uint8 { 0x11, 0x22 })
|
err = childIb2.AddStandardWithName("GPSAltitudeRef", []uint8{0x11, 0x22})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddChildIb(childIb2)
|
err = ib.AddChildIb(childIb2)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
err = ib.AddStandard(0x013e, []Rational{{Numerator: 0x11112222, Denominator: 0x33334444}})
|
||||||
err = ib.AddStandard(0x013e, []Rational { { Numerator: 0x11112222, Denominator: 0x33334444 } })
|
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// Link to another IB (sibling relationship). The root/standard IFD may
|
// Link to another IB (sibling relationship). The root/standard IFD may
|
||||||
// occur twice in some JPEGs (for thumbnail or FlashPix images).
|
// occur twice in some JPEGs (for thumbnail or FlashPix images).
|
||||||
|
|
||||||
nextIb := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
nextIb := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
err = nextIb.AddStandard(0x0101, []uint32 { 0x11223344 })
|
err = nextIb.AddStandard(0x0101, []uint32{0x11223344})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = nextIb.AddStandard(0x0102, []uint16 { 0x5566 })
|
err = nextIb.AddStandard(0x0102, []uint16{0x5566})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ib.SetNextIb(nextIb)
|
ib.SetNextIb(nextIb)
|
||||||
|
|
||||||
|
|
||||||
// Encode.
|
// Encode.
|
||||||
|
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
@ -823,10 +829,9 @@ func Test_IfdByteEncoder_EncodeToExif_WithChildAndSibling(t *testing.T) {
|
|||||||
exifData, err := ibe.EncodeToExif(ib)
|
exifData, err := ibe.EncodeToExif(ib)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// Parse.
|
// Parse.
|
||||||
|
|
||||||
_, index, err := Collect(exifData)
|
_, index, err := Collect(ti, exifData)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
tagsDump := index.RootIfd.DumpTree()
|
tagsDump := index.RootIfd.DumpTree()
|
||||||
@ -834,7 +839,7 @@ func Test_IfdByteEncoder_EncodeToExif_WithChildAndSibling(t *testing.T) {
|
|||||||
actual := strings.Join(tagsDump, "\n")
|
actual := strings.Join(tagsDump, "\n")
|
||||||
|
|
||||||
expected :=
|
expected :=
|
||||||
`> IFD [ROOT]->[IFD]:(0) TOP
|
`> IFD [ROOT]->[IFD]:(0) TOP
|
||||||
- (0x000b)
|
- (0x000b)
|
||||||
- (0x00ff)
|
- (0x00ff)
|
||||||
- (0x8769)
|
- (0x8769)
|
||||||
@ -875,27 +880,28 @@ func Test_IfdByteEncoder_EncodeToExif_WithChildAndSibling(t *testing.T) {
|
|||||||
func ExampleIfdByteEncoder_EncodeToExif() {
|
func ExampleIfdByteEncoder_EncodeToExif() {
|
||||||
// Construct an IFD.
|
// Construct an IFD.
|
||||||
|
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
err := ib.AddStandardWithName("ProcessingSoftware", "asciivalue")
|
err := ib.AddStandardWithName("ProcessingSoftware", "asciivalue")
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddStandardWithName("DotRange", []uint8 { 0x11 })
|
err = ib.AddStandardWithName("DotRange", []uint8{0x11})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddStandardWithName("SubfileType", []uint16 { 0x2233 })
|
err = ib.AddStandardWithName("SubfileType", []uint16{0x2233})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddStandardWithName("ImageWidth", []uint32 { 0x44556677 })
|
err = ib.AddStandardWithName("ImageWidth", []uint32{0x44556677})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddStandardWithName("WhitePoint", []Rational { { Numerator: 0x11112222, Denominator: 0x33334444 } })
|
err = ib.AddStandardWithName("WhitePoint", []Rational{{Numerator: 0x11112222, Denominator: 0x33334444}})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
err = ib.AddStandardWithName("ShutterSpeedValue", []SignedRational { { Numerator: 0x11112222, Denominator: 0x33334444 } })
|
err = ib.AddStandardWithName("ShutterSpeedValue", []SignedRational{{Numerator: 0x11112222, Denominator: 0x33334444}})
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// Encode it.
|
// Encode it.
|
||||||
|
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
@ -903,10 +909,9 @@ func ExampleIfdByteEncoder_EncodeToExif() {
|
|||||||
exifData, err := ibe.EncodeToExif(ib)
|
exifData, err := ibe.EncodeToExif(ib)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// Parse it so we can see it.
|
// Parse it so we can see it.
|
||||||
|
|
||||||
_, index, err := Collect(exifData)
|
_, index, err := Collect(ti, exifData)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// addressableData is the byte-slice where the allocated data can be
|
// addressableData is the byte-slice where the allocated data can be
|
||||||
|
@ -12,7 +12,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestAdd(t *testing.T) {
|
func TestAdd(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -98,8 +99,10 @@ func TestAdd(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSetNextIb(t *testing.T) {
|
func TestSetNextIb(t *testing.T) {
|
||||||
ib1 := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
ib2 := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
|
||||||
|
ib1 := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
ib2 := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
if ib1.nextIb != nil {
|
if ib1.nextIb != nil {
|
||||||
t.Fatalf("Next-IFD for IB1 not initially terminal.")
|
t.Fatalf("Next-IFD for IB1 not initially terminal.")
|
||||||
@ -117,7 +120,8 @@ func TestSetNextIb(t *testing.T) {
|
|||||||
|
|
||||||
func TestAddChildIb(t *testing.T) {
|
func TestAddChildIb(t *testing.T) {
|
||||||
|
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -131,7 +135,7 @@ func TestAddChildIb(t *testing.T) {
|
|||||||
|
|
||||||
exifIi, _ := IfdIdOrFail(IfdStandard, IfdExif)
|
exifIi, _ := IfdIdOrFail(IfdStandard, IfdExif)
|
||||||
|
|
||||||
ibChild := NewIfdBuilder(exifIi, TestDefaultByteOrder)
|
ibChild := NewIfdBuilder(ti, exifIi, TestDefaultByteOrder)
|
||||||
err = ib.AddChildIb(ibChild)
|
err = ib.AddChildIb(ibChild)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
@ -164,7 +168,8 @@ func TestAddTagsFromExisting(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
entries := make([]*IfdTagEntry, 3)
|
entries := make([]*IfdTagEntry, 3)
|
||||||
|
|
||||||
@ -194,6 +199,7 @@ func TestAddTagsFromExisting(t *testing.T) {
|
|||||||
ifd := &Ifd{
|
ifd := &Ifd{
|
||||||
Ii: RootIi,
|
Ii: RootIi,
|
||||||
Entries: entries,
|
Entries: entries,
|
||||||
|
tagIndex: ti,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ib.AddTagsFromExisting(ifd, nil, nil, nil)
|
err := ib.AddTagsFromExisting(ifd, nil, nil, nil)
|
||||||
@ -211,7 +217,8 @@ func TestAddTagsFromExisting(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddTagsFromExisting__Includes(t *testing.T) {
|
func TestAddTagsFromExisting__Includes(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
entries := make([]*IfdTagEntry, 3)
|
entries := make([]*IfdTagEntry, 3)
|
||||||
|
|
||||||
@ -237,6 +244,7 @@ func TestAddTagsFromExisting__Includes(t *testing.T) {
|
|||||||
ifd := &Ifd{
|
ifd := &Ifd{
|
||||||
Ii: RootIi,
|
Ii: RootIi,
|
||||||
Entries: entries,
|
Entries: entries,
|
||||||
|
tagIndex: ti,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ib.AddTagsFromExisting(ifd, nil, []uint16{0x33}, nil)
|
err := ib.AddTagsFromExisting(ifd, nil, []uint16{0x33}, nil)
|
||||||
@ -250,7 +258,8 @@ func TestAddTagsFromExisting__Includes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddTagsFromExisting__Excludes(t *testing.T) {
|
func TestAddTagsFromExisting__Excludes(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
entries := make([]*IfdTagEntry, 3)
|
entries := make([]*IfdTagEntry, 3)
|
||||||
|
|
||||||
@ -276,6 +285,7 @@ func TestAddTagsFromExisting__Excludes(t *testing.T) {
|
|||||||
ifd := &Ifd{
|
ifd := &Ifd{
|
||||||
Ii: RootIi,
|
Ii: RootIi,
|
||||||
Entries: entries,
|
Entries: entries,
|
||||||
|
tagIndex: ti,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ib.AddTagsFromExisting(ifd, nil, nil, []uint16{0x11})
|
err := ib.AddTagsFromExisting(ifd, nil, nil, []uint16{0x11})
|
||||||
@ -289,7 +299,8 @@ func TestAddTagsFromExisting__Excludes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFindN_First_1(t *testing.T) {
|
func TestFindN_First_1(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -339,7 +350,8 @@ func TestFindN_First_1(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFindN_First_2_1Returned(t *testing.T) {
|
func TestFindN_First_2_1Returned(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -389,7 +401,8 @@ func TestFindN_First_2_1Returned(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFindN_First_2_2Returned(t *testing.T) {
|
func TestFindN_First_2_2Returned(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -466,7 +479,8 @@ func TestFindN_First_2_2Returned(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFindN_Middle_WithDuplicates(t *testing.T) {
|
func TestFindN_Middle_WithDuplicates(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -546,7 +560,8 @@ func TestFindN_Middle_WithDuplicates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFindN_Middle_NoDuplicates(t *testing.T) {
|
func TestFindN_Middle_NoDuplicates(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -606,7 +621,8 @@ func TestFindN_Middle_NoDuplicates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFindN_Miss(t *testing.T) {
|
func TestFindN_Miss(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
found, err := ib.FindN(0x11, 1)
|
found, err := ib.FindN(0x11, 1)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -617,7 +633,8 @@ func TestFindN_Miss(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFind_Hit(t *testing.T) {
|
func TestFind_Hit(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -675,7 +692,8 @@ func TestFind_Hit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFind_Miss(t *testing.T) {
|
func TestFind_Miss(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -726,7 +744,8 @@ func TestFind_Miss(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReplace(t *testing.T) {
|
func TestReplace(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -788,7 +807,8 @@ func TestReplace(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReplaceN(t *testing.T) {
|
func TestReplaceN(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -850,7 +870,8 @@ func TestReplaceN(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteFirst(t *testing.T) {
|
func TestDeleteFirst(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -946,7 +967,8 @@ func TestDeleteFirst(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteN(t *testing.T) {
|
func TestDeleteN(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -1042,7 +1064,8 @@ func TestDeleteN(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteN_Two(t *testing.T) {
|
func TestDeleteN_Two(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -1122,7 +1145,8 @@ func TestDeleteN_Two(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteAll(t *testing.T) {
|
func TestDeleteAll(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
bt := &BuilderTag{
|
bt := &BuilderTag{
|
||||||
ii: RootIi,
|
ii: RootIi,
|
||||||
@ -1216,7 +1240,9 @@ func Test_IfdBuilder_CreateIfdBuilderFromExistingChain(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
itevr := NewIfdTagEntryValueResolver(rawExif, index.RootIfd.ByteOrder)
|
itevr := NewIfdTagEntryValueResolver(rawExif, index.RootIfd.ByteOrder)
|
||||||
@ -1296,7 +1322,9 @@ func Test_IfdBuilder_CreateIfdBuilderFromExistingChain_RealData(t *testing.T) {
|
|||||||
|
|
||||||
// Decode from binary.
|
// Decode from binary.
|
||||||
|
|
||||||
_, originalIndex, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, originalIndex, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
originalThumbnailData, err := originalIndex.RootIfd.NextIfd.Thumbnail()
|
originalThumbnailData, err := originalIndex.RootIfd.NextIfd.Thumbnail()
|
||||||
@ -1316,7 +1344,7 @@ func Test_IfdBuilder_CreateIfdBuilderFromExistingChain_RealData(t *testing.T) {
|
|||||||
|
|
||||||
// Parse again.
|
// Parse again.
|
||||||
|
|
||||||
_, recoveredIndex, err := Collect(updatedExif)
|
_, recoveredIndex, err := Collect(ti, updatedExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
recoveredTags := recoveredIndex.RootIfd.DumpTags()
|
recoveredTags := recoveredIndex.RootIfd.DumpTags()
|
||||||
@ -1400,143 +1428,145 @@ func Test_IfdBuilder_CreateIfdBuilderFromExistingChain_RealData(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_IfdBuilder_CreateIfdBuilderFromExistingChain_RealData_WithUpdate(t *testing.T) {
|
// func Test_IfdBuilder_CreateIfdBuilderFromExistingChain_RealData_WithUpdate(t *testing.T) {
|
||||||
filepath := path.Join(assetsPath, "NDM_8901.jpg")
|
// filepath := path.Join(assetsPath, "NDM_8901.jpg")
|
||||||
|
|
||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
// rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
// log.PanicIf(err)
|
||||||
|
|
||||||
// Decode from binary.
|
// // Decode from binary.
|
||||||
|
|
||||||
_, originalIndex, err := Collect(rawExif)
|
// ti := NewTagIndex()
|
||||||
log.PanicIf(err)
|
|
||||||
|
|
||||||
originalThumbnailData, err := originalIndex.RootIfd.NextIfd.Thumbnail()
|
// _, originalIndex, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
// log.PanicIf(err)
|
||||||
|
|
||||||
originalTags := originalIndex.RootIfd.DumpTags()
|
// originalThumbnailData, err := originalIndex.RootIfd.NextIfd.Thumbnail()
|
||||||
|
// log.PanicIf(err)
|
||||||
|
|
||||||
// Encode back to binary.
|
// originalTags := originalIndex.RootIfd.DumpTags()
|
||||||
|
|
||||||
ibe := NewIfdByteEncoder()
|
// // Encode back to binary.
|
||||||
|
|
||||||
itevr := NewIfdTagEntryValueResolver(rawExif, originalIndex.RootIfd.ByteOrder)
|
// ibe := NewIfdByteEncoder()
|
||||||
rootIb := NewIfdBuilderFromExistingChain(originalIndex.RootIfd, itevr)
|
|
||||||
|
|
||||||
// Update a tag,.
|
// itevr := NewIfdTagEntryValueResolver(rawExif, originalIndex.RootIfd.ByteOrder)
|
||||||
|
// rootIb := NewIfdBuilderFromExistingChain(originalIndex.RootIfd, itevr)
|
||||||
|
|
||||||
exifBt, err := rootIb.FindTagWithName("ExifTag")
|
// // Update a tag,.
|
||||||
log.PanicIf(err)
|
|
||||||
|
|
||||||
ucBt, err := exifBt.value.Ib().FindTagWithName("UserComment")
|
// exifBt, err := rootIb.FindTagWithName("ExifTag")
|
||||||
log.PanicIf(err)
|
// log.PanicIf(err)
|
||||||
|
|
||||||
uc := TagUnknownType_9298_UserComment{
|
// ucBt, err := exifBt.value.Ib().FindTagWithName("UserComment")
|
||||||
EncodingType: TagUnknownType_9298_UserComment_Encoding_ASCII,
|
// log.PanicIf(err)
|
||||||
EncodingBytes: []byte("TEST COMMENT"),
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ucBt.SetValue(rootIb.byteOrder, uc)
|
// uc := TagUnknownType_9298_UserComment{
|
||||||
log.PanicIf(err)
|
// EncodingType: TagUnknownType_9298_UserComment_Encoding_ASCII,
|
||||||
|
// EncodingBytes: []byte("TEST COMMENT"),
|
||||||
|
// }
|
||||||
|
|
||||||
// Encode.
|
// err = ucBt.SetValue(rootIb.byteOrder, uc)
|
||||||
|
// log.PanicIf(err)
|
||||||
|
|
||||||
updatedExif, err := ibe.EncodeToExif(rootIb)
|
// // Encode.
|
||||||
log.PanicIf(err)
|
|
||||||
|
|
||||||
// Parse again.
|
// updatedExif, err := ibe.EncodeToExif(rootIb)
|
||||||
|
// log.PanicIf(err)
|
||||||
|
|
||||||
_, recoveredIndex, err := Collect(updatedExif)
|
// // Parse again.
|
||||||
log.PanicIf(err)
|
|
||||||
|
|
||||||
recoveredTags := recoveredIndex.RootIfd.DumpTags()
|
// _, recoveredIndex, err := Collect(ti, updatedExif)
|
||||||
|
// log.PanicIf(err)
|
||||||
|
|
||||||
recoveredThumbnailData, err := recoveredIndex.RootIfd.NextIfd.Thumbnail()
|
// recoveredTags := recoveredIndex.RootIfd.DumpTags()
|
||||||
log.PanicIf(err)
|
|
||||||
|
|
||||||
// Check the thumbnail.
|
// recoveredThumbnailData, err := recoveredIndex.RootIfd.NextIfd.Thumbnail()
|
||||||
|
// log.PanicIf(err)
|
||||||
|
|
||||||
if bytes.Compare(recoveredThumbnailData, originalThumbnailData) != 0 {
|
// // Check the thumbnail.
|
||||||
t.Fatalf("recovered thumbnail does not match original")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that all of the same IFDs were presented.
|
// if bytes.Compare(recoveredThumbnailData, originalThumbnailData) != 0 {
|
||||||
|
// t.Fatalf("recovered thumbnail does not match original")
|
||||||
|
// }
|
||||||
|
|
||||||
originalIfdTags := make([][2]interface{}, 0)
|
// // Validate that all of the same IFDs were presented.
|
||||||
for _, ite := range originalTags {
|
|
||||||
if ite.ChildIfdName != "" {
|
|
||||||
originalIfdTags = append(originalIfdTags, [2]interface{}{ite.Ii, ite.TagId})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
recoveredIfdTags := make([][2]interface{}, 0)
|
// originalIfdTags := make([][2]interface{}, 0)
|
||||||
for _, ite := range recoveredTags {
|
// for _, ite := range originalTags {
|
||||||
if ite.ChildIfdName != "" {
|
// if ite.ChildIfdName != "" {
|
||||||
recoveredIfdTags = append(recoveredIfdTags, [2]interface{}{ite.Ii, ite.TagId})
|
// originalIfdTags = append(originalIfdTags, [2]interface{}{ite.Ii, ite.TagId})
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if reflect.DeepEqual(recoveredIfdTags, originalIfdTags) != true {
|
// recoveredIfdTags := make([][2]interface{}, 0)
|
||||||
fmt.Printf("Original IFD tags:\n\n")
|
// for _, ite := range recoveredTags {
|
||||||
|
// if ite.ChildIfdName != "" {
|
||||||
|
// recoveredIfdTags = append(recoveredIfdTags, [2]interface{}{ite.Ii, ite.TagId})
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
for i, x := range originalIfdTags {
|
// if reflect.DeepEqual(recoveredIfdTags, originalIfdTags) != true {
|
||||||
fmt.Printf(" %02d %v\n", i, x)
|
// fmt.Printf("Original IFD tags:\n\n")
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("\nRecovered IFD tags:\n\n")
|
// for i, x := range originalIfdTags {
|
||||||
|
// fmt.Printf(" %02d %v\n", i, x)
|
||||||
|
// }
|
||||||
|
|
||||||
for i, x := range recoveredIfdTags {
|
// fmt.Printf("\nRecovered IFD tags:\n\n")
|
||||||
fmt.Printf(" %02d %v\n", i, x)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("\n")
|
// for i, x := range recoveredIfdTags {
|
||||||
|
// fmt.Printf(" %02d %v\n", i, x)
|
||||||
|
// }
|
||||||
|
|
||||||
t.Fatalf("Recovered IFD tags are not correct.")
|
// fmt.Printf("\n")
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that all of the tags owned by the IFDs were presented. Note
|
// t.Fatalf("Recovered IFD tags are not correct.")
|
||||||
// that the thumbnail tags are not kept but only produced on the fly, which
|
// }
|
||||||
// is why we check it above.
|
|
||||||
|
|
||||||
if len(recoveredTags) != len(originalTags) {
|
// // Validate that all of the tags owned by the IFDs were presented. Note
|
||||||
t.Fatalf("Recovered tag-count does not match original.")
|
// // that the thumbnail tags are not kept but only produced on the fly, which
|
||||||
}
|
// // is why we check it above.
|
||||||
|
|
||||||
for i, recoveredIte := range recoveredTags {
|
// if len(recoveredTags) != len(originalTags) {
|
||||||
if recoveredIte.ChildIfdName != "" {
|
// t.Fatalf("Recovered tag-count does not match original.")
|
||||||
continue
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
originalIte := originalTags[i]
|
// for i, recoveredIte := range recoveredTags {
|
||||||
|
// if recoveredIte.ChildIfdName != "" {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
|
||||||
if recoveredIte.Ii != originalIte.Ii {
|
// originalIte := originalTags[i]
|
||||||
t.Fatalf("IfdIdentify not as expected: %s != %s ITE=%s", recoveredIte.Ii, originalIte.Ii, recoveredIte)
|
|
||||||
} else if recoveredIte.TagId != originalIte.TagId {
|
|
||||||
t.Fatalf("Tag-ID not as expected: %d != %d ITE=%s", recoveredIte.TagId, originalIte.TagId, recoveredIte)
|
|
||||||
} else if recoveredIte.TagType != originalIte.TagType {
|
|
||||||
t.Fatalf("Tag-type not as expected: %d != %d ITE=%s", recoveredIte.TagType, originalIte.TagType, recoveredIte)
|
|
||||||
}
|
|
||||||
|
|
||||||
originalValueBytes, err := originalIte.ValueBytes(originalIndex.RootIfd.addressableData, originalIndex.RootIfd.ByteOrder)
|
// if recoveredIte.Ii != originalIte.Ii {
|
||||||
log.PanicIf(err)
|
// t.Fatalf("IfdIdentify not as expected: %s != %s ITE=%s", recoveredIte.Ii, originalIte.Ii, recoveredIte)
|
||||||
|
// } else if recoveredIte.TagId != originalIte.TagId {
|
||||||
|
// t.Fatalf("Tag-ID not as expected: %d != %d ITE=%s", recoveredIte.TagId, originalIte.TagId, recoveredIte)
|
||||||
|
// } else if recoveredIte.TagType != originalIte.TagType {
|
||||||
|
// t.Fatalf("Tag-type not as expected: %d != %d ITE=%s", recoveredIte.TagType, originalIte.TagType, recoveredIte)
|
||||||
|
// }
|
||||||
|
|
||||||
recoveredValueBytes, err := recoveredIte.ValueBytes(recoveredIndex.RootIfd.addressableData, recoveredIndex.RootIfd.ByteOrder)
|
// originalValueBytes, err := originalIte.ValueBytes(originalIndex.RootIfd.addressableData, originalIndex.RootIfd.ByteOrder)
|
||||||
log.PanicIf(err)
|
// log.PanicIf(err)
|
||||||
|
|
||||||
if recoveredIte.TagId == 0x9286 {
|
// recoveredValueBytes, err := recoveredIte.ValueBytes(recoveredIndex.RootIfd.addressableData, recoveredIndex.RootIfd.ByteOrder)
|
||||||
expectedValueBytes := make([]byte, 0)
|
// log.PanicIf(err)
|
||||||
|
|
||||||
expectedValueBytes = append(expectedValueBytes, []byte{'A', 'S', 'C', 'I', 'I', 0, 0, 0}...)
|
// if recoveredIte.TagId == 0x9286 {
|
||||||
expectedValueBytes = append(expectedValueBytes, []byte("TEST COMMENT")...)
|
// expectedValueBytes := make([]byte, 0)
|
||||||
|
|
||||||
if bytes.Compare(recoveredValueBytes, expectedValueBytes) != 0 {
|
// expectedValueBytes = append(expectedValueBytes, []byte{'A', 'S', 'C', 'I', 'I', 0, 0, 0}...)
|
||||||
t.Fatalf("Recovered UserComment does not have the right value: %v != %v", recoveredValueBytes, expectedValueBytes)
|
// expectedValueBytes = append(expectedValueBytes, []byte("TEST COMMENT")...)
|
||||||
}
|
|
||||||
} else if bytes.Compare(recoveredValueBytes, originalValueBytes) != 0 {
|
// if bytes.Compare(recoveredValueBytes, expectedValueBytes) != 0 {
|
||||||
t.Fatalf("bytes of tag content not correct: %v != %v ITE=%s", recoveredValueBytes, originalValueBytes, recoveredIte)
|
// t.Fatalf("Recovered UserComment does not have the right value: %v != %v", recoveredValueBytes, expectedValueBytes)
|
||||||
}
|
// }
|
||||||
}
|
// } else if bytes.Compare(recoveredValueBytes, originalValueBytes) != 0 {
|
||||||
}
|
// t.Fatalf("bytes of tag content not correct: %v != %v ITE=%s", recoveredValueBytes, originalValueBytes, recoveredIte)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
func ExampleIfd_Thumbnail() {
|
func ExampleIfd_Thumbnail() {
|
||||||
filepath := path.Join(assetsPath, "NDM_8901.jpg")
|
filepath := path.Join(assetsPath, "NDM_8901.jpg")
|
||||||
@ -1544,7 +1574,9 @@ func ExampleIfd_Thumbnail() {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
thumbnailData, err := index.RootIfd.NextIfd.Thumbnail()
|
thumbnailData, err := index.RootIfd.NextIfd.Thumbnail()
|
||||||
@ -1560,7 +1592,9 @@ func ExampleBuilderTag_SetValue() {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// Create builder.
|
// Create builder.
|
||||||
@ -1599,11 +1633,14 @@ func ExampleBuilderTag_SetValue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_IfdBuilder_CreateIfdBuilderWithExistingIfd(t *testing.T) {
|
func Test_IfdBuilder_CreateIfdBuilderWithExistingIfd(t *testing.T) {
|
||||||
|
ti := NewTagIndex()
|
||||||
|
|
||||||
tagId := IfdTagIdWithIdentityOrFail(GpsIi)
|
tagId := IfdTagIdWithIdentityOrFail(GpsIi)
|
||||||
|
|
||||||
parentIfd := &Ifd{
|
parentIfd := &Ifd{
|
||||||
Ii: RootIi,
|
Ii: RootIi,
|
||||||
Name: IfdStandard,
|
Name: IfdStandard,
|
||||||
|
tagIndex: ti,
|
||||||
}
|
}
|
||||||
|
|
||||||
ifd := &Ifd{
|
ifd := &Ifd{
|
||||||
@ -1612,6 +1649,7 @@ func Test_IfdBuilder_CreateIfdBuilderWithExistingIfd(t *testing.T) {
|
|||||||
ByteOrder: TestDefaultByteOrder,
|
ByteOrder: TestDefaultByteOrder,
|
||||||
Offset: 0x123,
|
Offset: 0x123,
|
||||||
ParentIfd: parentIfd,
|
ParentIfd: parentIfd,
|
||||||
|
tagIndex: ti,
|
||||||
}
|
}
|
||||||
|
|
||||||
ib := NewIfdBuilderWithExistingIfd(ifd)
|
ib := NewIfdBuilderWithExistingIfd(ifd)
|
||||||
@ -1628,7 +1666,12 @@ func Test_IfdBuilder_CreateIfdBuilderWithExistingIfd(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNewStandardBuilderTag_OneUnit(t *testing.T) {
|
func TestNewStandardBuilderTag_OneUnit(t *testing.T) {
|
||||||
bt := NewStandardBuilderTag(ExifIi, uint16(0x8833), TestDefaultByteOrder, []uint32{uint32(0x1234)})
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
it, err := ti.Get(ExifIi, uint16(0x8833))
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
bt := NewStandardBuilderTag(ExifIi, it, TestDefaultByteOrder, []uint32{uint32(0x1234)})
|
||||||
|
|
||||||
if bt.ii != ExifIi {
|
if bt.ii != ExifIi {
|
||||||
t.Fatalf("II in BuilderTag not correct")
|
t.Fatalf("II in BuilderTag not correct")
|
||||||
@ -1640,21 +1683,12 @@ func TestNewStandardBuilderTag_OneUnit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNewStandardBuilderTag_TwoUnits(t *testing.T) {
|
func TestNewStandardBuilderTag_TwoUnits(t *testing.T) {
|
||||||
bt := NewStandardBuilderTag(ExifIi, uint16(0x8833), TestDefaultByteOrder, []uint32{uint32(0x1234), uint32(0x5678)})
|
ti := NewTagIndex()
|
||||||
|
|
||||||
if bt.ii != ExifIi {
|
it, err := ti.Get(ExifIi, uint16(0x8833))
|
||||||
t.Fatalf("II in BuilderTag not correct")
|
log.PanicIf(err)
|
||||||
} else if bt.tagId != 0x8833 {
|
|
||||||
t.Fatalf("tag-ID not correct")
|
|
||||||
} else if bytes.Compare(bt.value.Bytes(), []byte{
|
|
||||||
0x0, 0x0, 0x12, 0x34,
|
|
||||||
0x0, 0x0, 0x56, 0x78}) != 0 {
|
|
||||||
t.Fatalf("value not correct")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewStandardBuilderTagWithName(t *testing.T) {
|
bt := NewStandardBuilderTag(ExifIi, it, TestDefaultByteOrder, []uint32{uint32(0x1234), uint32(0x5678)})
|
||||||
bt := NewStandardBuilderTagWithName(ExifIi, "ISOSpeed", TestDefaultByteOrder, []uint32{uint32(0x1234), uint32(0x5678)})
|
|
||||||
|
|
||||||
if bt.ii != ExifIi {
|
if bt.ii != ExifIi {
|
||||||
t.Fatalf("II in BuilderTag not correct")
|
t.Fatalf("II in BuilderTag not correct")
|
||||||
@ -1668,7 +1702,8 @@ func TestNewStandardBuilderTagWithName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddStandardWithName(t *testing.T) {
|
func TestAddStandardWithName(t *testing.T) {
|
||||||
ib := NewIfdBuilder(RootIi, TestDefaultByteOrder)
|
ti := NewTagIndex()
|
||||||
|
ib := NewIfdBuilder(ti, RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
err := ib.AddStandardWithName("ProcessingSoftware", "some software")
|
err := ib.AddStandardWithName("ProcessingSoftware", "some software")
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
@ -2,12 +2,12 @@ package exif
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
@ -23,7 +23,6 @@ var (
|
|||||||
ErrNoGpsTags = errors.New("no gps tags")
|
ErrNoGpsTags = errors.New("no gps tags")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// IfdTagEnumerator knows how to decode an IFD and all of the tags it
|
// IfdTagEnumerator knows how to decode an IFD and all of the tags it
|
||||||
// describes.
|
// describes.
|
||||||
//
|
//
|
||||||
@ -96,19 +95,20 @@ func (ife *IfdTagEnumerator) getUint32() (value uint32, raw []byte, err error) {
|
|||||||
return value, raw, nil
|
return value, raw, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type IfdEnumerate struct {
|
type IfdEnumerate struct {
|
||||||
exifData []byte
|
exifData []byte
|
||||||
buffer *bytes.Buffer
|
buffer *bytes.Buffer
|
||||||
byteOrder binary.ByteOrder
|
byteOrder binary.ByteOrder
|
||||||
currentOffset uint32
|
currentOffset uint32
|
||||||
|
tagIndex *TagIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIfdEnumerate(exifData []byte, byteOrder binary.ByteOrder) *IfdEnumerate {
|
func NewIfdEnumerate(tagIndex *TagIndex, exifData []byte, byteOrder binary.ByteOrder) *IfdEnumerate {
|
||||||
return &IfdEnumerate{
|
return &IfdEnumerate{
|
||||||
exifData: exifData,
|
exifData: exifData,
|
||||||
buffer: bytes.NewBuffer(exifData),
|
buffer: bytes.NewBuffer(exifData),
|
||||||
byteOrder: byteOrder,
|
byteOrder: byteOrder,
|
||||||
|
tagIndex: tagIndex,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ func (ie *IfdEnumerate) getTagEnumerator(ifdOffset uint32) (ite *IfdTagEnumerato
|
|||||||
return ite
|
return ite
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ie *IfdEnumerate) parseTag(ii IfdIdentity, tagIndex int, ite *IfdTagEnumerator, resolveValue bool) (tag *IfdTagEntry, err error) {
|
func (ie *IfdEnumerate) parseTag(ii IfdIdentity, tagPosition int, ite *IfdTagEnumerator, resolveValue bool) (tag *IfdTagEntry, 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))
|
||||||
@ -152,7 +152,7 @@ func (ie *IfdEnumerate) parseTag(ii IfdIdentity, tagIndex int, ite *IfdTagEnumer
|
|||||||
tag = &IfdTagEntry{
|
tag = &IfdTagEntry{
|
||||||
Ii: ii,
|
Ii: ii,
|
||||||
TagId: tagId,
|
TagId: tagId,
|
||||||
TagIndex: tagIndex,
|
TagIndex: tagPosition,
|
||||||
TagType: tagType,
|
TagType: tagType,
|
||||||
UnitCount: unitCount,
|
UnitCount: unitCount,
|
||||||
ValueOffset: valueOffset,
|
ValueOffset: valueOffset,
|
||||||
@ -220,7 +220,7 @@ func (ie *IfdEnumerate) resolveTagValue(ite *IfdTagEntry) (valueBytes []byte, is
|
|||||||
|
|
||||||
return valueBytes, false, nil
|
return valueBytes, false, nil
|
||||||
default:
|
default:
|
||||||
// TODO(dustin): !! Finish translating the rest of the types (make reusable and replace into other similar implementations?)
|
// TODO(dustin): !! Finish translating the rest of the types (make reusable and replace into other similar implementations?)
|
||||||
log.Panicf("can not produce bytes for unknown-type tag (0x%04x): [%s]", ite.TagId, reflect.TypeOf(value))
|
log.Panicf("can not produce bytes for unknown-type tag (0x%04x): [%s]", ite.TagId, reflect.TypeOf(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,7 +336,6 @@ func (ie *IfdEnumerate) parseThumbnail(offsetIte, lengthIte *IfdTagEntry) (thumb
|
|||||||
|
|
||||||
addressableData := ie.exifData[ExifAddressableAreaStart:]
|
addressableData := ie.exifData[ExifAddressableAreaStart:]
|
||||||
|
|
||||||
|
|
||||||
vRaw, err := lengthIte.Value(addressableData, ie.byteOrder)
|
vRaw, err := lengthIte.Value(addressableData, ie.byteOrder)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
@ -365,7 +364,7 @@ func (ie *IfdEnumerate) scan(ii IfdIdentity, ifdOffset uint32, visitor RawTagVis
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for ifdIndex := 0;; ifdIndex++ {
|
for ifdIndex := 0; ; ifdIndex++ {
|
||||||
ifdEnumerateLogger.Debugf(nil, "Parsing IFD [%s] (%d) at offset (%04x).", ii.IfdName, ifdIndex, ifdOffset)
|
ifdEnumerateLogger.Debugf(nil, "Parsing IFD [%s] (%d) at offset (%04x).", ii.IfdName, ifdIndex, ifdOffset)
|
||||||
ite := ie.getTagEnumerator(ifdOffset)
|
ite := ie.getTagEnumerator(ifdOffset)
|
||||||
|
|
||||||
@ -398,7 +397,6 @@ func (ie *IfdEnumerate) Scan(ifdOffset uint32, visitor RawTagVisitor, resolveVal
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Ifd represents a single parsed IFD.
|
// Ifd represents a single parsed IFD.
|
||||||
type Ifd struct {
|
type Ifd struct {
|
||||||
// This is just for convenience, just so that we can easily get the values
|
// This is just for convenience, just so that we can easily get the values
|
||||||
@ -435,6 +433,8 @@ type Ifd struct {
|
|||||||
NextIfd *Ifd
|
NextIfd *Ifd
|
||||||
|
|
||||||
thumbnailData []byte
|
thumbnailData []byte
|
||||||
|
|
||||||
|
tagIndex *TagIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ifd *Ifd) ChildWithIfdIdentity(ii IfdIdentity) (childIfd *Ifd, err error) {
|
func (ifd *Ifd) ChildWithIfdIdentity(ii IfdIdentity) (childIfd *Ifd, err error) {
|
||||||
@ -524,7 +524,7 @@ func (ifd *Ifd) FindTagWithName(tagName string) (results []*IfdTagEntry, err err
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
ii := ifd.Identity()
|
ii := ifd.Identity()
|
||||||
it, err := tagIndex.GetWithName(ii, tagName)
|
it, err := ifd.tagIndex.GetWithName(ii, tagName)
|
||||||
if log.Is(err, ErrTagNotFound) == true {
|
if log.Is(err, ErrTagNotFound) == true {
|
||||||
log.Panic(ErrTagNotStandard)
|
log.Panic(ErrTagNotStandard)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
@ -613,7 +613,7 @@ func (ifd *Ifd) DumpTags() []*IfdTagEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ifd *Ifd) printTagTree(populateValues bool, index, level int, nextLink bool) {
|
func (ifd *Ifd) printTagTree(populateValues bool, index, level int, nextLink bool) {
|
||||||
indent := strings.Repeat(" ", level * 2)
|
indent := strings.Repeat(" ", level*2)
|
||||||
|
|
||||||
prefix := " "
|
prefix := " "
|
||||||
if nextLink {
|
if nextLink {
|
||||||
@ -630,7 +630,7 @@ func (ifd *Ifd) printTagTree(populateValues bool, index, level int, nextLink boo
|
|||||||
if tag.ChildIfdName != "" {
|
if tag.ChildIfdName != "" {
|
||||||
fmt.Printf("%s - TAG: %s\n", indent, tag)
|
fmt.Printf("%s - TAG: %s\n", indent, tag)
|
||||||
} else {
|
} else {
|
||||||
it, err := tagIndex.Get(ifd.Identity(), tag.TagId)
|
it, err := ifd.tagIndex.Get(ifd.Identity(), tag.TagId)
|
||||||
|
|
||||||
tagName := ""
|
tagName := ""
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -662,7 +662,7 @@ func (ifd *Ifd) printTagTree(populateValues bool, index, level int, nextLink boo
|
|||||||
log.Panicf("alien child IFD referenced by a tag: [%s]", tag.ChildIfdName)
|
log.Panicf("alien child IFD referenced by a tag: [%s]", tag.ChildIfdName)
|
||||||
}
|
}
|
||||||
|
|
||||||
childIfd.printTagTree(populateValues, 0, level + 1, false)
|
childIfd.printTagTree(populateValues, 0, level+1, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,7 +671,7 @@ func (ifd *Ifd) printTagTree(populateValues bool, index, level int, nextLink boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ifd.NextIfd != nil {
|
if ifd.NextIfd != nil {
|
||||||
ifd.NextIfd.printTagTree(populateValues, index + 1, level, true)
|
ifd.NextIfd.printTagTree(populateValues, index+1, level, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,7 +681,7 @@ func (ifd *Ifd) PrintTagTree(populateValues bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ifd *Ifd) printIfdTree(level int, nextLink bool) {
|
func (ifd *Ifd) printIfdTree(level int, nextLink bool) {
|
||||||
indent := strings.Repeat(" ", level * 2)
|
indent := strings.Repeat(" ", level*2)
|
||||||
|
|
||||||
prefix := " "
|
prefix := " "
|
||||||
if nextLink {
|
if nextLink {
|
||||||
@ -703,7 +703,7 @@ func (ifd *Ifd) printIfdTree(level int, nextLink bool) {
|
|||||||
log.Panicf("alien child IFD referenced by a tag: [%s]", tag.ChildIfdName)
|
log.Panicf("alien child IFD referenced by a tag: [%s]", tag.ChildIfdName)
|
||||||
}
|
}
|
||||||
|
|
||||||
childIfd.printIfdTree(level + 1, false)
|
childIfd.printIfdTree(level+1, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,7 +726,7 @@ func (ifd *Ifd) dumpTree(tagsDump []string, level int) []string {
|
|||||||
tagsDump = make([]string, 0)
|
tagsDump = make([]string, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
indent := strings.Repeat(" ", level * 2)
|
indent := strings.Repeat(" ", level*2)
|
||||||
|
|
||||||
var ifdPhrase string
|
var ifdPhrase string
|
||||||
if ifd.ParentIfd != nil {
|
if ifd.ParentIfd != nil {
|
||||||
@ -750,7 +750,7 @@ func (ifd *Ifd) dumpTree(tagsDump []string, level int) []string {
|
|||||||
log.Panicf("alien child IFD referenced by a tag: [%s]", tag.ChildIfdName)
|
log.Panicf("alien child IFD referenced by a tag: [%s]", tag.ChildIfdName)
|
||||||
}
|
}
|
||||||
|
|
||||||
tagsDump = childIfd.dumpTree(tagsDump, level + 1)
|
tagsDump = childIfd.dumpTree(tagsDump, level+1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,9 +785,7 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// TODO(dustin): !! Also add functionality to update the GPS info.
|
||||||
// TODO(dustin): !! Also add functionality to update the GPS info.
|
|
||||||
|
|
||||||
|
|
||||||
gi = new(GpsInfo)
|
gi = new(GpsInfo)
|
||||||
|
|
||||||
@ -797,11 +795,10 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
|
|||||||
|
|
||||||
if tags, found := ifd.EntriesByTagId[TagVersionId]; found == false {
|
if tags, found := ifd.EntriesByTagId[TagVersionId]; found == false {
|
||||||
log.Panic(ErrNoGpsTags)
|
log.Panic(ErrNoGpsTags)
|
||||||
} else if bytes.Compare(tags[0].value, []byte { 2, 2, 0, 0}) != 0 {
|
} else if bytes.Compare(tags[0].value, []byte{2, 2, 0, 0}) != 0 {
|
||||||
log.Panic(ErrNoGpsTags)
|
log.Panic(ErrNoGpsTags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tags, found := ifd.EntriesByTagId[TagLatitudeId]
|
tags, found := ifd.EntriesByTagId[TagLatitudeId]
|
||||||
if found == false {
|
if found == false {
|
||||||
log.Panicf("latitude not found")
|
log.Panicf("latitude not found")
|
||||||
@ -834,7 +831,6 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
|
|||||||
longitudeRefValue, err := ifd.TagValue(tags[0])
|
longitudeRefValue, err := ifd.TagValue(tags[0])
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// Parse location.
|
// Parse location.
|
||||||
|
|
||||||
latitudeRaw := latitudeValue.([]Rational)
|
latitudeRaw := latitudeValue.([]Rational)
|
||||||
@ -855,7 +851,6 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
|
|||||||
Seconds: int(float64(longitudeRaw[2].Numerator) / float64(longitudeRaw[2].Denominator)),
|
Seconds: int(float64(longitudeRaw[2].Numerator) / float64(longitudeRaw[2].Denominator)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Parse altitude.
|
// Parse altitude.
|
||||||
|
|
||||||
altitudeTags, foundAltitude := ifd.EntriesByTagId[TagAltitudeId]
|
altitudeTags, foundAltitude := ifd.EntriesByTagId[TagAltitudeId]
|
||||||
@ -877,7 +872,6 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
|
|||||||
gi.Altitude = altitude
|
gi.Altitude = altitude
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Parse time.
|
// Parse time.
|
||||||
|
|
||||||
timestampTags, foundTimestamp := ifd.EntriesByTagId[TagTimestampId]
|
timestampTags, foundTimestamp := ifd.EntriesByTagId[TagTimestampId]
|
||||||
@ -910,7 +904,6 @@ func (ifd *Ifd) GpsInfo() (gi *GpsInfo, err error) {
|
|||||||
return gi, nil
|
return gi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type ParsedTagVisitor func(*Ifd, *IfdTagEntry) error
|
type ParsedTagVisitor func(*Ifd, *IfdTagEntry) error
|
||||||
|
|
||||||
func (ifd *Ifd) EnumerateTagsRecursively(visitor ParsedTagVisitor) (err error) {
|
func (ifd *Ifd) EnumerateTagsRecursively(visitor ParsedTagVisitor) (err error) {
|
||||||
@ -937,7 +930,6 @@ func (ifd *Ifd) EnumerateTagsRecursively(visitor ParsedTagVisitor) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type QueuedIfd struct {
|
type QueuedIfd struct {
|
||||||
Ii IfdIdentity
|
Ii IfdIdentity
|
||||||
TagId uint16
|
TagId uint16
|
||||||
@ -952,7 +944,6 @@ type QueuedIfd struct {
|
|||||||
ParentTagIndex int
|
ParentTagIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type IfdIndex struct {
|
type IfdIndex struct {
|
||||||
RootIfd *Ifd
|
RootIfd *Ifd
|
||||||
Ifds []*Ifd
|
Ifds []*Ifd
|
||||||
@ -960,7 +951,6 @@ type IfdIndex struct {
|
|||||||
Lookup map[IfdIdentity][]*Ifd
|
Lookup map[IfdIdentity][]*Ifd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Scan enumerates the different EXIF blocks (called IFDs).
|
// Scan enumerates the different EXIF blocks (called IFDs).
|
||||||
func (ie *IfdEnumerate) Collect(rootIfdOffset uint32, resolveValues bool) (index IfdIndex, err error) {
|
func (ie *IfdEnumerate) Collect(rootIfdOffset uint32, resolveValues bool) (index IfdIndex, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -1043,6 +1033,8 @@ func (ie *IfdEnumerate) Collect(rootIfdOffset uint32, resolveValues bool) (index
|
|||||||
|
|
||||||
NextIfdOffset: nextIfdOffset,
|
NextIfdOffset: nextIfdOffset,
|
||||||
thumbnailData: thumbnailData,
|
thumbnailData: thumbnailData,
|
||||||
|
|
||||||
|
tagIndex: ie.tagIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add ourselves to a big list of IFDs.
|
// Add ourselves to a big list of IFDs.
|
||||||
@ -1146,7 +1138,6 @@ func (ie *IfdEnumerate) setChildrenIndex(ifd *Ifd) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ParseOneIfd is a hack to use an IE to parse a raw IFD block. Can be used for
|
// ParseOneIfd is a hack to use an IE to parse a raw IFD block. Can be used for
|
||||||
// testing.
|
// testing.
|
||||||
func ParseOneIfd(ii IfdIdentity, byteOrder binary.ByteOrder, ifdBlock []byte, visitor RawTagVisitor, resolveValues bool) (nextIfdOffset uint32, entries []*IfdTagEntry, err error) {
|
func ParseOneIfd(ii IfdIdentity, byteOrder binary.ByteOrder, ifdBlock []byte, visitor RawTagVisitor, resolveValues bool) (nextIfdOffset uint32, entries []*IfdTagEntry, err error) {
|
||||||
@ -1197,7 +1188,7 @@ func FindIfdFromRootIfd(rootIfd *Ifd, ifdDesignation string) (ifd *Ifd, err erro
|
|||||||
|
|
||||||
ifd = rootIfd
|
ifd = rootIfd
|
||||||
|
|
||||||
// TODO(dustin): !! Add test.
|
// TODO(dustin): !! Add test.
|
||||||
|
|
||||||
switch ifdDesignation {
|
switch ifdDesignation {
|
||||||
case "ifd0":
|
case "ifd0":
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package exif
|
package exif
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path"
|
|
||||||
"testing"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -53,7 +53,9 @@ func TestIfdTagEntry_ValueBytes_RealData(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
eh, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
eh, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
var ite *IfdTagEntry
|
var ite *IfdTagEntry
|
||||||
@ -95,7 +97,9 @@ func TestIfdTagEntry_Resolver_ValueBytes(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
eh, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
eh, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
var ite *IfdTagEntry
|
var ite *IfdTagEntry
|
||||||
@ -138,7 +142,9 @@ func TestIfdTagEntry_Resolver_ValueBytes__Unknown_Field_And_Nonroot_Ifd(t *testi
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
eh, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
eh, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ii, _ := IfdIdOrFail(IfdStandard, IfdExif)
|
ii, _ := IfdIdOrFail(IfdStandard, IfdExif)
|
||||||
@ -161,7 +167,7 @@ func TestIfdTagEntry_Resolver_ValueBytes__Unknown_Field_And_Nonroot_Ifd(t *testi
|
|||||||
decodedBytes, err := itevr.ValueBytes(ite)
|
decodedBytes, err := itevr.ValueBytes(ite)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
expected := []byte { '0', '2', '3', '0' }
|
expected := []byte{'0', '2', '3', '0'}
|
||||||
|
|
||||||
if len(decodedBytes) != int(ite.UnitCount) {
|
if len(decodedBytes) != int(ite.UnitCount) {
|
||||||
t.Fatalf("Decoded bytes not the right count.")
|
t.Fatalf("Decoded bytes not the right count.")
|
||||||
@ -176,7 +182,9 @@ func Test_Ifd_FindTagWithId_Hit(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ifd := index.RootIfd
|
ifd := index.RootIfd
|
||||||
@ -195,7 +203,9 @@ func Test_Ifd_FindTagWithId_Miss(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ifd := index.RootIfd
|
ifd := index.RootIfd
|
||||||
@ -214,7 +224,9 @@ func Test_Ifd_FindTagWithName_Hit(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ifd := index.RootIfd
|
ifd := index.RootIfd
|
||||||
@ -233,7 +245,9 @@ func Test_Ifd_FindTagWithName_Miss(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ifd := index.RootIfd
|
ifd := index.RootIfd
|
||||||
@ -252,7 +266,9 @@ func Test_Ifd_FindTagWithName_NonStandard(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ifd := index.RootIfd
|
ifd := index.RootIfd
|
||||||
@ -271,7 +287,9 @@ func Test_Ifd_Thumbnail(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ifd := index.RootIfd
|
ifd := index.RootIfd
|
||||||
@ -307,7 +325,9 @@ func TestIfd_GpsInfo(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ifd, err := index.RootIfd.ChildWithIfdIdentity(GpsIi)
|
ifd, err := index.RootIfd.ChildWithIfdIdentity(GpsIi)
|
||||||
@ -335,14 +355,15 @@ func TestIfd_EnumerateTagsRecursively(t *testing.T) {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
log.PanicIf(err)
|
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
|
log.PanicIf(err)
|
||||||
|
|
||||||
collected := make([][2]interface{}, 0)
|
collected := make([][2]interface{}, 0)
|
||||||
|
|
||||||
cb := func(ifd *Ifd, ite *IfdTagEntry) error {
|
cb := func(ifd *Ifd, ite *IfdTagEntry) error {
|
||||||
item := [2]interface{} {
|
item := [2]interface{}{
|
||||||
ifd.Ii.IfdName,
|
ifd.Ii.IfdName,
|
||||||
int(ite.TagId),
|
int(ite.TagId),
|
||||||
}
|
}
|
||||||
@ -355,107 +376,107 @@ func TestIfd_EnumerateTagsRecursively(t *testing.T) {
|
|||||||
err = index.RootIfd.EnumerateTagsRecursively(cb)
|
err = index.RootIfd.EnumerateTagsRecursively(cb)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
expected := [][2]interface{} {
|
expected := [][2]interface{}{
|
||||||
[2]interface{} { "IFD", 0x010f },
|
[2]interface{}{"IFD", 0x010f},
|
||||||
[2]interface{} { "IFD", 0x0110 },
|
[2]interface{}{"IFD", 0x0110},
|
||||||
[2]interface{} { "IFD", 0x0112 },
|
[2]interface{}{"IFD", 0x0112},
|
||||||
[2]interface{} { "IFD", 0x011a },
|
[2]interface{}{"IFD", 0x011a},
|
||||||
[2]interface{} { "IFD", 0x011b },
|
[2]interface{}{"IFD", 0x011b},
|
||||||
[2]interface{} { "IFD", 0x0128 },
|
[2]interface{}{"IFD", 0x0128},
|
||||||
[2]interface{} { "IFD", 0x0132 },
|
[2]interface{}{"IFD", 0x0132},
|
||||||
[2]interface{} { "IFD", 0x013b },
|
[2]interface{}{"IFD", 0x013b},
|
||||||
[2]interface{} { "IFD", 0x0213 },
|
[2]interface{}{"IFD", 0x0213},
|
||||||
[2]interface{} { "IFD", 0x8298 },
|
[2]interface{}{"IFD", 0x8298},
|
||||||
[2]interface{} { "Exif", 0x829a },
|
[2]interface{}{"Exif", 0x829a},
|
||||||
[2]interface{} { "Exif", 0x829d },
|
[2]interface{}{"Exif", 0x829d},
|
||||||
[2]interface{} { "Exif", 0x8822 },
|
[2]interface{}{"Exif", 0x8822},
|
||||||
[2]interface{} { "Exif", 0x8827 },
|
[2]interface{}{"Exif", 0x8827},
|
||||||
[2]interface{} { "Exif", 0x8830 },
|
[2]interface{}{"Exif", 0x8830},
|
||||||
[2]interface{} { "Exif", 0x8832 },
|
[2]interface{}{"Exif", 0x8832},
|
||||||
[2]interface{} { "Exif", 0x9000 },
|
[2]interface{}{"Exif", 0x9000},
|
||||||
[2]interface{} { "Exif", 0x9003 },
|
[2]interface{}{"Exif", 0x9003},
|
||||||
[2]interface{} { "Exif", 0x9004 },
|
[2]interface{}{"Exif", 0x9004},
|
||||||
[2]interface{} { "Exif", 0x9101 },
|
[2]interface{}{"Exif", 0x9101},
|
||||||
[2]interface{} { "Exif", 0x9201 },
|
[2]interface{}{"Exif", 0x9201},
|
||||||
[2]interface{} { "Exif", 0x9202 },
|
[2]interface{}{"Exif", 0x9202},
|
||||||
[2]interface{} { "Exif", 0x9204 },
|
[2]interface{}{"Exif", 0x9204},
|
||||||
[2]interface{} { "Exif", 0x9207 },
|
[2]interface{}{"Exif", 0x9207},
|
||||||
[2]interface{} { "Exif", 0x9209 },
|
[2]interface{}{"Exif", 0x9209},
|
||||||
[2]interface{} { "Exif", 0x920a },
|
[2]interface{}{"Exif", 0x920a},
|
||||||
[2]interface{} { "Exif", 0x927c },
|
[2]interface{}{"Exif", 0x927c},
|
||||||
[2]interface{} { "Exif", 0x9286 },
|
[2]interface{}{"Exif", 0x9286},
|
||||||
[2]interface{} { "Exif", 0x9290 },
|
[2]interface{}{"Exif", 0x9290},
|
||||||
[2]interface{} { "Exif", 0x9291 },
|
[2]interface{}{"Exif", 0x9291},
|
||||||
[2]interface{} { "Exif", 0x9292 },
|
[2]interface{}{"Exif", 0x9292},
|
||||||
[2]interface{} { "Exif", 0xa000 },
|
[2]interface{}{"Exif", 0xa000},
|
||||||
[2]interface{} { "Exif", 0xa001 },
|
[2]interface{}{"Exif", 0xa001},
|
||||||
[2]interface{} { "Exif", 0xa002 },
|
[2]interface{}{"Exif", 0xa002},
|
||||||
[2]interface{} { "Exif", 0xa003 },
|
[2]interface{}{"Exif", 0xa003},
|
||||||
[2]interface{} { "Iop", 0x0001 },
|
[2]interface{}{"Iop", 0x0001},
|
||||||
[2]interface{} { "Iop", 0x0002 },
|
[2]interface{}{"Iop", 0x0002},
|
||||||
[2]interface{} { "Exif", 0xa20e },
|
[2]interface{}{"Exif", 0xa20e},
|
||||||
[2]interface{} { "Exif", 0xa20f },
|
[2]interface{}{"Exif", 0xa20f},
|
||||||
[2]interface{} { "Exif", 0xa210 },
|
[2]interface{}{"Exif", 0xa210},
|
||||||
[2]interface{} { "Exif", 0xa401 },
|
[2]interface{}{"Exif", 0xa401},
|
||||||
[2]interface{} { "Exif", 0xa402 },
|
[2]interface{}{"Exif", 0xa402},
|
||||||
[2]interface{} { "Exif", 0xa403 },
|
[2]interface{}{"Exif", 0xa403},
|
||||||
[2]interface{} { "Exif", 0xa406 },
|
[2]interface{}{"Exif", 0xa406},
|
||||||
[2]interface{} { "Exif", 0xa430 },
|
[2]interface{}{"Exif", 0xa430},
|
||||||
[2]interface{} { "Exif", 0xa431 },
|
[2]interface{}{"Exif", 0xa431},
|
||||||
[2]interface{} { "Exif", 0xa432 },
|
[2]interface{}{"Exif", 0xa432},
|
||||||
[2]interface{} { "Exif", 0xa434 },
|
[2]interface{}{"Exif", 0xa434},
|
||||||
[2]interface{} { "Exif", 0xa435 },
|
[2]interface{}{"Exif", 0xa435},
|
||||||
[2]interface{} { "GPSInfo", 0x0000 },
|
[2]interface{}{"GPSInfo", 0x0000},
|
||||||
[2]interface{} { "IFD", 0x010f },
|
[2]interface{}{"IFD", 0x010f},
|
||||||
[2]interface{} { "IFD", 0x0110 },
|
[2]interface{}{"IFD", 0x0110},
|
||||||
[2]interface{} { "IFD", 0x0112 },
|
[2]interface{}{"IFD", 0x0112},
|
||||||
[2]interface{} { "IFD", 0x011a },
|
[2]interface{}{"IFD", 0x011a},
|
||||||
[2]interface{} { "IFD", 0x011b },
|
[2]interface{}{"IFD", 0x011b},
|
||||||
[2]interface{} { "IFD", 0x0128 },
|
[2]interface{}{"IFD", 0x0128},
|
||||||
[2]interface{} { "IFD", 0x0132 },
|
[2]interface{}{"IFD", 0x0132},
|
||||||
[2]interface{} { "IFD", 0x013b },
|
[2]interface{}{"IFD", 0x013b},
|
||||||
[2]interface{} { "IFD", 0x0213 },
|
[2]interface{}{"IFD", 0x0213},
|
||||||
[2]interface{} { "IFD", 0x8298 },
|
[2]interface{}{"IFD", 0x8298},
|
||||||
[2]interface{} { "Exif", 0x829a },
|
[2]interface{}{"Exif", 0x829a},
|
||||||
[2]interface{} { "Exif", 0x829d },
|
[2]interface{}{"Exif", 0x829d},
|
||||||
[2]interface{} { "Exif", 0x8822 },
|
[2]interface{}{"Exif", 0x8822},
|
||||||
[2]interface{} { "Exif", 0x8827 },
|
[2]interface{}{"Exif", 0x8827},
|
||||||
[2]interface{} { "Exif", 0x8830 },
|
[2]interface{}{"Exif", 0x8830},
|
||||||
[2]interface{} { "Exif", 0x8832 },
|
[2]interface{}{"Exif", 0x8832},
|
||||||
[2]interface{} { "Exif", 0x9000 },
|
[2]interface{}{"Exif", 0x9000},
|
||||||
[2]interface{} { "Exif", 0x9003 },
|
[2]interface{}{"Exif", 0x9003},
|
||||||
[2]interface{} { "Exif", 0x9004 },
|
[2]interface{}{"Exif", 0x9004},
|
||||||
[2]interface{} { "Exif", 0x9101 },
|
[2]interface{}{"Exif", 0x9101},
|
||||||
[2]interface{} { "Exif", 0x9201 },
|
[2]interface{}{"Exif", 0x9201},
|
||||||
[2]interface{} { "Exif", 0x9202 },
|
[2]interface{}{"Exif", 0x9202},
|
||||||
[2]interface{} { "Exif", 0x9204 },
|
[2]interface{}{"Exif", 0x9204},
|
||||||
[2]interface{} { "Exif", 0x9207 },
|
[2]interface{}{"Exif", 0x9207},
|
||||||
[2]interface{} { "Exif", 0x9209 },
|
[2]interface{}{"Exif", 0x9209},
|
||||||
[2]interface{} { "Exif", 0x920a },
|
[2]interface{}{"Exif", 0x920a},
|
||||||
[2]interface{} { "Exif", 0x927c },
|
[2]interface{}{"Exif", 0x927c},
|
||||||
[2]interface{} { "Exif", 0x9286 },
|
[2]interface{}{"Exif", 0x9286},
|
||||||
[2]interface{} { "Exif", 0x9290 },
|
[2]interface{}{"Exif", 0x9290},
|
||||||
[2]interface{} { "Exif", 0x9291 },
|
[2]interface{}{"Exif", 0x9291},
|
||||||
[2]interface{} { "Exif", 0x9292 },
|
[2]interface{}{"Exif", 0x9292},
|
||||||
[2]interface{} { "Exif", 0xa000 },
|
[2]interface{}{"Exif", 0xa000},
|
||||||
[2]interface{} { "Exif", 0xa001 },
|
[2]interface{}{"Exif", 0xa001},
|
||||||
[2]interface{} { "Exif", 0xa002 },
|
[2]interface{}{"Exif", 0xa002},
|
||||||
[2]interface{} { "Exif", 0xa003 },
|
[2]interface{}{"Exif", 0xa003},
|
||||||
[2]interface{} { "Iop", 0x0001 },
|
[2]interface{}{"Iop", 0x0001},
|
||||||
[2]interface{} { "Iop", 0x0002 },
|
[2]interface{}{"Iop", 0x0002},
|
||||||
[2]interface{} { "Exif", 0xa20e },
|
[2]interface{}{"Exif", 0xa20e},
|
||||||
[2]interface{} { "Exif", 0xa20f },
|
[2]interface{}{"Exif", 0xa20f},
|
||||||
[2]interface{} { "Exif", 0xa210 },
|
[2]interface{}{"Exif", 0xa210},
|
||||||
[2]interface{} { "Exif", 0xa401 },
|
[2]interface{}{"Exif", 0xa401},
|
||||||
[2]interface{} { "Exif", 0xa402 },
|
[2]interface{}{"Exif", 0xa402},
|
||||||
[2]interface{} { "Exif", 0xa403 },
|
[2]interface{}{"Exif", 0xa403},
|
||||||
[2]interface{} { "Exif", 0xa406 },
|
[2]interface{}{"Exif", 0xa406},
|
||||||
[2]interface{} { "Exif", 0xa430 },
|
[2]interface{}{"Exif", 0xa430},
|
||||||
[2]interface{} { "Exif", 0xa431 },
|
[2]interface{}{"Exif", 0xa431},
|
||||||
[2]interface{} { "Exif", 0xa432 },
|
[2]interface{}{"Exif", 0xa432},
|
||||||
[2]interface{} { "Exif", 0xa434 },
|
[2]interface{}{"Exif", 0xa434},
|
||||||
[2]interface{} { "Exif", 0xa435 },
|
[2]interface{}{"Exif", 0xa435},
|
||||||
[2]interface{} { "GPSInfo", 0x0000 },
|
[2]interface{}{"GPSInfo", 0x0000},
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.DeepEqual(collected, expected) != true {
|
if reflect.DeepEqual(collected, expected) != true {
|
||||||
@ -487,7 +508,9 @@ func ExampleIfd_EnumerateTagsRecursively() {
|
|||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
cb := func(ifd *Ifd, ite *IfdTagEntry) error {
|
cb := func(ifd *Ifd, ite *IfdTagEntry) error {
|
||||||
@ -503,14 +526,15 @@ func ExampleIfd_EnumerateTagsRecursively() {
|
|||||||
// Output:
|
// Output:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func ExampleIfd_GpsInfo() {
|
func ExampleIfd_GpsInfo() {
|
||||||
filepath := path.Join(assetsPath, "gps.jpg")
|
filepath := path.Join(assetsPath, "gps.jpg")
|
||||||
|
|
||||||
rawExif, err := SearchFileAndExtractExif(filepath)
|
rawExif, err := SearchFileAndExtractExif(filepath)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
_, index, err := Collect(rawExif)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
_, index, err := Collect(ti, rawExif)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
ifd, err := index.RootIfd.ChildWithIfdIdentity(GpsIi)
|
ifd, err := index.RootIfd.ChildWithIfdIdentity(GpsIi)
|
||||||
|
12
tags.go
12
tags.go
@ -37,8 +37,6 @@ var (
|
|||||||
// blob (not a slice of longs).
|
// blob (not a slice of longs).
|
||||||
ThumbnailOffsetTagId: struct{}{},
|
ThumbnailOffsetTagId: struct{}{},
|
||||||
}
|
}
|
||||||
|
|
||||||
tagIndex *TagIndex
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -64,15 +62,15 @@ type IndexedTag struct {
|
|||||||
Type uint16
|
Type uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it IndexedTag) String() string {
|
func (it *IndexedTag) String() string {
|
||||||
return fmt.Sprintf("TAG<ID=(0x%04x) NAME=[%s] IFD=[%s]>", it.Id, it.Name, it.Ifd)
|
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 {
|
func (it *IndexedTag) IsName(ifd, name string) bool {
|
||||||
return it.Name == name && it.Ifd == ifd
|
return it.Name == name && it.Ifd == ifd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it IndexedTag) Is(ifd string, id uint16) bool {
|
func (it *IndexedTag) Is(ifd string, id uint16) bool {
|
||||||
return it.Id == id && it.Ifd == ifd
|
return it.Id == id && it.Ifd == ifd
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +316,3 @@ func IfdId(parentIfdName, ifdName string) (ii IfdIdentity, id int) {
|
|||||||
|
|
||||||
return ii, id
|
return ii, id
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
tagIndex = NewTagIndex()
|
|
||||||
}
|
|
||||||
|
@ -14,7 +14,9 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestGet(t *testing.T) {
|
func TestGet(t *testing.T) {
|
||||||
it, err := tagIndex.Get(RootIi, 0x10f)
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
it, err := ti.Get(RootIi, 0x10f)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if it.Is("IFD", 0x10f) == false || it.IsName("IFD", "Make") == false {
|
if it.Is("IFD", 0x10f) == false || it.IsName("IFD", "Make") == false {
|
||||||
@ -23,7 +25,9 @@ func TestGet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetWithName(t *testing.T) {
|
func TestGetWithName(t *testing.T) {
|
||||||
it, err := tagIndex.GetWithName(RootIi, "Make")
|
ti := NewTagIndex()
|
||||||
|
|
||||||
|
it, err := ti.GetWithName(RootIi, "Make")
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
if it.Is("IFD", 0x10f) == false || it.Is("IFD", 0x10f) == false {
|
if it.Is("IFD", 0x10f) == false || it.Is("IFD", 0x10f) == false {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package exif
|
package exif
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
)
|
)
|
||||||
@ -11,7 +11,6 @@ func TestUndefinedValue_ExifVersion(t *testing.T) {
|
|||||||
byteOrder := TestDefaultByteOrder
|
byteOrder := TestDefaultByteOrder
|
||||||
ii := ExifIi
|
ii := ExifIi
|
||||||
|
|
||||||
|
|
||||||
// Create our unknown-type tag's value using the fact that we know it's a
|
// Create our unknown-type tag's value using the fact that we know it's a
|
||||||
// non-null-terminated string.
|
// non-null-terminated string.
|
||||||
|
|
||||||
@ -23,7 +22,6 @@ func TestUndefinedValue_ExifVersion(t *testing.T) {
|
|||||||
ed, err := ve.EncodeWithType(tt, valueString)
|
ed, err := ve.EncodeWithType(tt, valueString)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// Create the tag using the official "unknown" type now that we already
|
// Create the tag using the official "unknown" type now that we already
|
||||||
// have the bytes.
|
// have the bytes.
|
||||||
|
|
||||||
@ -36,11 +34,12 @@ func TestUndefinedValue_ExifVersion(t *testing.T) {
|
|||||||
value: encodedValue,
|
value: encodedValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Stage the build.
|
// Stage the build.
|
||||||
|
|
||||||
|
ti := NewTagIndex()
|
||||||
|
|
||||||
ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
ib := NewIfdBuilder(ii, byteOrder)
|
ib := NewIfdBuilder(ti, ii, byteOrder)
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
bw := NewByteWriter(b, byteOrder)
|
bw := NewByteWriter(b, byteOrder)
|
||||||
@ -48,7 +47,6 @@ func TestUndefinedValue_ExifVersion(t *testing.T) {
|
|||||||
addressableOffset := uint32(0x1234)
|
addressableOffset := uint32(0x1234)
|
||||||
ida := newIfdDataAllocator(addressableOffset)
|
ida := newIfdDataAllocator(addressableOffset)
|
||||||
|
|
||||||
|
|
||||||
// Encode.
|
// Encode.
|
||||||
|
|
||||||
_, err = ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
|
_, err = ibe.encodeTagToBytes(ib, bt, bw, ida, uint32(0))
|
||||||
@ -71,7 +69,7 @@ func TestUndefinedValue_ExifVersion(t *testing.T) {
|
|||||||
t.Fatalf("Tag type not correct: (%d)", ite.TagType)
|
t.Fatalf("Tag type not correct: (%d)", ite.TagType)
|
||||||
} else if ite.UnitCount != (uint32(len(valueString))) {
|
} else if ite.UnitCount != (uint32(len(valueString))) {
|
||||||
t.Fatalf("Tag unit-count not correct: (%d)", ite.UnitCount)
|
t.Fatalf("Tag unit-count not correct: (%d)", ite.UnitCount)
|
||||||
} else if bytes.Compare(ite.RawValueOffset, []byte { '0', '2', '3', '0' }) != 0 {
|
} else if bytes.Compare(ite.RawValueOffset, []byte{'0', '2', '3', '0'}) != 0 {
|
||||||
t.Fatalf("Tag's value (as raw bytes) is not correct: [%x]", ite.RawValueOffset)
|
t.Fatalf("Tag's value (as raw bytes) is not correct: [%x]", ite.RawValueOffset)
|
||||||
} else if ite.ChildIfdName != "" {
|
} else if ite.ChildIfdName != "" {
|
||||||
t.Fatalf("Tag's IFD-name should be empty: [%s]", ite.ChildIfdName)
|
t.Fatalf("Tag's IFD-name should be empty: [%s]", ite.ChildIfdName)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user