Repository navigation
fix: restore ingredient thumbnails with c2pa-web #389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
d2c6f58
ab926d3
5885cae
f6e7325
761ae84
2793b4d
7943b9e
4402acb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| // Copyright 2021-2024 Adobe, Copyright 2025 The C2PA Contributors | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is a new file this can be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @MassivaM Can this be
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes I forgot we had that linter , we'll want to change this eventually but yes that's okay for now! |
||
|
|
||
| import type { ManifestStore, Reader } from '@contentauth/c2pa-web'; | ||
|
|
||
| /** | ||
| * Convert a relative thumbnail URI to absolute form. Already absolute | ||
| * identifiers pass through unchanged. | ||
| */ | ||
| export function toAbsoluteIdentifier( | ||
| identifier: string, | ||
| manifestLabel: string, | ||
| ): string { | ||
| if (identifier.startsWith('self#jumbf=/c2pa/')) return identifier; | ||
|
|
||
| if (identifier.startsWith('self#jumbf=')) { | ||
| const path = identifier.slice('self#jumbf='.length); | ||
|
|
||
| return `self#jumbf=/c2pa/${manifestLabel}/${path}`; | ||
| } | ||
|
|
||
| return identifier; | ||
| } | ||
|
|
||
| /** Pre-fetch every embedded thumbnail's bytes, keyed by absolute identifier. */ | ||
| export async function resolveThumbnails( | ||
| manifestStore: ManifestStore, | ||
| reader: Reader, | ||
| ): Promise<Map<string, Blob>> { | ||
| const refs = new Map<string, string>(); | ||
|
|
||
| for (const [label, manifest] of Object.entries(manifestStore.manifests || {})) { | ||
| if (manifest.thumbnail?.identifier && manifest.thumbnail.format) { | ||
| refs.set( | ||
| toAbsoluteIdentifier(manifest.thumbnail.identifier, label), | ||
| manifest.thumbnail.format, | ||
| ); | ||
| } | ||
|
|
||
| for (const ingredient of manifest.ingredients || []) { | ||
| if (ingredient.thumbnail?.identifier && ingredient.thumbnail.format) { | ||
| refs.set( | ||
| toAbsoluteIdentifier(ingredient.thumbnail.identifier, label), | ||
| ingredient.thumbnail.format, | ||
| ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const entries = await Promise.all( | ||
| Array.from(refs.entries()).map( | ||
| async ([identifier, format]): Promise<[string, Blob] | null> => { | ||
| try { | ||
| const bytes = await reader.resourceToBytes(identifier); | ||
|
|
||
| return [identifier, new Blob([new Uint8Array(bytes)], { type: format })]; | ||
| } catch (err) { | ||
| console.warn(`Failed to resolve thumbnail ${identifier}:`, err); | ||
|
|
||
| return null; | ||
| } | ||
| }, | ||
| ), | ||
| ); | ||
|
|
||
| return new Map(entries.filter((e): e is [string, Blob] => e !== null)); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use a multiline comment here to make it more readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MassivaM I just fixed this. Thanks!