open-ultrahdr 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/index.d.mts +35 -135
- package/dist/index.d.ts +35 -135
- package/dist/index.js +65 -56
- package/dist/index.mjs +64 -56
- package/package.json +4 -4
- package/src/index.ts +96 -275
- package/src/types.ts +16 -2
package/README.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -85,9 +85,23 @@ interface UltraHdrEncodeOptions {
|
|
|
85
85
|
gainMapQuality: number;
|
|
86
86
|
/** Target HDR capacity (typically 2.0-4.0) */
|
|
87
87
|
targetHdrCapacity: number;
|
|
88
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Whether to include ISO 21496-1 metadata.
|
|
90
|
+
*
|
|
91
|
+
* Currently a no-op: libultrahdr's encoder unconditionally emits ISO
|
|
92
|
+
* 21496-1 metadata and exposes no public toggle. Kept for API stability
|
|
93
|
+
* with prior versions; setting this to `false` will not suppress the
|
|
94
|
+
* metadata block.
|
|
95
|
+
*/
|
|
89
96
|
includeIsoMetadata: boolean;
|
|
90
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* Whether to include UltraHDR v1 metadata for Android compatibility.
|
|
99
|
+
*
|
|
100
|
+
* Currently a no-op: libultrahdr's encoder unconditionally emits the v1
|
|
101
|
+
* metadata block and exposes no public toggle. Kept for API stability
|
|
102
|
+
* with prior versions; setting this to `false` will not suppress the
|
|
103
|
+
* metadata block.
|
|
104
|
+
*/
|
|
91
105
|
includeUltrahdrV1: boolean;
|
|
92
106
|
/** Downscale factor for the gain map (1 = same size, 2 = half, 4 = quarter) */
|
|
93
107
|
gainMapScale: number;
|
|
@@ -132,18 +146,18 @@ declare const smallSizeEncodeOptions: UltraHdrEncodeOptions;
|
|
|
132
146
|
/**
|
|
133
147
|
* Open UltraHDR Library
|
|
134
148
|
*
|
|
135
|
-
* TypeScript bindings for the
|
|
136
|
-
*
|
|
137
|
-
*
|
|
149
|
+
* TypeScript bindings for the libultrahdr WASM library. Provides detection,
|
|
150
|
+
* encoding, and decoding of UltraHDR JPEG images implementing the
|
|
151
|
+
* ISO 21496-1 (gain map) specification.
|
|
152
|
+
*
|
|
153
|
+
* Backed by upstream `libultrahdr` compiled to WebAssembly via Emscripten/embind.
|
|
138
154
|
*
|
|
139
155
|
* @example
|
|
140
156
|
* ```typescript
|
|
141
157
|
* import { isUltraHdr, decodeUltraHdr, setLocation } from 'open-ultrahdr';
|
|
142
158
|
*
|
|
143
|
-
* // Set the location for WASM files
|
|
144
159
|
* setLocation('/path/to/wasm/');
|
|
145
160
|
*
|
|
146
|
-
* // Check if an image is UltraHDR
|
|
147
161
|
* const buffer = await file.arrayBuffer();
|
|
148
162
|
* if (await isUltraHdr(buffer)) {
|
|
149
163
|
* const result = await decodeUltraHdr('item-1', buffer);
|
|
@@ -155,171 +169,57 @@ declare const smallSizeEncodeOptions: UltraHdrEncodeOptions;
|
|
|
155
169
|
/**
|
|
156
170
|
* Sets the location/public path for loading WASM files.
|
|
157
171
|
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
172
|
+
* Must be called before using any other functions when the WASM file is not
|
|
173
|
+
* served from the same directory as the JavaScript bundle.
|
|
160
174
|
*
|
|
161
175
|
* @param newLocation - Base URL or path where WASM files are located.
|
|
162
|
-
*
|
|
163
|
-
* @example
|
|
164
|
-
* ```typescript
|
|
165
|
-
* // Set location before any other calls
|
|
166
|
-
* setLocation('/assets/wasm/');
|
|
167
|
-
* ```
|
|
168
176
|
*/
|
|
169
177
|
declare function setLocation(newLocation: string): void;
|
|
170
178
|
/**
|
|
171
|
-
*
|
|
179
|
+
* Sets an explicit URL (or `data:` URL) for the WASM file.
|
|
172
180
|
*
|
|
173
|
-
*
|
|
174
|
-
* fully decoding the image.
|
|
181
|
+
* Useful when bundling the WASM as a base64 data URL.
|
|
175
182
|
*
|
|
176
|
-
* @param
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
*
|
|
181
|
-
* const buffer = await file.arrayBuffer();
|
|
182
|
-
* if (await isUltraHdr(buffer)) {
|
|
183
|
-
* console.log('This is an UltraHDR image!');
|
|
184
|
-
* }
|
|
185
|
-
* ```
|
|
183
|
+
* @param url - Full URL or data URL pointing to `open_ultrahdr.wasm`.
|
|
184
|
+
*/
|
|
185
|
+
declare function setWasmUrl(url: string): void;
|
|
186
|
+
/**
|
|
187
|
+
* Checks if a buffer contains an UltraHDR image.
|
|
186
188
|
*/
|
|
187
189
|
declare function isUltraHdr(buffer: ArrayBuffer): Promise<boolean>;
|
|
188
190
|
/**
|
|
189
|
-
* Probes an image to check if it's UltraHDR and extracts component
|
|
190
|
-
*
|
|
191
|
-
* This function efficiently validates if an image is UltraHDR by checking for
|
|
192
|
-
* required components (primary image, gain map, metadata) without full decoding.
|
|
193
|
-
* Returns structured results useful for batch processing and filtering.
|
|
194
|
-
*
|
|
195
|
-
* Unlike `isUltraHdr`, this function provides detailed information about what
|
|
196
|
-
* was found, making it useful for diagnostics and filtering workflows.
|
|
197
|
-
*
|
|
198
|
-
* @param buffer - Image file contents.
|
|
199
|
-
* @return Probe result with detailed component information.
|
|
200
|
-
*
|
|
201
|
-
* @example
|
|
202
|
-
* ```typescript
|
|
203
|
-
* const buffer = await file.arrayBuffer();
|
|
204
|
-
* const result = await probeUltraHdr(buffer);
|
|
191
|
+
* Probes an image to check if it's UltraHDR and extracts component info.
|
|
205
192
|
*
|
|
206
|
-
*
|
|
207
|
-
* console.log('UltraHDR image:', result.width, 'x', result.height);
|
|
208
|
-
* console.log('HDR capacity:', result.hdrCapacity, 'stops');
|
|
209
|
-
* console.log('Gain map:', result.gainMapWidth, 'x', result.gainMapHeight);
|
|
210
|
-
* } else {
|
|
211
|
-
* // Diagnose why it's not a valid UltraHDR
|
|
212
|
-
* if (!result.hasPrimaryImage) console.log('Not a valid JPEG');
|
|
213
|
-
* if (!result.hasGainMap) console.log('Missing gain map');
|
|
214
|
-
* if (!result.hasMetadata) console.log('Missing HDR metadata');
|
|
215
|
-
* }
|
|
216
|
-
* ```
|
|
193
|
+
* Never throws — invalid inputs return a result with all flags set to false.
|
|
217
194
|
*/
|
|
218
195
|
declare function probeUltraHdr(buffer: ArrayBuffer): Promise<UltraHdrProbeResult>;
|
|
219
196
|
/**
|
|
220
197
|
* Decodes an UltraHDR image, extracting all components.
|
|
221
|
-
*
|
|
222
|
-
* @param id - Unique identifier for this operation (for cancellation).
|
|
223
|
-
* @param buffer - UltraHDR JPEG file contents.
|
|
224
|
-
* @return Decoded result with SDR image, gain map, and metadata.
|
|
225
|
-
*
|
|
226
|
-
* @throws Error if the buffer is not a valid UltraHDR JPEG.
|
|
227
|
-
*
|
|
228
|
-
* @example
|
|
229
|
-
* ```typescript
|
|
230
|
-
* const buffer = await file.arrayBuffer();
|
|
231
|
-
* const result = await decodeUltraHdr('upload-1', buffer);
|
|
232
|
-
*
|
|
233
|
-
* // Access components
|
|
234
|
-
* const sdrBlob = new Blob([result.sdrImage], { type: 'image/jpeg' });
|
|
235
|
-
* console.log('Image size:', result.width, 'x', result.height);
|
|
236
|
-
* console.log('HDR capacity:', result.metadata.hdrCapacityMax);
|
|
237
|
-
* ```
|
|
238
198
|
*/
|
|
239
|
-
declare function decodeUltraHdr(
|
|
199
|
+
declare function decodeUltraHdr(_id: ItemId, buffer: ArrayBuffer): Promise<UltraHdrDecodeResult>;
|
|
240
200
|
/**
|
|
241
201
|
* Encodes an UltraHDR JPEG from SDR and HDR inputs.
|
|
242
|
-
*
|
|
243
|
-
* @param id - Unique identifier for this operation.
|
|
244
|
-
* @param sdrBuffer - SDR JPEG image bytes.
|
|
245
|
-
* @param hdrBuffer - HDR linear RGB data (Float32Array, 3 values per pixel).
|
|
246
|
-
* @param options - Encoding options.
|
|
247
|
-
* @return Encoded UltraHDR JPEG as ArrayBuffer.
|
|
248
|
-
*
|
|
249
|
-
* @throws Error if inputs are invalid or dimensions don't match.
|
|
250
|
-
*
|
|
251
|
-
* @example
|
|
252
|
-
* ```typescript
|
|
253
|
-
* const sdrBuffer = await sdrFile.arrayBuffer();
|
|
254
|
-
* const hdrData = await getHdrLinearData(); // Float32Array
|
|
255
|
-
*
|
|
256
|
-
* const ultraHdr = await encodeUltraHdr('encode-1', sdrBuffer, hdrData, {
|
|
257
|
-
* ...defaultEncodeOptions,
|
|
258
|
-
* targetHdrCapacity: 4.0,
|
|
259
|
-
* });
|
|
260
|
-
*
|
|
261
|
-
* // Create downloadable file
|
|
262
|
-
* const blob = new Blob([ultraHdr], { type: 'image/jpeg' });
|
|
263
|
-
* ```
|
|
264
202
|
*/
|
|
265
|
-
declare function encodeUltraHdr(
|
|
203
|
+
declare function encodeUltraHdr(_id: ItemId, sdrBuffer: ArrayBuffer, hdrBuffer: ArrayBuffer, options?: Partial<UltraHdrEncodeOptions>): Promise<ArrayBuffer>;
|
|
266
204
|
/**
|
|
267
205
|
* Extracts the SDR base image from an UltraHDR JPEG.
|
|
268
|
-
*
|
|
269
|
-
* This produces a standard JPEG that can be displayed on any device,
|
|
270
|
-
* without the gain map metadata. Useful for backwards compatibility.
|
|
271
|
-
*
|
|
272
|
-
* @param buffer - UltraHDR JPEG file contents.
|
|
273
|
-
* @return Standard JPEG without gain map.
|
|
274
|
-
*
|
|
275
|
-
* @example
|
|
276
|
-
* ```typescript
|
|
277
|
-
* const ultraHdrBuffer = await file.arrayBuffer();
|
|
278
|
-
* const sdrBuffer = await extractSdrBase(ultraHdrBuffer);
|
|
279
|
-
*
|
|
280
|
-
* // Use the SDR image for non-HDR displays
|
|
281
|
-
* const blob = new Blob([sdrBuffer], { type: 'image/jpeg' });
|
|
282
|
-
* ```
|
|
283
206
|
*/
|
|
284
207
|
declare function extractSdrBase(buffer: ArrayBuffer): Promise<ArrayBuffer>;
|
|
285
208
|
/**
|
|
286
209
|
* Gets gain map metadata from an UltraHDR JPEG.
|
|
287
|
-
*
|
|
288
|
-
* This is faster than `decodeUltraHdr` when you only need the metadata.
|
|
289
|
-
*
|
|
290
|
-
* @param buffer - UltraHDR JPEG file contents.
|
|
291
|
-
* @return Gain map metadata.
|
|
292
|
-
*
|
|
293
|
-
* @throws Error if the buffer doesn't contain gain map metadata.
|
|
294
|
-
*
|
|
295
|
-
* @example
|
|
296
|
-
* ```typescript
|
|
297
|
-
* const metadata = await getMetadata(buffer);
|
|
298
|
-
* console.log('Version:', metadata.version);
|
|
299
|
-
* console.log('HDR headroom:', metadata.hdrCapacityMax, 'stops');
|
|
300
|
-
* ```
|
|
301
210
|
*/
|
|
302
211
|
declare function getMetadata(buffer: ArrayBuffer): Promise<GainMapMetadata>;
|
|
303
212
|
/**
|
|
304
213
|
* Validates gain map metadata.
|
|
305
|
-
*
|
|
306
|
-
* @param metadata - The metadata to validate.
|
|
307
|
-
* @return True if the metadata is valid.
|
|
308
214
|
*/
|
|
309
215
|
declare function validateMetadata(metadata: GainMapMetadata): Promise<boolean>;
|
|
310
216
|
/**
|
|
311
217
|
* Estimates the HDR headroom from metadata.
|
|
312
|
-
*
|
|
313
|
-
* @param metadata - The gain map metadata.
|
|
314
|
-
* @return Maximum additional stops of dynamic range above SDR.
|
|
315
218
|
*/
|
|
316
219
|
declare function estimateHdrHeadroom(metadata: GainMapMetadata): Promise<number>;
|
|
317
220
|
/**
|
|
318
221
|
* Checks if metadata indicates a meaningful HDR image.
|
|
319
|
-
*
|
|
320
|
-
* @param metadata - The gain map metadata.
|
|
321
|
-
* @return True if the gain map provides significant dynamic range extension.
|
|
322
222
|
*/
|
|
323
223
|
declare function isMeaningfulHdr(metadata: GainMapMetadata): Promise<boolean>;
|
|
324
224
|
|
|
325
|
-
export { ColorGamut, type GainMapMetadata, type ItemId, TransferFunction, type UltraHdrDecodeResult, type UltraHdrEncodeOptions, type UltraHdrProbeResult, decodeUltraHdr, defaultEncodeOptions, encodeUltraHdr, estimateHdrHeadroom, extractSdrBase, getMetadata, highQualityEncodeOptions, isMeaningfulHdr, isUltraHdr, probeUltraHdr, setLocation, smallSizeEncodeOptions, validateMetadata };
|
|
225
|
+
export { ColorGamut, type GainMapMetadata, type ItemId, TransferFunction, type UltraHdrDecodeResult, type UltraHdrEncodeOptions, type UltraHdrProbeResult, decodeUltraHdr, defaultEncodeOptions, encodeUltraHdr, estimateHdrHeadroom, extractSdrBase, getMetadata, highQualityEncodeOptions, isMeaningfulHdr, isUltraHdr, probeUltraHdr, setLocation, setWasmUrl, smallSizeEncodeOptions, validateMetadata };
|
package/dist/index.d.ts
CHANGED
|
@@ -85,9 +85,23 @@ interface UltraHdrEncodeOptions {
|
|
|
85
85
|
gainMapQuality: number;
|
|
86
86
|
/** Target HDR capacity (typically 2.0-4.0) */
|
|
87
87
|
targetHdrCapacity: number;
|
|
88
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Whether to include ISO 21496-1 metadata.
|
|
90
|
+
*
|
|
91
|
+
* Currently a no-op: libultrahdr's encoder unconditionally emits ISO
|
|
92
|
+
* 21496-1 metadata and exposes no public toggle. Kept for API stability
|
|
93
|
+
* with prior versions; setting this to `false` will not suppress the
|
|
94
|
+
* metadata block.
|
|
95
|
+
*/
|
|
89
96
|
includeIsoMetadata: boolean;
|
|
90
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* Whether to include UltraHDR v1 metadata for Android compatibility.
|
|
99
|
+
*
|
|
100
|
+
* Currently a no-op: libultrahdr's encoder unconditionally emits the v1
|
|
101
|
+
* metadata block and exposes no public toggle. Kept for API stability
|
|
102
|
+
* with prior versions; setting this to `false` will not suppress the
|
|
103
|
+
* metadata block.
|
|
104
|
+
*/
|
|
91
105
|
includeUltrahdrV1: boolean;
|
|
92
106
|
/** Downscale factor for the gain map (1 = same size, 2 = half, 4 = quarter) */
|
|
93
107
|
gainMapScale: number;
|
|
@@ -132,18 +146,18 @@ declare const smallSizeEncodeOptions: UltraHdrEncodeOptions;
|
|
|
132
146
|
/**
|
|
133
147
|
* Open UltraHDR Library
|
|
134
148
|
*
|
|
135
|
-
* TypeScript bindings for the
|
|
136
|
-
*
|
|
137
|
-
*
|
|
149
|
+
* TypeScript bindings for the libultrahdr WASM library. Provides detection,
|
|
150
|
+
* encoding, and decoding of UltraHDR JPEG images implementing the
|
|
151
|
+
* ISO 21496-1 (gain map) specification.
|
|
152
|
+
*
|
|
153
|
+
* Backed by upstream `libultrahdr` compiled to WebAssembly via Emscripten/embind.
|
|
138
154
|
*
|
|
139
155
|
* @example
|
|
140
156
|
* ```typescript
|
|
141
157
|
* import { isUltraHdr, decodeUltraHdr, setLocation } from 'open-ultrahdr';
|
|
142
158
|
*
|
|
143
|
-
* // Set the location for WASM files
|
|
144
159
|
* setLocation('/path/to/wasm/');
|
|
145
160
|
*
|
|
146
|
-
* // Check if an image is UltraHDR
|
|
147
161
|
* const buffer = await file.arrayBuffer();
|
|
148
162
|
* if (await isUltraHdr(buffer)) {
|
|
149
163
|
* const result = await decodeUltraHdr('item-1', buffer);
|
|
@@ -155,171 +169,57 @@ declare const smallSizeEncodeOptions: UltraHdrEncodeOptions;
|
|
|
155
169
|
/**
|
|
156
170
|
* Sets the location/public path for loading WASM files.
|
|
157
171
|
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
172
|
+
* Must be called before using any other functions when the WASM file is not
|
|
173
|
+
* served from the same directory as the JavaScript bundle.
|
|
160
174
|
*
|
|
161
175
|
* @param newLocation - Base URL or path where WASM files are located.
|
|
162
|
-
*
|
|
163
|
-
* @example
|
|
164
|
-
* ```typescript
|
|
165
|
-
* // Set location before any other calls
|
|
166
|
-
* setLocation('/assets/wasm/');
|
|
167
|
-
* ```
|
|
168
176
|
*/
|
|
169
177
|
declare function setLocation(newLocation: string): void;
|
|
170
178
|
/**
|
|
171
|
-
*
|
|
179
|
+
* Sets an explicit URL (or `data:` URL) for the WASM file.
|
|
172
180
|
*
|
|
173
|
-
*
|
|
174
|
-
* fully decoding the image.
|
|
181
|
+
* Useful when bundling the WASM as a base64 data URL.
|
|
175
182
|
*
|
|
176
|
-
* @param
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
*
|
|
181
|
-
* const buffer = await file.arrayBuffer();
|
|
182
|
-
* if (await isUltraHdr(buffer)) {
|
|
183
|
-
* console.log('This is an UltraHDR image!');
|
|
184
|
-
* }
|
|
185
|
-
* ```
|
|
183
|
+
* @param url - Full URL or data URL pointing to `open_ultrahdr.wasm`.
|
|
184
|
+
*/
|
|
185
|
+
declare function setWasmUrl(url: string): void;
|
|
186
|
+
/**
|
|
187
|
+
* Checks if a buffer contains an UltraHDR image.
|
|
186
188
|
*/
|
|
187
189
|
declare function isUltraHdr(buffer: ArrayBuffer): Promise<boolean>;
|
|
188
190
|
/**
|
|
189
|
-
* Probes an image to check if it's UltraHDR and extracts component
|
|
190
|
-
*
|
|
191
|
-
* This function efficiently validates if an image is UltraHDR by checking for
|
|
192
|
-
* required components (primary image, gain map, metadata) without full decoding.
|
|
193
|
-
* Returns structured results useful for batch processing and filtering.
|
|
194
|
-
*
|
|
195
|
-
* Unlike `isUltraHdr`, this function provides detailed information about what
|
|
196
|
-
* was found, making it useful for diagnostics and filtering workflows.
|
|
197
|
-
*
|
|
198
|
-
* @param buffer - Image file contents.
|
|
199
|
-
* @return Probe result with detailed component information.
|
|
200
|
-
*
|
|
201
|
-
* @example
|
|
202
|
-
* ```typescript
|
|
203
|
-
* const buffer = await file.arrayBuffer();
|
|
204
|
-
* const result = await probeUltraHdr(buffer);
|
|
191
|
+
* Probes an image to check if it's UltraHDR and extracts component info.
|
|
205
192
|
*
|
|
206
|
-
*
|
|
207
|
-
* console.log('UltraHDR image:', result.width, 'x', result.height);
|
|
208
|
-
* console.log('HDR capacity:', result.hdrCapacity, 'stops');
|
|
209
|
-
* console.log('Gain map:', result.gainMapWidth, 'x', result.gainMapHeight);
|
|
210
|
-
* } else {
|
|
211
|
-
* // Diagnose why it's not a valid UltraHDR
|
|
212
|
-
* if (!result.hasPrimaryImage) console.log('Not a valid JPEG');
|
|
213
|
-
* if (!result.hasGainMap) console.log('Missing gain map');
|
|
214
|
-
* if (!result.hasMetadata) console.log('Missing HDR metadata');
|
|
215
|
-
* }
|
|
216
|
-
* ```
|
|
193
|
+
* Never throws — invalid inputs return a result with all flags set to false.
|
|
217
194
|
*/
|
|
218
195
|
declare function probeUltraHdr(buffer: ArrayBuffer): Promise<UltraHdrProbeResult>;
|
|
219
196
|
/**
|
|
220
197
|
* Decodes an UltraHDR image, extracting all components.
|
|
221
|
-
*
|
|
222
|
-
* @param id - Unique identifier for this operation (for cancellation).
|
|
223
|
-
* @param buffer - UltraHDR JPEG file contents.
|
|
224
|
-
* @return Decoded result with SDR image, gain map, and metadata.
|
|
225
|
-
*
|
|
226
|
-
* @throws Error if the buffer is not a valid UltraHDR JPEG.
|
|
227
|
-
*
|
|
228
|
-
* @example
|
|
229
|
-
* ```typescript
|
|
230
|
-
* const buffer = await file.arrayBuffer();
|
|
231
|
-
* const result = await decodeUltraHdr('upload-1', buffer);
|
|
232
|
-
*
|
|
233
|
-
* // Access components
|
|
234
|
-
* const sdrBlob = new Blob([result.sdrImage], { type: 'image/jpeg' });
|
|
235
|
-
* console.log('Image size:', result.width, 'x', result.height);
|
|
236
|
-
* console.log('HDR capacity:', result.metadata.hdrCapacityMax);
|
|
237
|
-
* ```
|
|
238
198
|
*/
|
|
239
|
-
declare function decodeUltraHdr(
|
|
199
|
+
declare function decodeUltraHdr(_id: ItemId, buffer: ArrayBuffer): Promise<UltraHdrDecodeResult>;
|
|
240
200
|
/**
|
|
241
201
|
* Encodes an UltraHDR JPEG from SDR and HDR inputs.
|
|
242
|
-
*
|
|
243
|
-
* @param id - Unique identifier for this operation.
|
|
244
|
-
* @param sdrBuffer - SDR JPEG image bytes.
|
|
245
|
-
* @param hdrBuffer - HDR linear RGB data (Float32Array, 3 values per pixel).
|
|
246
|
-
* @param options - Encoding options.
|
|
247
|
-
* @return Encoded UltraHDR JPEG as ArrayBuffer.
|
|
248
|
-
*
|
|
249
|
-
* @throws Error if inputs are invalid or dimensions don't match.
|
|
250
|
-
*
|
|
251
|
-
* @example
|
|
252
|
-
* ```typescript
|
|
253
|
-
* const sdrBuffer = await sdrFile.arrayBuffer();
|
|
254
|
-
* const hdrData = await getHdrLinearData(); // Float32Array
|
|
255
|
-
*
|
|
256
|
-
* const ultraHdr = await encodeUltraHdr('encode-1', sdrBuffer, hdrData, {
|
|
257
|
-
* ...defaultEncodeOptions,
|
|
258
|
-
* targetHdrCapacity: 4.0,
|
|
259
|
-
* });
|
|
260
|
-
*
|
|
261
|
-
* // Create downloadable file
|
|
262
|
-
* const blob = new Blob([ultraHdr], { type: 'image/jpeg' });
|
|
263
|
-
* ```
|
|
264
202
|
*/
|
|
265
|
-
declare function encodeUltraHdr(
|
|
203
|
+
declare function encodeUltraHdr(_id: ItemId, sdrBuffer: ArrayBuffer, hdrBuffer: ArrayBuffer, options?: Partial<UltraHdrEncodeOptions>): Promise<ArrayBuffer>;
|
|
266
204
|
/**
|
|
267
205
|
* Extracts the SDR base image from an UltraHDR JPEG.
|
|
268
|
-
*
|
|
269
|
-
* This produces a standard JPEG that can be displayed on any device,
|
|
270
|
-
* without the gain map metadata. Useful for backwards compatibility.
|
|
271
|
-
*
|
|
272
|
-
* @param buffer - UltraHDR JPEG file contents.
|
|
273
|
-
* @return Standard JPEG without gain map.
|
|
274
|
-
*
|
|
275
|
-
* @example
|
|
276
|
-
* ```typescript
|
|
277
|
-
* const ultraHdrBuffer = await file.arrayBuffer();
|
|
278
|
-
* const sdrBuffer = await extractSdrBase(ultraHdrBuffer);
|
|
279
|
-
*
|
|
280
|
-
* // Use the SDR image for non-HDR displays
|
|
281
|
-
* const blob = new Blob([sdrBuffer], { type: 'image/jpeg' });
|
|
282
|
-
* ```
|
|
283
206
|
*/
|
|
284
207
|
declare function extractSdrBase(buffer: ArrayBuffer): Promise<ArrayBuffer>;
|
|
285
208
|
/**
|
|
286
209
|
* Gets gain map metadata from an UltraHDR JPEG.
|
|
287
|
-
*
|
|
288
|
-
* This is faster than `decodeUltraHdr` when you only need the metadata.
|
|
289
|
-
*
|
|
290
|
-
* @param buffer - UltraHDR JPEG file contents.
|
|
291
|
-
* @return Gain map metadata.
|
|
292
|
-
*
|
|
293
|
-
* @throws Error if the buffer doesn't contain gain map metadata.
|
|
294
|
-
*
|
|
295
|
-
* @example
|
|
296
|
-
* ```typescript
|
|
297
|
-
* const metadata = await getMetadata(buffer);
|
|
298
|
-
* console.log('Version:', metadata.version);
|
|
299
|
-
* console.log('HDR headroom:', metadata.hdrCapacityMax, 'stops');
|
|
300
|
-
* ```
|
|
301
210
|
*/
|
|
302
211
|
declare function getMetadata(buffer: ArrayBuffer): Promise<GainMapMetadata>;
|
|
303
212
|
/**
|
|
304
213
|
* Validates gain map metadata.
|
|
305
|
-
*
|
|
306
|
-
* @param metadata - The metadata to validate.
|
|
307
|
-
* @return True if the metadata is valid.
|
|
308
214
|
*/
|
|
309
215
|
declare function validateMetadata(metadata: GainMapMetadata): Promise<boolean>;
|
|
310
216
|
/**
|
|
311
217
|
* Estimates the HDR headroom from metadata.
|
|
312
|
-
*
|
|
313
|
-
* @param metadata - The gain map metadata.
|
|
314
|
-
* @return Maximum additional stops of dynamic range above SDR.
|
|
315
218
|
*/
|
|
316
219
|
declare function estimateHdrHeadroom(metadata: GainMapMetadata): Promise<number>;
|
|
317
220
|
/**
|
|
318
221
|
* Checks if metadata indicates a meaningful HDR image.
|
|
319
|
-
*
|
|
320
|
-
* @param metadata - The gain map metadata.
|
|
321
|
-
* @return True if the gain map provides significant dynamic range extension.
|
|
322
222
|
*/
|
|
323
223
|
declare function isMeaningfulHdr(metadata: GainMapMetadata): Promise<boolean>;
|
|
324
224
|
|
|
325
|
-
export { ColorGamut, type GainMapMetadata, type ItemId, TransferFunction, type UltraHdrDecodeResult, type UltraHdrEncodeOptions, type UltraHdrProbeResult, decodeUltraHdr, defaultEncodeOptions, encodeUltraHdr, estimateHdrHeadroom, extractSdrBase, getMetadata, highQualityEncodeOptions, isMeaningfulHdr, isUltraHdr, probeUltraHdr, setLocation, smallSizeEncodeOptions, validateMetadata };
|
|
225
|
+
export { ColorGamut, type GainMapMetadata, type ItemId, TransferFunction, type UltraHdrDecodeResult, type UltraHdrEncodeOptions, type UltraHdrProbeResult, decodeUltraHdr, defaultEncodeOptions, encodeUltraHdr, estimateHdrHeadroom, extractSdrBase, getMetadata, highQualityEncodeOptions, isMeaningfulHdr, isUltraHdr, probeUltraHdr, setLocation, setWasmUrl, smallSizeEncodeOptions, validateMetadata };
|
package/dist/index.js
CHANGED
|
@@ -43,6 +43,7 @@ __export(index_exports, {
|
|
|
43
43
|
isUltraHdr: () => isUltraHdr,
|
|
44
44
|
probeUltraHdr: () => probeUltraHdr,
|
|
45
45
|
setLocation: () => setLocation,
|
|
46
|
+
setWasmUrl: () => setWasmUrl,
|
|
46
47
|
smallSizeEncodeOptions: () => smallSizeEncodeOptions,
|
|
47
48
|
validateMetadata: () => validateMetadata
|
|
48
49
|
});
|
|
@@ -88,59 +89,61 @@ var smallSizeEncodeOptions = {
|
|
|
88
89
|
};
|
|
89
90
|
|
|
90
91
|
// src/index.ts
|
|
92
|
+
var WASM_FILENAME = "open_ultrahdr.wasm";
|
|
91
93
|
var location = "";
|
|
94
|
+
var explicitWasmUrl = null;
|
|
92
95
|
var wasmInstance = null;
|
|
93
96
|
var initPromise = null;
|
|
97
|
+
var initGeneration = 0;
|
|
94
98
|
function setLocation(newLocation) {
|
|
95
99
|
location = newLocation;
|
|
100
|
+
explicitWasmUrl = null;
|
|
101
|
+
resetCache();
|
|
96
102
|
}
|
|
97
|
-
function
|
|
98
|
-
|
|
103
|
+
function setWasmUrl(url) {
|
|
104
|
+
explicitWasmUrl = url;
|
|
105
|
+
resetCache();
|
|
99
106
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
wasmMetadata.gainMapMin = metadata.gainMapMin;
|
|
109
|
-
wasmMetadata.gainMapMax = metadata.gainMapMax;
|
|
110
|
-
wasmMetadata.gamma = metadata.gamma;
|
|
111
|
-
wasmMetadata.offsetSdr = metadata.offsetSdr;
|
|
112
|
-
wasmMetadata.offsetHdr = metadata.offsetHdr;
|
|
113
|
-
wasmMetadata.hdrCapacityMin = metadata.hdrCapacityMin;
|
|
114
|
-
wasmMetadata.hdrCapacityMax = metadata.hdrCapacityMax;
|
|
115
|
-
return wasmMetadata;
|
|
107
|
+
function resetCache() {
|
|
108
|
+
initGeneration += 1;
|
|
109
|
+
wasmInstance = null;
|
|
110
|
+
initPromise = null;
|
|
111
|
+
}
|
|
112
|
+
function joinPath(base, name) {
|
|
113
|
+
if (!base) return name;
|
|
114
|
+
return base.endsWith("/") ? `${base}${name}` : `${base}/${name}`;
|
|
116
115
|
}
|
|
117
116
|
async function getWasm() {
|
|
118
|
-
if (wasmInstance)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (initPromise) {
|
|
122
|
-
return initPromise;
|
|
123
|
-
}
|
|
117
|
+
if (wasmInstance) return wasmInstance;
|
|
118
|
+
if (initPromise) return initPromise;
|
|
119
|
+
const generation = initGeneration;
|
|
124
120
|
initPromise = (async () => {
|
|
125
121
|
try {
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
122
|
+
const wasmModule = await import("open-ultrahdr-wasm");
|
|
123
|
+
const factory = wasmModule.default;
|
|
124
|
+
const isNode = typeof process !== "undefined" && !!process.versions && !!process.versions.node;
|
|
125
|
+
const moduleOptions = {};
|
|
126
|
+
if (explicitWasmUrl) {
|
|
127
|
+
moduleOptions.locateFile = (path) => path.endsWith(".wasm") ? explicitWasmUrl : path;
|
|
128
|
+
} else if (location) {
|
|
129
|
+
if (isNode) {
|
|
131
130
|
const fs = await import("fs");
|
|
132
|
-
const wasmBytes = await fs.promises.readFile(
|
|
133
|
-
|
|
131
|
+
const wasmBytes = await fs.promises.readFile(joinPath(location, WASM_FILENAME));
|
|
132
|
+
moduleOptions.wasmBinary = new Uint8Array(wasmBytes);
|
|
134
133
|
} else {
|
|
135
|
-
|
|
134
|
+
moduleOptions.locateFile = (path) => path.endsWith(".wasm") ? joinPath(location, WASM_FILENAME) : path;
|
|
136
135
|
}
|
|
137
|
-
} else {
|
|
138
|
-
await UltraHdrWasm.default();
|
|
139
136
|
}
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
const instance = await factory(moduleOptions);
|
|
138
|
+
if (generation !== initGeneration) {
|
|
139
|
+
return getWasm();
|
|
140
|
+
}
|
|
141
|
+
wasmInstance = instance;
|
|
142
|
+
return instance;
|
|
142
143
|
} catch (err) {
|
|
143
|
-
|
|
144
|
+
if (generation === initGeneration) {
|
|
145
|
+
initPromise = null;
|
|
146
|
+
}
|
|
144
147
|
throw err;
|
|
145
148
|
}
|
|
146
149
|
})();
|
|
@@ -151,27 +154,35 @@ async function isUltraHdr(buffer) {
|
|
|
151
154
|
return wasm.isUltraHdr(new Uint8Array(buffer));
|
|
152
155
|
}
|
|
153
156
|
async function probeUltraHdr(buffer) {
|
|
154
|
-
|
|
155
|
-
|
|
157
|
+
try {
|
|
158
|
+
const wasm = await getWasm();
|
|
159
|
+
return wasm.probeUltraHdr(new Uint8Array(buffer));
|
|
160
|
+
} catch {
|
|
161
|
+
return {
|
|
162
|
+
isValid: false,
|
|
163
|
+
hasPrimaryImage: false,
|
|
164
|
+
hasGainMap: false,
|
|
165
|
+
hasMetadata: false,
|
|
166
|
+
width: 0,
|
|
167
|
+
height: 0,
|
|
168
|
+
gainMapWidth: 0,
|
|
169
|
+
gainMapHeight: 0,
|
|
170
|
+
hdrCapacity: 0,
|
|
171
|
+
metadataVersion: ""
|
|
172
|
+
};
|
|
173
|
+
}
|
|
156
174
|
}
|
|
157
|
-
async function decodeUltraHdr(
|
|
175
|
+
async function decodeUltraHdr(_id, buffer) {
|
|
158
176
|
const wasm = await getWasm();
|
|
159
177
|
return wasm.decodeUltraHdr(new Uint8Array(buffer));
|
|
160
178
|
}
|
|
161
|
-
async function encodeUltraHdr(
|
|
179
|
+
async function encodeUltraHdr(_id, sdrBuffer, hdrBuffer, options) {
|
|
162
180
|
const wasm = await getWasm();
|
|
163
|
-
const
|
|
164
|
-
const mergedOpts = { ...defaultEncodeOptions, ...options };
|
|
165
|
-
wasmOpts.baseQuality = mergedOpts.baseQuality;
|
|
166
|
-
wasmOpts.gainMapQuality = mergedOpts.gainMapQuality;
|
|
167
|
-
wasmOpts.targetHdrCapacity = mergedOpts.targetHdrCapacity;
|
|
168
|
-
wasmOpts.includeIsoMetadata = mergedOpts.includeIsoMetadata;
|
|
169
|
-
wasmOpts.includeUltrahdrV1 = mergedOpts.includeUltrahdrV1;
|
|
170
|
-
wasmOpts.gainMapScale = mergedOpts.gainMapScale;
|
|
181
|
+
const merged = { ...defaultEncodeOptions, ...options };
|
|
171
182
|
const result = wasm.encodeUltraHdr(
|
|
172
183
|
new Uint8Array(sdrBuffer),
|
|
173
184
|
new Float32Array(hdrBuffer),
|
|
174
|
-
|
|
185
|
+
merged
|
|
175
186
|
);
|
|
176
187
|
return result.buffer.slice(
|
|
177
188
|
result.byteOffset,
|
|
@@ -192,18 +203,15 @@ async function getMetadata(buffer) {
|
|
|
192
203
|
}
|
|
193
204
|
async function validateMetadata(metadata) {
|
|
194
205
|
const wasm = await getWasm();
|
|
195
|
-
|
|
196
|
-
return wasm.validateMetadata(wasmMetadata);
|
|
206
|
+
return wasm.validateMetadata(metadata);
|
|
197
207
|
}
|
|
198
208
|
async function estimateHdrHeadroom(metadata) {
|
|
199
209
|
const wasm = await getWasm();
|
|
200
|
-
|
|
201
|
-
return wasm.estimateHdrHeadroom(wasmMetadata);
|
|
210
|
+
return wasm.estimateHdrHeadroom(metadata);
|
|
202
211
|
}
|
|
203
212
|
async function isMeaningfulHdr(metadata) {
|
|
204
213
|
const wasm = await getWasm();
|
|
205
|
-
|
|
206
|
-
return wasm.isMeaningfulHdr(wasmMetadata);
|
|
214
|
+
return wasm.isMeaningfulHdr(metadata);
|
|
207
215
|
}
|
|
208
216
|
// Annotate the CommonJS export names for ESM import in node:
|
|
209
217
|
0 && (module.exports = {
|
|
@@ -220,6 +228,7 @@ async function isMeaningfulHdr(metadata) {
|
|
|
220
228
|
isUltraHdr,
|
|
221
229
|
probeUltraHdr,
|
|
222
230
|
setLocation,
|
|
231
|
+
setWasmUrl,
|
|
223
232
|
smallSizeEncodeOptions,
|
|
224
233
|
validateMetadata
|
|
225
234
|
});
|