File size: 1,686 Bytes
695f088
 
 
8240fca
695f088
 
8240fca
695f088
 
 
 
 
 
8240fca
 
695f088
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// One Core sample from its image file on Hugging Face: the row group that holds it, thumbnail column only.
//
//   footprint row (part, parquet_row) -> <images>/part_NNNNN.parquet (one row group per sample)
//     -> footer (read once per file, parquet.js openFile: 0.2-1.5 MB) -> that row group's thumbnail (and product_id where the file has it)
//     -> an object URL for <img>

import { compressors, newStats, openFile, parquetRead } from './parquet.js'

export const imageUrl = (info, part) => `${info.images}part_${String(part).padStart(5, '0')}.parquet`

/** The thumbnail of one sample: {src (object URL), productId, url, stats}. */
export async function loadThumbnail(info, sample) {
  const stats = newStats(), url = imageUrl(info, sample.part)
  const { file, metadata } = await openFile(url, stats)                          // footer read once per file
  const names = metadata.schema.slice(1).map(c => c.name)
  let rowStart = 0
  for (let g = 0; g < sample.parquet_row; g++) rowStart += Number(metadata.row_groups[g].num_rows)
  const columns = ['thumbnail', ...(names.includes('product_id') ? ['product_id'] : [])]
  let row
  await parquetRead({ file, metadata, compressors, columns, rowStart, rowEnd: rowStart + 1, rowFormat: 'object',
    utf8: false, onComplete(rows) { row = rows[0] } })                 // utf8: the thumbnail stays bytes
  if (!row?.thumbnail) throw new Error(`${url}: no thumbnail in row ${rowStart}`)
  stats.read = performance.now() - stats.t0
  const text = v => (v instanceof Uint8Array ? new TextDecoder().decode(v) : v ?? null)
  return { src: URL.createObjectURL(new Blob([row.thumbnail])), productId: text(row.product_id), url, stats }
}