...
1 package exifundefined
2
3 import (
4 "bytes"
5 "fmt"
6
7 "encoding/binary"
8
9 "github.com/dsoprea/go-logging"
10
11 "github.com/dsoprea/go-exif/v3/common"
12 )
13
14 type Tag8828Oecf struct {
15 Columns uint16
16 Rows uint16
17 ColumnNames []string
18 Values []exifcommon.SignedRational
19 }
20
21 func (oecf Tag8828Oecf) String() string {
22 return fmt.Sprintf("Tag8828Oecf<COLUMNS=(%d) ROWS=(%d)>", oecf.Columns, oecf.Rows)
23 }
24
25 func (oecf Tag8828Oecf) EncoderName() string {
26 return "Codec8828Oecf"
27 }
28
29 type Codec8828Oecf struct {
30 }
31
32 func (Codec8828Oecf) Encode(value interface{}, byteOrder binary.ByteOrder) (encoded []byte, unitCount uint32, err error) {
33 defer func() {
34 if state := recover(); state != nil {
35 err = log.Wrap(state.(error))
36 }
37 }()
38
39
40
41 oecf, ok := value.(Tag8828Oecf)
42 if ok == false {
43 log.Panicf("can only encode a Tag8828Oecf")
44 }
45
46 b := new(bytes.Buffer)
47
48 err = binary.Write(b, byteOrder, oecf.Columns)
49 log.PanicIf(err)
50
51 err = binary.Write(b, byteOrder, oecf.Rows)
52 log.PanicIf(err)
53
54 for _, name := range oecf.ColumnNames {
55 _, err := b.Write([]byte(name))
56 log.PanicIf(err)
57
58 _, err = b.Write([]byte{0})
59 log.PanicIf(err)
60 }
61
62 ve := exifcommon.NewValueEncoder(byteOrder)
63
64 ed, err := ve.Encode(oecf.Values)
65 log.PanicIf(err)
66
67 _, err = b.Write(ed.Encoded)
68 log.PanicIf(err)
69
70 return b.Bytes(), uint32(b.Len()), nil
71 }
72
73 func (Codec8828Oecf) Decode(valueContext *exifcommon.ValueContext) (value EncodeableValue, err error) {
74 defer func() {
75 if state := recover(); state != nil {
76 err = log.Wrap(state.(error))
77 }
78 }()
79
80
81
82 valueContext.SetUndefinedValueType(exifcommon.TypeByte)
83
84 valueBytes, err := valueContext.ReadBytes()
85 log.PanicIf(err)
86
87 oecf := Tag8828Oecf{}
88
89 oecf.Columns = valueContext.ByteOrder().Uint16(valueBytes[0:2])
90 oecf.Rows = valueContext.ByteOrder().Uint16(valueBytes[2:4])
91
92 columnNames := make([]string, oecf.Columns)
93
94
95 startAt := 4
96
97
98 offset := startAt
99
100 currentColumnNumber := uint16(0)
101
102 for currentColumnNumber < oecf.Columns {
103 if valueBytes[offset] == 0 {
104 columnName := string(valueBytes[startAt:offset])
105 if len(columnName) == 0 {
106 log.Panicf("SFR column (%d) has zero length", currentColumnNumber)
107 }
108
109 columnNames[currentColumnNumber] = columnName
110 currentColumnNumber++
111
112 offset++
113 startAt = offset
114 continue
115 }
116
117 offset++
118 }
119
120 oecf.ColumnNames = columnNames
121
122 rawRationalBytes := valueBytes[offset:]
123
124 rationalSize := exifcommon.TypeSignedRational.Size()
125 if len(rawRationalBytes)%rationalSize > 0 {
126 log.Panicf("OECF signed-rationals not aligned: (%d) %% (%d) > 0", len(rawRationalBytes), rationalSize)
127 }
128
129 rationalCount := len(rawRationalBytes) / rationalSize
130
131 parser := new(exifcommon.Parser)
132
133 byteOrder := valueContext.ByteOrder()
134
135 items, err := parser.ParseSignedRationals(rawRationalBytes, uint32(rationalCount), byteOrder)
136 log.PanicIf(err)
137
138 oecf.Values = items
139
140 return oecf, nil
141 }
142
143 func init() {
144 registerDecoder(
145 exifcommon.IfdExifStandardIfdIdentity.UnindexedString(),
146 0x8828,
147 Codec8828Oecf{})
148 }
149
View as plain text