@@ -114,19 +114,21 @@ func (h *Handler) Parse(r io.ReaderAt, makerNoteOffset, exifBase int64, cfg *mak
114114 return nil , parseErr
115115 }
116116
117- tags := make ([]parser.Tag , 0 , entryCount )
117+ tags := make ([]parser.Tag , 0 , entryCount * 2 ) // Extra capacity for decoded sub-tags
118118
119119 // Parse each IFD entry
120120 entryOffset := ifdOffset + ifdEntryCountSize
121121 for i := uint16 (0 ); i < entryCount ; i ++ {
122- tag , err := h .parseEntry (reader , entryOffset , exifBase )
122+ tag , subTags , err := h .parseEntry (reader , entryOffset , exifBase )
123123 if err != nil {
124124 // Continue parsing other entries
125125 entryOffset += ifdEntrySize
126126 continue
127127 }
128128 if tag != nil {
129129 tags = append (tags , * tag )
130+ // Add decoded sub-tags (for CameraSettings, ShotInfo, etc.)
131+ tags = append (tags , subTags ... )
130132 }
131133 entryOffset += ifdEntrySize
132134 }
@@ -136,32 +138,33 @@ func (h *Handler) Parse(r io.ReaderAt, makerNoteOffset, exifBase int64, cfg *mak
136138
137139// parseEntry parses a single IFD entry.
138140// For Canon, offsets are absolute (relative to EXIF TIFF header).
139- func (h * Handler ) parseEntry (r * imxbin.Reader , entryOffset , exifBase int64 ) (* parser.Tag , error ) {
141+ // Returns the main tag plus any decoded sub-tags (for compound tags like CameraSettings).
142+ func (h * Handler ) parseEntry (r * imxbin.Reader , entryOffset , exifBase int64 ) (* parser.Tag , []parser.Tag , error ) {
140143 // Read entry fields
141144 tagID , err := r .ReadUint16 (entryOffset )
142145 if err != nil {
143- return nil , err
146+ return nil , nil , err
144147 }
145148
146149 tagType , err := r .ReadUint16 (entryOffset + 2 )
147150 if err != nil {
148- return nil , err
151+ return nil , nil , err
149152 }
150153
151154 count , err := r .ReadUint32 (entryOffset + 4 )
152155 if err != nil {
153- return nil , err
156+ return nil , nil , err
154157 }
155158
156159 valueOffset , err := r .ReadUint32 (entryOffset + 8 )
157160 if err != nil {
158- return nil , err
161+ return nil , nil , err
159162 }
160163
161164 // Calculate data size
162165 typeSize := getTypeSize (tagType )
163166 if typeSize == 0 {
164- return nil , fmt .Errorf ("unknown type: %d" , tagType )
167+ return nil , nil , fmt .Errorf ("unknown type: %d" , tagType )
165168 }
166169
167170 totalSize := int64 (count ) * int64 (typeSize )
@@ -178,15 +181,101 @@ func (h *Handler) parseEntry(r *imxbin.Reader, entryOffset, exifBase int64) (*pa
178181 // Read and parse value
179182 value , err := h .readValue (r , tagType , count , dataOffset , valueOffset )
180183 if err != nil {
181- return nil , err
184+ return nil , nil , err
182185 }
183186
184- return & parser.Tag {
187+ mainTag := & parser.Tag {
185188 ID : parser .TagID (fmt .Sprintf ("Canon:0x%04X" , tagID )),
186189 Name : h .TagName (tagID ),
187190 Value : value ,
188191 DataType : getTypeName (tagType ),
189- }, nil
192+ }
193+
194+ // Decode compound tags into sub-tags
195+ var subTags []parser.Tag
196+ switch tagID {
197+ case 0x0001 : // CameraSettings
198+ subTags = h .decodeCameraSettings (value )
199+ case 0x0004 : // ShotInfo
200+ subTags = h .decodeShotInfo (value )
201+ case 0x0010 : // ModelID
202+ if decoded := h .decodeModelIDTag (value ); decoded != nil {
203+ subTags = append (subTags , * decoded )
204+ }
205+ }
206+
207+ return mainTag , subTags , nil
208+ }
209+
210+ // decodeCameraSettings extracts individual settings from CameraSettings array
211+ func (h * Handler ) decodeCameraSettings (value any ) []parser.Tag {
212+ shorts , ok := value .([]uint16 )
213+ if ! ok {
214+ return nil
215+ }
216+
217+ var tags []parser.Tag
218+ for i , v := range shorts {
219+ name , decoded := decodeCameraSettingsValue (i , v )
220+ if name != "" && decoded != "" {
221+ tags = append (tags , parser.Tag {
222+ ID : parser .TagID ("Canon:CameraSettings:" + name ),
223+ Name : name ,
224+ Value : decoded ,
225+ DataType : "decoded" ,
226+ })
227+ }
228+ }
229+ return tags
230+ }
231+
232+ // decodeShotInfo extracts individual settings from ShotInfo array
233+ func (h * Handler ) decodeShotInfo (value any ) []parser.Tag {
234+ shorts , ok := value .([]uint16 )
235+ if ! ok {
236+ return nil
237+ }
238+
239+ var tags []parser.Tag
240+ for i , v := range shorts {
241+ name , decoded := decodeShotInfoValue (i , v )
242+ if name != "" && decoded != "" {
243+ tags = append (tags , parser.Tag {
244+ ID : parser .TagID ("Canon:ShotInfo:" + name ),
245+ Name : name ,
246+ Value : decoded ,
247+ DataType : "decoded" ,
248+ })
249+ }
250+ }
251+ return tags
252+ }
253+
254+ // decodeModelIDTag decodes the ModelID to camera model name
255+ func (h * Handler ) decodeModelIDTag (value any ) * parser.Tag {
256+ var modelID uint32
257+ switch v := value .(type ) {
258+ case uint32 :
259+ modelID = v
260+ case []uint32 :
261+ if len (v ) > 0 {
262+ modelID = v [0 ]
263+ }
264+ default :
265+ return nil
266+ }
267+
268+ decoded := decodeModelID (modelID )
269+ if decoded == "" {
270+ return nil
271+ }
272+
273+ return & parser.Tag {
274+ ID : parser .TagID ("Canon:ModelName" ),
275+ Name : "ModelName" ,
276+ Value : decoded ,
277+ DataType : "decoded" ,
278+ }
190279}
191280
192281// readValue reads a tag value based on its type.
0 commit comments