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 }
}
|