mirror of
https://github.com/dsoprea/go-exif.git
synced 2025-05-31 11:41:57 +00:00
ifd_builder_encode: Bugfixed next-IFD offsets.
- Affected sibling IFDs.
This commit is contained in:
parent
887842e85a
commit
6c71ccf651
@ -2,7 +2,6 @@ package exif
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
// "fmt"
|
|
||||||
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
@ -288,15 +287,18 @@ func (ibe *IfdByteEncoder) encodeIfdToBytes(ib *IfdBuilder, ifdAddressableOffset
|
|||||||
// N the link from this IFD to the next IFD that will be written in the
|
// N the link from this IFD to the next IFD that will be written in the
|
||||||
// next cycle.
|
// next cycle.
|
||||||
if setNextIb == true {
|
if setNextIb == true {
|
||||||
nextIfdOffsetToWrite += dataSize
|
// Write address of next IFD in chain. This will be the original
|
||||||
// fmt.Printf("SETTING NEXT-IFD FOR %s TO: (0x%04x)\n", ib.ii, nextIfdOffsetToWrite)
|
// allocation offset plus the size of everything we have allocated for
|
||||||
} else {
|
// this IFD and its child-IFDs.
|
||||||
nextIfdOffsetToWrite = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write address of next IFD in chain.
|
offset := ifdAddressableOffset + dataSize
|
||||||
err = bw.WriteUint32(nextIfdOffsetToWrite)
|
|
||||||
log.PanicIf(err)
|
err := bw.WriteUint32(offset)
|
||||||
|
log.PanicIf(err)
|
||||||
|
} else {
|
||||||
|
err := bw.WriteUint32(0)
|
||||||
|
log.PanicIf(err)
|
||||||
|
}
|
||||||
|
|
||||||
_, err = b.Write(dataBytes)
|
_, err = b.Write(dataBytes)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
@ -336,8 +338,6 @@ func (ibe *IfdByteEncoder) encodeAndAttachIfd(ib *IfdBuilder, ifdAddressableOffs
|
|||||||
for thisIb := ib; thisIb != nil; thisIb = thisIb.nextIb {
|
for thisIb := ib; thisIb != nil; thisIb = thisIb.nextIb {
|
||||||
// Do a dry-run in order to pre-determine its size requirement.
|
// Do a dry-run in order to pre-determine its size requirement.
|
||||||
|
|
||||||
// fmt.Printf("BUILDING IFD: %s ifdAddressableOffset=(0x%04x)\n", ib.ii, ifdAddressableOffset)
|
|
||||||
|
|
||||||
_, tableSize, allocatedDataSize, _, err := ibe.encodeIfdToBytes(ib, ifdAddressableOffset, 0, false)
|
_, tableSize, allocatedDataSize, _, err := ibe.encodeIfdToBytes(ib, ifdAddressableOffset, 0, false)
|
||||||
log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"reflect"
|
"reflect"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/dsoprea/go-logging"
|
"github.com/dsoprea/go-logging"
|
||||||
)
|
)
|
||||||
@ -793,18 +794,18 @@ func Test_IfdByteEncoder_EncodeToExif_WithChildAndSibling(t *testing.T) {
|
|||||||
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(RootIi, TestDefaultByteOrder)
|
||||||
|
|
||||||
// err = nextIb.AddFromConfig(0x0101, []uint32 { 0x11223344 })
|
err = nextIb.AddFromConfig(0x0101, []uint32 { 0x11223344 })
|
||||||
// log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// err = nextIb.AddFromConfig(0x0102, []uint16 { 0x5566 })
|
err = nextIb.AddFromConfig(0x0102, []uint16 { 0x5566 })
|
||||||
// log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// ib.SetNextIb(nextIb)
|
ib.SetNextIb(nextIb)
|
||||||
|
|
||||||
|
|
||||||
// Encode.
|
// Encode.
|
||||||
@ -824,184 +825,103 @@ func Test_IfdByteEncoder_EncodeToExif_WithChildAndSibling(t *testing.T) {
|
|||||||
|
|
||||||
tagsDump := index.RootIfd.DumpTree()
|
tagsDump := index.RootIfd.DumpTree()
|
||||||
|
|
||||||
expected := []string {
|
actual := strings.Join(tagsDump, "\n")
|
||||||
"[ROOT]->[IFD] (0x000b)",
|
|
||||||
"[ROOT]->[IFD] (0x00ff)",
|
|
||||||
"[ROOT]->[IFD] (0x8769)",
|
|
||||||
"[IFD]->[Exif] (0x8827)",
|
|
||||||
"[IFD]->[Exif] (0x8833)",
|
|
||||||
"[ROOT]->[IFD] (0x0100)",
|
|
||||||
"[ROOT]->[IFD] (0x8825)",
|
|
||||||
"[IFD]->[GPSInfo] (0x0005)",
|
|
||||||
"[ROOT]->[IFD] (0x013e)",
|
|
||||||
}
|
|
||||||
|
|
||||||
if reflect.DeepEqual(tagsDump, expected) != true {
|
expected :=
|
||||||
|
`> IFD [ROOT]->[IFD]:(0) TOP
|
||||||
|
- (0x000b)
|
||||||
|
- (0x00ff)
|
||||||
|
- (0x8769)
|
||||||
|
> IFD [IFD]->[Exif]:(0) TOP
|
||||||
|
- (0x8827)
|
||||||
|
- (0x8833)
|
||||||
|
< IFD [IFD]->[Exif]:(0) BOTTOM
|
||||||
|
- (0x0100)
|
||||||
|
- (0x8825)
|
||||||
|
> IFD [IFD]->[GPSInfo]:(0) TOP
|
||||||
|
- (0x0005)
|
||||||
|
< IFD [IFD]->[GPSInfo]:(0) BOTTOM
|
||||||
|
- (0x013e)
|
||||||
|
< IFD [ROOT]->[IFD]:(0) BOTTOM
|
||||||
|
* LINKING TO SIBLING IFD [IFD]:(1)
|
||||||
|
> IFD [ROOT]->[IFD]:(1) TOP
|
||||||
|
- (0x8827)
|
||||||
|
- (0x8833)
|
||||||
|
< IFD [ROOT]->[IFD]:(1) BOTTOM`
|
||||||
|
|
||||||
|
if actual != expected {
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
|
|
||||||
fmt.Printf("Actual:\n")
|
fmt.Printf("Actual:\n")
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("%s\n", actual)
|
||||||
for i, line := range tagsDump {
|
|
||||||
fmt.Printf("%d: %s\n", i, line)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
|
|
||||||
fmt.Printf("Expected:\n")
|
fmt.Printf("Expected:\n")
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
|
fmt.Printf("%s\n", expected)
|
||||||
for i, line := range expected {
|
|
||||||
fmt.Printf("%d: %s\n", i, line)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
|
|
||||||
t.Fatalf("IFD hierarchy not correct.")
|
t.Fatalf("IFD hierarchy not correct.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// func ExampleIfdByteEncoder_EncodeToExif() {
|
func ExampleIfdByteEncoder_EncodeToExif() {
|
||||||
// // Construct an IFD.
|
// Construct an IFD.
|
||||||
|
|
||||||
// ib := NewIfdBuilder(RootIi, EncodeDefaultByteOrder)
|
ib := NewIfdBuilder(RootIi, EncodeDefaultByteOrder)
|
||||||
|
|
||||||
// err := ib.AddFromConfigWithName("ProcessingSoftware", "asciivalue")
|
err := ib.AddFromConfigWithName("ProcessingSoftware", "asciivalue")
|
||||||
// log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// err = ib.AddFromConfigWithName("DotRange", []uint8 { 0x11 })
|
err = ib.AddFromConfigWithName("DotRange", []uint8 { 0x11 })
|
||||||
// log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// err = ib.AddFromConfigWithName("SubfileType", []uint16 { 0x2233 })
|
err = ib.AddFromConfigWithName("SubfileType", []uint16 { 0x2233 })
|
||||||
// log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// err = ib.AddFromConfigWithName("ImageWidth", []uint32 { 0x44556677 })
|
err = ib.AddFromConfigWithName("ImageWidth", []uint32 { 0x44556677 })
|
||||||
// log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// err = ib.AddFromConfigWithName("WhitePoint", []Rational { { Numerator: 0x11112222, Denominator: 0x33334444 } })
|
err = ib.AddFromConfigWithName("WhitePoint", []Rational { { Numerator: 0x11112222, Denominator: 0x33334444 } })
|
||||||
// log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// err = ib.AddFromConfigWithName("ShutterSpeedValue", []SignedRational { { Numerator: 0x11112222, Denominator: 0x33334444 } })
|
err = ib.AddFromConfigWithName("ShutterSpeedValue", []SignedRational { { Numerator: 0x11112222, Denominator: 0x33334444 } })
|
||||||
// log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
|
|
||||||
// // Encode it.
|
// Encode it.
|
||||||
|
|
||||||
// ibe := NewIfdByteEncoder()
|
ibe := NewIfdByteEncoder()
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
||||||
// e := NewExif()
|
e := NewExif()
|
||||||
|
|
||||||
// _, index, err := e.Collect(exifData)
|
_, index, err := e.Collect(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
|
||||||
// // resolved (where position 0x0 will correlate with offset 0x0).
|
// resolved (where position 0x0 will correlate with offset 0x0).
|
||||||
// addressableData := exifData[ExifAddressableAreaStart:]
|
addressableData := exifData[ExifAddressableAreaStart:]
|
||||||
|
|
||||||
// for i, e := range index.RootIfd.Entries {
|
for i, e := range index.RootIfd.Entries {
|
||||||
// value, err := e.Value(addressableData, EncodeDefaultByteOrder)
|
value, err := e.Value(addressableData, EncodeDefaultByteOrder)
|
||||||
// log.PanicIf(err)
|
log.PanicIf(err)
|
||||||
|
|
||||||
// fmt.Printf("%d: %s [%v]\n", i, e, value)
|
fmt.Printf("%d: %s [%v]\n", i, e, value)
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // Output:
|
// Output:
|
||||||
// //
|
//
|
||||||
// // 0: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x0b) TAG-TYPE=[ASCII] UNIT-COUNT=(11)> [asciivalue]
|
// 0: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x0b) TAG-TYPE=[ASCII] UNIT-COUNT=(11)> [asciivalue]
|
||||||
// // 1: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x150) TAG-TYPE=[BYTE] UNIT-COUNT=(1)> [[17]]
|
// 1: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x150) TAG-TYPE=[BYTE] UNIT-COUNT=(1)> [[17]]
|
||||||
// // 2: IfdTagEntry<TAG-IFD=[] TAG-ID=(0xff) TAG-TYPE=[SHORT] UNIT-COUNT=(1)> [[8755]]
|
// 2: IfdTagEntry<TAG-IFD=[] TAG-ID=(0xff) TAG-TYPE=[SHORT] UNIT-COUNT=(1)> [[8755]]
|
||||||
// // 3: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x100) TAG-TYPE=[LONG] UNIT-COUNT=(1)> [[1146447479]]
|
// 3: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x100) TAG-TYPE=[LONG] UNIT-COUNT=(1)> [[1146447479]]
|
||||||
// // 4: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x13e) TAG-TYPE=[RATIONAL] UNIT-COUNT=(1)> [[{286335522 858997828}]]
|
// 4: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x13e) TAG-TYPE=[RATIONAL] UNIT-COUNT=(1)> [[{286335522 858997828}]]
|
||||||
// // 5: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x9201) TAG-TYPE=[SRATIONAL] UNIT-COUNT=(1)> [[{286335522 858997828}]]
|
// 5: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x9201) TAG-TYPE=[SRATIONAL] UNIT-COUNT=(1)> [[{286335522 858997828}]]
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// func ExampleIfdByteEncoder_EncodeToExif_WithChild() {
|
|
||||||
// // Construct an IFD.
|
|
||||||
|
|
||||||
// ib := NewIfdBuilder(RootIi, EncodeDefaultByteOrder)
|
|
||||||
|
|
||||||
// err := ib.AddFromConfigWithName("ProcessingSoftware", "asciivalue")
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
// err = ib.AddFromConfigWithName("DotRange", []uint8 { 0x11 })
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
// err = ib.AddFromConfigWithName("SubfileType", []uint16 { 0x2233 })
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
|
|
||||||
// // Add a child IB right in the middle.
|
|
||||||
|
|
||||||
// childIb := NewIfdBuilder(ExifIi, EncodeDefaultByteOrder)
|
|
||||||
|
|
||||||
// err = childIb.AddFromConfigWithName("ISOSpeedRatings", []uint16 { 0x1122 })
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
// err = childIb.AddFromConfigWithName("ISOSpeed", []uint32 { 0x33445566 })
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
// err = ib.AddChildIb(childIb)
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
|
|
||||||
// err = ib.AddFromConfigWithName("ImageWidth", []uint32 { 0x44556677 })
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
// err = ib.AddFromConfigWithName("WhitePoint", []Rational { { Numerator: 0x11112222, Denominator: 0x33334444 } })
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
// err = ib.AddFromConfigWithName("ShutterSpeedValue", []SignedRational { { Numerator: 0x11112222, Denominator: 0x33334444 } })
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
|
|
||||||
// // Encode it.
|
|
||||||
|
|
||||||
// ibe := NewIfdByteEncoder()
|
|
||||||
|
|
||||||
// exifData, err := ibe.EncodeToExif(ib)
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
|
|
||||||
// // Parse it so we can see it.
|
|
||||||
|
|
||||||
// e := NewExif()
|
|
||||||
|
|
||||||
// _, index, err := e.Collect(exifData)
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
// // addressableData is the byte-slice where the allocated data can be
|
|
||||||
// // resolved (where position 0x0 will correlate with offset 0x0).
|
|
||||||
// addressableData := exifData[ExifAddressableAreaStart:]
|
|
||||||
|
|
||||||
// for i, e := range index.RootIfd.Entries {
|
|
||||||
// value, err := e.Value(addressableData, EncodeDefaultByteOrder)
|
|
||||||
// log.PanicIf(err)
|
|
||||||
|
|
||||||
// fmt.Printf("%d: %s %v\n", i, e, value)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Output:
|
|
||||||
// //
|
|
||||||
// // 0: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x0b) TAG-TYPE=[ASCII] UNIT-COUNT=(11)> asciivalue
|
|
||||||
// // 1: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x150) TAG-TYPE=[BYTE] UNIT-COUNT=(1)> [17]
|
|
||||||
// // 2: IfdTagEntry<TAG-IFD=[] TAG-ID=(0xff) TAG-TYPE=[SHORT] UNIT-COUNT=(1)> [8755]
|
|
||||||
// // 3: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x100) TAG-TYPE=[LONG] UNIT-COUNT=(1)> [1146447479]
|
|
||||||
// // 4: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x13e) TAG-TYPE=[RATIONAL] UNIT-COUNT=(1)> [{286335522 858997828}]
|
|
||||||
// // 5: IfdTagEntry<TAG-IFD=[] TAG-ID=(0x9201) TAG-TYPE=[SRATIONAL] UNIT-COUNT=(1)> [{286335522 858997828}]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO(dustin): !! Write test with both chained and child IFDs
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user