...
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 TagA20CSpatialFrequencyResponse struct {
15 Columns uint16
16 Rows uint16
17 ColumnNames []string
18 Values []exifcommon.Rational
19 }
20
21 func (TagA20CSpatialFrequencyResponse) EncoderName() string {
22 return "CodecA20CSpatialFrequencyResponse"
23 }
24
25 func (sfr TagA20CSpatialFrequencyResponse) String() string {
26 return fmt.Sprintf("CodecA20CSpatialFrequencyResponse<COLUMNS=(%d) ROWS=(%d)>", sfr.Columns, sfr.Rows)
27 }
28
29 type CodecA20CSpatialFrequencyResponse struct {
30 }
31
32 func (CodecA20CSpatialFrequencyResponse) 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 sfr, ok := value.(TagA20CSpatialFrequencyResponse)
42 if ok == false {
43 log.Panicf("can only encode a TagA20CSpatialFrequencyResponse")
44 }
45
46 b := new(bytes.Buffer)
47
48 err = binary.Write(b, byteOrder, sfr.Columns)
49 log.PanicIf(err)
50
51 err = binary.Write(b, byteOrder, sfr.Rows)
52 log.PanicIf(err)
53
54
55
56 for _, name := range sfr.ColumnNames {
57 _, err := b.WriteString(name)
58 log.PanicIf(err)
59
60 err = b.WriteByte(0)
61 log.PanicIf(err)
62 }
63
64
65
66 ve := exifcommon.NewValueEncoder(byteOrder)
67
68 ed, err := ve.Encode(sfr.Values)
69 log.PanicIf(err)
70
71 _, err = b.Write(ed.Encoded)
72 log.PanicIf(err)
73
74 encoded = b.Bytes()
75
76
77
78 return encoded, uint32(len(encoded)), nil
79 }
80
81 func (CodecA20CSpatialFrequencyResponse) Decode(valueContext *exifcommon.ValueContext) (value EncodeableValue, err error) {
82 defer func() {
83 if state := recover(); state != nil {
84 err = log.Wrap(state.(error))
85 }
86 }()
87
88
89
90 byteOrder := valueContext.ByteOrder()
91
92 valueContext.SetUndefinedValueType(exifcommon.TypeByte)
93
94 valueBytes, err := valueContext.ReadBytes()
95 log.PanicIf(err)
96
97 sfr := TagA20CSpatialFrequencyResponse{}
98
99 sfr.Columns = byteOrder.Uint16(valueBytes[0:2])
100 sfr.Rows = byteOrder.Uint16(valueBytes[2:4])
101
102 columnNames := make([]string, sfr.Columns)
103
104
105 startAt := 4
106
107
108 offset := 4
109
110 currentColumnNumber := uint16(0)
111
112 for currentColumnNumber < sfr.Columns {
113 if valueBytes[offset] == 0 {
114 columnName := string(valueBytes[startAt:offset])
115 if len(columnName) == 0 {
116 log.Panicf("SFR column (%d) has zero length", currentColumnNumber)
117 }
118
119 columnNames[currentColumnNumber] = columnName
120 currentColumnNumber++
121
122 offset++
123 startAt = offset
124 continue
125 }
126
127 offset++
128 }
129
130 sfr.ColumnNames = columnNames
131
132 rawRationalBytes := valueBytes[offset:]
133
134 rationalSize := exifcommon.TypeRational.Size()
135 if len(rawRationalBytes)%rationalSize > 0 {
136 log.Panicf("SFR rationals not aligned: (%d) %% (%d) > 0", len(rawRationalBytes), rationalSize)
137 }
138
139 rationalCount := len(rawRationalBytes) / rationalSize
140
141 parser := new(exifcommon.Parser)
142
143 items, err := parser.ParseRationals(rawRationalBytes, uint32(rationalCount), byteOrder)
144 log.PanicIf(err)
145
146 sfr.Values = items
147
148 return sfr, nil
149 }
150
151 func init() {
152 registerEncoder(
153 TagA20CSpatialFrequencyResponse{},
154 CodecA20CSpatialFrequencyResponse{})
155
156 registerDecoder(
157 exifcommon.IfdExifStandardIfdIdentity.UnindexedString(),
158 0xa20c,
159 CodecA20CSpatialFrequencyResponse{})
160 }
161
View as plain text