@@ -103,19 +103,12 @@ func (r *Reader) extractThumbnail(data []byte) error {
103
103
return fmt .Errorf ("unable to read KFX document symbols: %w" , err )
104
104
}
105
105
106
- type entity struct {
107
- id uint32
108
- idType uint32
109
- data []byte
110
- }
111
- entities := make (map [uint32 ][]* entity )
106
+ entities := newEntitySet (docSymbols )
112
107
113
108
indexTabReader := bytes .NewReader (data [contInfo .IndexTabOffset : contInfo .IndexTabOffset + contInfo .IndexTabLength ])
114
109
tabEntry := struct {
115
- NumID uint32
116
- NumType uint32
117
- Offset uint64
118
- Size uint64
110
+ NumID , NumType uint32
111
+ Offset , Size uint64
119
112
}{}
120
113
121
114
for {
@@ -156,24 +149,17 @@ func (r *Reader) extractThumbnail(data []byte) error {
156
149
if err := entyInfo .validate (); err != nil {
157
150
return err
158
151
}
159
-
160
- entities [tabEntry .NumType ] = append (entities [tabEntry .NumType ],
161
- & entity {
162
- id : tabEntry .NumID ,
163
- idType : tabEntry .NumType ,
164
- data : enty [entyHeader .Size :],
165
- })
152
+ entities .addEntity (tabEntry .NumID , tabEntry .NumType , enty [entyHeader .Size :])
166
153
}
167
154
168
- meta , exists := entities [ symBookMetadata ]
169
- if ! exists {
155
+ metas := entities . getAllOfType ( symBookMetadata )
156
+ if len ( metas ) == 0 {
170
157
// NOTE: KFX input plugin expects case like this and attempts to get to
171
- // $258 directly, processing it differently I am ignoring this for now
172
- // as I never seen case like this.
158
+ // $258 (Metadata) directly, processing it differently in this case. I
159
+ // am ignoring this for now as I never seen case like this.
173
160
return errors .New ("no book metadata found" )
174
- }
175
- if len (meta ) != 1 {
176
- return fmt .Errorf ("ambiguous metadata, expected single book metadata entity, got %d" , len (meta ))
161
+ } else if len (metas ) != 1 {
162
+ return fmt .Errorf ("ambiguous metadata, expected single book metadata entity, got %d" , len (metas ))
177
163
}
178
164
179
165
type (
@@ -190,7 +176,7 @@ func (r *Reader) extractThumbnail(data []byte) error {
190
176
}
191
177
)
192
178
var bmd bookMetadata
193
- if err := decodeData (lstProlog , meta [0 ].data , & bmd ); err != nil {
179
+ if err := decodeData (lstProlog , metas [0 ].data , & bmd ); err != nil {
194
180
return err
195
181
}
196
182
if index := slices .IndexFunc (bmd .CategorizedMetadata , func (p properties ) bool {
@@ -221,21 +207,9 @@ func (r *Reader) extractThumbnail(data []byte) error {
221
207
return nil
222
208
}
223
209
224
- eres , exists := entities [symExternalResource ]
225
- if ! exists {
226
- return errors .New ("no external resources found" )
227
- }
228
- id , ok := docSymbols .FindByName (r .cover )
229
- if ! ok {
230
- return errors .New ("cover image name not found in the symbol table" )
231
- }
232
- id -= ion .V1SystemSymbolTable .MaxID ()
233
-
234
- var index int
235
- if index = slices .IndexFunc (eres , func (e * entity ) bool {
236
- return uint64 (e .id ) == id
237
- }); index == - 1 {
238
- return errors .New ("cover image id not found in the external resources" )
210
+ coverRes , err := entities .getByName (r .cover , symExternalResource )
211
+ if err != nil {
212
+ return fmt .Errorf ("unable to get cover image entity: %w" , err )
239
213
}
240
214
241
215
c := struct {
@@ -246,29 +220,17 @@ func (r *Reader) extractThumbnail(data []byte) error {
246
220
// Height int `ion:"$423"`
247
221
// Mime string `ion:"$162"`
248
222
}{}
249
-
250
- if err := decodeData (lstProlog , eres [index ].data , & c ); err != nil {
223
+ if err := decodeData (lstProlog , coverRes .data , & c ); err != nil {
251
224
return err
252
225
}
253
226
254
- imgDataID , ok := docSymbols .FindByName (c .Location )
255
- if ! ok {
256
- return errors .New ("cover image location not found in the symbol table" )
257
- }
258
- imgDataID -= ion .V1SystemSymbolTable .MaxID ()
259
-
260
- media , exists := entities [symRawMedia ]
261
- if ! exists {
262
- return errors .New ("no raw media fragments found in a book" )
263
- }
264
- if index = slices .IndexFunc (media , func (e * entity ) bool {
265
- return uint64 (e .id ) == imgDataID
266
- }); index == - 1 {
267
- return errors .New ("cover image raw media not found in the external resources" )
227
+ coverImage , err := entities .getByName (c .Location , symRawMedia )
228
+ if err != nil {
229
+ return fmt .Errorf ("unable to get cover image data: %w" , err )
268
230
}
269
231
270
232
var img image.Image
271
- if img , _ , err = image .Decode (bytes .NewReader (media [ index ] .data )); err != nil {
233
+ if img , _ , err = image .Decode (bytes .NewReader (coverImage .data )); err != nil {
272
234
return fmt .Errorf ("unable to decode extracted cover: %w" , err )
273
235
}
274
236
imgthumb := imaging .Thumbnail (img , r .width , r .height , imaging .Lanczos )
@@ -381,3 +343,58 @@ func (e *entityInfo) validate() error {
381
343
}
382
344
return nil
383
345
}
346
+
347
+ type (
348
+ entity struct {
349
+ id , idType uint32
350
+ data []byte
351
+ }
352
+ entitySet struct {
353
+ st ion.SymbolTable
354
+ fragments map [uint32 ][]* entity
355
+ }
356
+ )
357
+
358
+ func newEntitySet (st ion.SymbolTable ) * entitySet {
359
+ return & entitySet {
360
+ st : st ,
361
+ fragments : make (map [uint32 ][]* entity ),
362
+ }
363
+ }
364
+
365
+ func (s * entitySet ) addEntity (id , idType uint32 , data []byte ) {
366
+ s .fragments [idType ] = append (s .fragments [idType ],
367
+ & entity {
368
+ id : id ,
369
+ idType : idType ,
370
+ data : data ,
371
+ })
372
+ }
373
+
374
+ func (s * entitySet ) getAllOfType (idType uint32 ) []* entity {
375
+ entities , exists := s .fragments [idType ]
376
+ if ! exists {
377
+ return nil
378
+ }
379
+ return entities
380
+ }
381
+
382
+ func (s * entitySet ) getByName (name string , idType uint32 ) (* entity , error ) {
383
+ entities , exists := s .fragments [idType ]
384
+ if ! exists {
385
+ return nil , fmt .Errorf ("no entities of type '%d' found" , idType )
386
+ }
387
+ id , ok := s .st .FindByName (name )
388
+ if ! ok {
389
+ return nil , fmt .Errorf ("symbol '%s' not found in the symbol table" , name )
390
+ }
391
+ id -= ion .V1SystemSymbolTable .MaxID ()
392
+
393
+ var index int
394
+ if index = slices .IndexFunc (entities , func (e * entity ) bool {
395
+ return uint64 (e .id ) == id
396
+ }); index == - 1 {
397
+ return nil , fmt .Errorf ("entity fragment '%s' of type '%d' not found" , name , idType )
398
+ }
399
+ return entities [index ], nil
400
+ }
0 commit comments