open-ultrahdr 0.1.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 +31 -0
- package/dist/index.d.mts +266 -0
- package/dist/index.d.ts +266 -0
- package/dist/index.js +201 -0
- package/dist/index.mjs +151 -0
- package/package.json +72 -0
- package/src/index.ts +368 -0
- package/src/types.ts +150 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Open UltraHDR Library
|
|
3
|
+
*
|
|
4
|
+
* TypeScript bindings for the UltraHDR WASM library.
|
|
5
|
+
* Provides detection, encoding, and decoding of UltraHDR JPEG images
|
|
6
|
+
* implementing ISO 21496-1 (gain map) specification.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { isUltraHdr, decodeUltraHdr, setLocation } from 'open-ultrahdr';
|
|
11
|
+
*
|
|
12
|
+
* // Set the location for WASM files
|
|
13
|
+
* setLocation('/path/to/wasm/');
|
|
14
|
+
*
|
|
15
|
+
* // Check if an image is UltraHDR
|
|
16
|
+
* const buffer = await file.arrayBuffer();
|
|
17
|
+
* if (await isUltraHdr(buffer)) {
|
|
18
|
+
* const result = await decodeUltraHdr('item-1', buffer);
|
|
19
|
+
* console.log('HDR headroom:', result.metadata.hdrCapacityMax);
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// Re-export types
|
|
25
|
+
export type { ItemId, GainMapMetadata, UltraHdrDecodeResult, UltraHdrEncodeOptions } from './types';
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
ColorGamut,
|
|
29
|
+
TransferFunction,
|
|
30
|
+
defaultEncodeOptions,
|
|
31
|
+
highQualityEncodeOptions,
|
|
32
|
+
smallSizeEncodeOptions,
|
|
33
|
+
} from './types';
|
|
34
|
+
|
|
35
|
+
import type { ItemId, GainMapMetadata, UltraHdrDecodeResult, UltraHdrEncodeOptions } from './types';
|
|
36
|
+
|
|
37
|
+
import { defaultEncodeOptions } from './types';
|
|
38
|
+
|
|
39
|
+
// WASM class types (these are actual classes from the generated WASM bindings)
|
|
40
|
+
interface WasmUltraHdrEncodeOptions {
|
|
41
|
+
baseQuality: number;
|
|
42
|
+
gainMapQuality: number;
|
|
43
|
+
targetHdrCapacity: number;
|
|
44
|
+
includeIsoMetadata: boolean;
|
|
45
|
+
includeUltrahdrV1: boolean;
|
|
46
|
+
gainMapScale: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface WasmGainMapMetadata {
|
|
50
|
+
version: string;
|
|
51
|
+
baseRenditionIsHdr: boolean;
|
|
52
|
+
gainMapMin: number[];
|
|
53
|
+
gainMapMax: number[];
|
|
54
|
+
gamma: number[];
|
|
55
|
+
offsetSdr: number[];
|
|
56
|
+
offsetHdr: number[];
|
|
57
|
+
hdrCapacityMin: number;
|
|
58
|
+
hdrCapacityMax: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// WASM module type (these come from the generated WASM bindings)
|
|
62
|
+
interface UltraHdrWasmModule {
|
|
63
|
+
default: (moduleOrPath?: string | URL | Response | BufferSource) => Promise<unknown>;
|
|
64
|
+
isUltraHdr: (buffer: Uint8Array) => boolean;
|
|
65
|
+
decodeUltraHdr: (buffer: Uint8Array) => UltraHdrDecodeResult;
|
|
66
|
+
encodeUltraHdr: (
|
|
67
|
+
sdrBuffer: Uint8Array,
|
|
68
|
+
hdrBuffer: Float32Array,
|
|
69
|
+
options: WasmUltraHdrEncodeOptions
|
|
70
|
+
) => Uint8Array;
|
|
71
|
+
extractSdrBase: (buffer: Uint8Array) => Uint8Array;
|
|
72
|
+
getMetadata: (buffer: Uint8Array) => WasmGainMapMetadata;
|
|
73
|
+
createDefaultOptions: () => WasmUltraHdrEncodeOptions;
|
|
74
|
+
createHighQualityOptions: () => WasmUltraHdrEncodeOptions;
|
|
75
|
+
createSmallSizeOptions: () => WasmUltraHdrEncodeOptions;
|
|
76
|
+
createDefaultMetadata: () => WasmGainMapMetadata;
|
|
77
|
+
validateMetadata: (metadata: WasmGainMapMetadata) => boolean;
|
|
78
|
+
estimateHdrHeadroom: (metadata: WasmGainMapMetadata) => number;
|
|
79
|
+
isMeaningfulHdr: (metadata: WasmGainMapMetadata) => boolean;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Location prefix for WASM files.
|
|
84
|
+
* Set this before calling any other functions.
|
|
85
|
+
*/
|
|
86
|
+
let location = '';
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Cached WASM module instance.
|
|
90
|
+
*/
|
|
91
|
+
let wasmInstance: UltraHdrWasmModule | null = null;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Promise for ongoing WASM initialization.
|
|
95
|
+
*/
|
|
96
|
+
let initPromise: Promise<UltraHdrWasmModule> | null = null;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Sets the location/public path for loading WASM files.
|
|
100
|
+
*
|
|
101
|
+
* This must be called before using any other functions when the WASM
|
|
102
|
+
* files are not in the same directory as the JavaScript bundle.
|
|
103
|
+
*
|
|
104
|
+
* @param newLocation - Base URL or path where WASM files are located.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* // Set location before any other calls
|
|
109
|
+
* setLocation('/assets/wasm/');
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export function setLocation(newLocation: string): void {
|
|
113
|
+
location = newLocation;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Checks if metadata is a WASM class instance (has __wbg_ptr property).
|
|
118
|
+
*/
|
|
119
|
+
function isWasmMetadataInstance(metadata: unknown): boolean {
|
|
120
|
+
return typeof metadata === 'object' && metadata !== null && '__wbg_ptr' in metadata;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Converts a plain metadata object to a WASM class instance.
|
|
125
|
+
*/
|
|
126
|
+
async function toWasmMetadata(metadata: GainMapMetadata): Promise<WasmGainMapMetadata> {
|
|
127
|
+
// If it's already a WASM instance, return as-is
|
|
128
|
+
if (isWasmMetadataInstance(metadata)) {
|
|
129
|
+
return metadata as unknown as WasmGainMapMetadata;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Create a new WASM instance and copy properties
|
|
133
|
+
const wasm = await getWasm();
|
|
134
|
+
const wasmMetadata = wasm.createDefaultMetadata();
|
|
135
|
+
|
|
136
|
+
wasmMetadata.version = metadata.version;
|
|
137
|
+
wasmMetadata.baseRenditionIsHdr = metadata.baseRenditionIsHdr;
|
|
138
|
+
wasmMetadata.gainMapMin = metadata.gainMapMin;
|
|
139
|
+
wasmMetadata.gainMapMax = metadata.gainMapMax;
|
|
140
|
+
wasmMetadata.gamma = metadata.gamma;
|
|
141
|
+
wasmMetadata.offsetSdr = metadata.offsetSdr;
|
|
142
|
+
wasmMetadata.offsetHdr = metadata.offsetHdr;
|
|
143
|
+
wasmMetadata.hdrCapacityMin = metadata.hdrCapacityMin;
|
|
144
|
+
wasmMetadata.hdrCapacityMax = metadata.hdrCapacityMax;
|
|
145
|
+
|
|
146
|
+
return wasmMetadata;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Gets the WASM module, initializing it if necessary.
|
|
151
|
+
*/
|
|
152
|
+
async function getWasm(): Promise<UltraHdrWasmModule> {
|
|
153
|
+
if (wasmInstance) {
|
|
154
|
+
return wasmInstance;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (initPromise) {
|
|
158
|
+
return initPromise;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
initPromise = (async () => {
|
|
162
|
+
// Dynamic import of the WASM package
|
|
163
|
+
const UltraHdrWasm = (await import('open-ultrahdr-wasm')) as unknown as UltraHdrWasmModule;
|
|
164
|
+
|
|
165
|
+
// Initialize WASM with the location prefix for the .wasm file
|
|
166
|
+
// If location is set, construct the full URL to the WASM file
|
|
167
|
+
if (location) {
|
|
168
|
+
const wasmUrl = location + 'open_ultrahdr_bg.wasm';
|
|
169
|
+
await UltraHdrWasm.default(wasmUrl);
|
|
170
|
+
} else {
|
|
171
|
+
// Let the WASM module use its default URL resolution (import.meta.url)
|
|
172
|
+
await UltraHdrWasm.default();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
wasmInstance = UltraHdrWasm as unknown as UltraHdrWasmModule;
|
|
176
|
+
return wasmInstance;
|
|
177
|
+
})();
|
|
178
|
+
|
|
179
|
+
return initPromise;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Checks if a buffer contains an UltraHDR image.
|
|
184
|
+
*
|
|
185
|
+
* This is a fast check that looks for gain map metadata without
|
|
186
|
+
* fully decoding the image.
|
|
187
|
+
*
|
|
188
|
+
* @param buffer - JPEG file contents.
|
|
189
|
+
* @return True if the image contains UltraHDR/gain map data.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```typescript
|
|
193
|
+
* const buffer = await file.arrayBuffer();
|
|
194
|
+
* if (await isUltraHdr(buffer)) {
|
|
195
|
+
* console.log('This is an UltraHDR image!');
|
|
196
|
+
* }
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export async function isUltraHdr(buffer: ArrayBuffer): Promise<boolean> {
|
|
200
|
+
const wasm = await getWasm();
|
|
201
|
+
return wasm.isUltraHdr(new Uint8Array(buffer));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Decodes an UltraHDR image, extracting all components.
|
|
206
|
+
*
|
|
207
|
+
* @param id - Unique identifier for this operation (for cancellation).
|
|
208
|
+
* @param buffer - UltraHDR JPEG file contents.
|
|
209
|
+
* @return Decoded result with SDR image, gain map, and metadata.
|
|
210
|
+
*
|
|
211
|
+
* @throws Error if the buffer is not a valid UltraHDR JPEG.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* const buffer = await file.arrayBuffer();
|
|
216
|
+
* const result = await decodeUltraHdr('upload-1', buffer);
|
|
217
|
+
*
|
|
218
|
+
* // Access components
|
|
219
|
+
* const sdrBlob = new Blob([result.sdrImage], { type: 'image/jpeg' });
|
|
220
|
+
* console.log('Image size:', result.width, 'x', result.height);
|
|
221
|
+
* console.log('HDR capacity:', result.metadata.hdrCapacityMax);
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
export async function decodeUltraHdr(
|
|
225
|
+
id: ItemId,
|
|
226
|
+
buffer: ArrayBuffer
|
|
227
|
+
): Promise<UltraHdrDecodeResult> {
|
|
228
|
+
const wasm = await getWasm();
|
|
229
|
+
return wasm.decodeUltraHdr(new Uint8Array(buffer));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Encodes an UltraHDR JPEG from SDR and HDR inputs.
|
|
234
|
+
*
|
|
235
|
+
* @param id - Unique identifier for this operation.
|
|
236
|
+
* @param sdrBuffer - SDR JPEG image bytes.
|
|
237
|
+
* @param hdrBuffer - HDR linear RGB data (Float32Array, 3 values per pixel).
|
|
238
|
+
* @param options - Encoding options.
|
|
239
|
+
* @return Encoded UltraHDR JPEG as ArrayBuffer.
|
|
240
|
+
*
|
|
241
|
+
* @throws Error if inputs are invalid or dimensions don't match.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```typescript
|
|
245
|
+
* const sdrBuffer = await sdrFile.arrayBuffer();
|
|
246
|
+
* const hdrData = await getHdrLinearData(); // Float32Array
|
|
247
|
+
*
|
|
248
|
+
* const ultraHdr = await encodeUltraHdr('encode-1', sdrBuffer, hdrData, {
|
|
249
|
+
* ...defaultEncodeOptions,
|
|
250
|
+
* targetHdrCapacity: 4.0,
|
|
251
|
+
* });
|
|
252
|
+
*
|
|
253
|
+
* // Create downloadable file
|
|
254
|
+
* const blob = new Blob([ultraHdr], { type: 'image/jpeg' });
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export async function encodeUltraHdr(
|
|
258
|
+
id: ItemId,
|
|
259
|
+
sdrBuffer: ArrayBuffer,
|
|
260
|
+
hdrBuffer: ArrayBuffer,
|
|
261
|
+
options?: Partial<UltraHdrEncodeOptions>
|
|
262
|
+
): Promise<ArrayBuffer> {
|
|
263
|
+
const wasm = await getWasm();
|
|
264
|
+
|
|
265
|
+
// Create a proper WASM options instance
|
|
266
|
+
const wasmOpts = wasm.createDefaultOptions();
|
|
267
|
+
|
|
268
|
+
// Apply user-provided options
|
|
269
|
+
const mergedOpts = { ...defaultEncodeOptions, ...options };
|
|
270
|
+
wasmOpts.baseQuality = mergedOpts.baseQuality;
|
|
271
|
+
wasmOpts.gainMapQuality = mergedOpts.gainMapQuality;
|
|
272
|
+
wasmOpts.targetHdrCapacity = mergedOpts.targetHdrCapacity;
|
|
273
|
+
wasmOpts.includeIsoMetadata = mergedOpts.includeIsoMetadata;
|
|
274
|
+
wasmOpts.includeUltrahdrV1 = mergedOpts.includeUltrahdrV1;
|
|
275
|
+
wasmOpts.gainMapScale = mergedOpts.gainMapScale;
|
|
276
|
+
|
|
277
|
+
const result = wasm.encodeUltraHdr(
|
|
278
|
+
new Uint8Array(sdrBuffer),
|
|
279
|
+
new Float32Array(hdrBuffer),
|
|
280
|
+
wasmOpts
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
// Ensure we return a proper ArrayBuffer (not SharedArrayBuffer)
|
|
284
|
+
return result.buffer.slice(0) as ArrayBuffer;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Extracts the SDR base image from an UltraHDR JPEG.
|
|
289
|
+
*
|
|
290
|
+
* This produces a standard JPEG that can be displayed on any device,
|
|
291
|
+
* without the gain map metadata. Useful for backwards compatibility.
|
|
292
|
+
*
|
|
293
|
+
* @param buffer - UltraHDR JPEG file contents.
|
|
294
|
+
* @return Standard JPEG without gain map.
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* ```typescript
|
|
298
|
+
* const ultraHdrBuffer = await file.arrayBuffer();
|
|
299
|
+
* const sdrBuffer = await extractSdrBase(ultraHdrBuffer);
|
|
300
|
+
*
|
|
301
|
+
* // Use the SDR image for non-HDR displays
|
|
302
|
+
* const blob = new Blob([sdrBuffer], { type: 'image/jpeg' });
|
|
303
|
+
* ```
|
|
304
|
+
*/
|
|
305
|
+
export async function extractSdrBase(buffer: ArrayBuffer): Promise<ArrayBuffer> {
|
|
306
|
+
const wasm = await getWasm();
|
|
307
|
+
const result = wasm.extractSdrBase(new Uint8Array(buffer));
|
|
308
|
+
// Ensure we return a proper ArrayBuffer (not SharedArrayBuffer)
|
|
309
|
+
return result.buffer.slice(0) as ArrayBuffer;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Gets gain map metadata from an UltraHDR JPEG.
|
|
314
|
+
*
|
|
315
|
+
* This is faster than `decodeUltraHdr` when you only need the metadata.
|
|
316
|
+
*
|
|
317
|
+
* @param buffer - UltraHDR JPEG file contents.
|
|
318
|
+
* @return Gain map metadata.
|
|
319
|
+
*
|
|
320
|
+
* @throws Error if the buffer doesn't contain gain map metadata.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```typescript
|
|
324
|
+
* const metadata = await getMetadata(buffer);
|
|
325
|
+
* console.log('Version:', metadata.version);
|
|
326
|
+
* console.log('HDR headroom:', metadata.hdrCapacityMax, 'stops');
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
export async function getMetadata(buffer: ArrayBuffer): Promise<GainMapMetadata> {
|
|
330
|
+
const wasm = await getWasm();
|
|
331
|
+
return wasm.getMetadata(new Uint8Array(buffer));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Validates gain map metadata.
|
|
336
|
+
*
|
|
337
|
+
* @param metadata - The metadata to validate.
|
|
338
|
+
* @return True if the metadata is valid.
|
|
339
|
+
*/
|
|
340
|
+
export async function validateMetadata(metadata: GainMapMetadata): Promise<boolean> {
|
|
341
|
+
const wasm = await getWasm();
|
|
342
|
+
const wasmMetadata = await toWasmMetadata(metadata);
|
|
343
|
+
return wasm.validateMetadata(wasmMetadata);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Estimates the HDR headroom from metadata.
|
|
348
|
+
*
|
|
349
|
+
* @param metadata - The gain map metadata.
|
|
350
|
+
* @return Maximum additional stops of dynamic range above SDR.
|
|
351
|
+
*/
|
|
352
|
+
export async function estimateHdrHeadroom(metadata: GainMapMetadata): Promise<number> {
|
|
353
|
+
const wasm = await getWasm();
|
|
354
|
+
const wasmMetadata = await toWasmMetadata(metadata);
|
|
355
|
+
return wasm.estimateHdrHeadroom(wasmMetadata);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Checks if metadata indicates a meaningful HDR image.
|
|
360
|
+
*
|
|
361
|
+
* @param metadata - The gain map metadata.
|
|
362
|
+
* @return True if the gain map provides significant dynamic range extension.
|
|
363
|
+
*/
|
|
364
|
+
export async function isMeaningfulHdr(metadata: GainMapMetadata): Promise<boolean> {
|
|
365
|
+
const wasm = await getWasm();
|
|
366
|
+
const wasmMetadata = await toWasmMetadata(metadata);
|
|
367
|
+
return wasm.isMeaningfulHdr(wasmMetadata);
|
|
368
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unique identifier for an item being processed.
|
|
3
|
+
*/
|
|
4
|
+
export type ItemId = string;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ISO 21496-1 Gain Map Metadata.
|
|
8
|
+
*
|
|
9
|
+
* Contains all the metadata required to interpret and apply a gain map
|
|
10
|
+
* according to the ISO 21496-1 specification.
|
|
11
|
+
*/
|
|
12
|
+
export interface GainMapMetadata {
|
|
13
|
+
/** Specification version (e.g., "1.0") */
|
|
14
|
+
version: string;
|
|
15
|
+
|
|
16
|
+
/** Whether the base rendition is HDR (false = SDR base, true = HDR base) */
|
|
17
|
+
baseRenditionIsHdr: boolean;
|
|
18
|
+
|
|
19
|
+
/** Minimum gain value per channel (RGB), in log2 scale */
|
|
20
|
+
gainMapMin: number[];
|
|
21
|
+
|
|
22
|
+
/** Maximum gain value per channel (RGB), in log2 scale */
|
|
23
|
+
gainMapMax: number[];
|
|
24
|
+
|
|
25
|
+
/** Gamma correction per channel (RGB) */
|
|
26
|
+
gamma: number[];
|
|
27
|
+
|
|
28
|
+
/** SDR offset per channel (RGB), used for black point adjustment */
|
|
29
|
+
offsetSdr: number[];
|
|
30
|
+
|
|
31
|
+
/** HDR offset per channel (RGB), used for black point adjustment */
|
|
32
|
+
offsetHdr: number[];
|
|
33
|
+
|
|
34
|
+
/** Minimum HDR capacity (log2 scale) where gain map starts to apply */
|
|
35
|
+
hdrCapacityMin: number;
|
|
36
|
+
|
|
37
|
+
/** Maximum HDR capacity (log2 scale) for full HDR output */
|
|
38
|
+
hdrCapacityMax: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Result of decoding an UltraHDR image.
|
|
43
|
+
*/
|
|
44
|
+
export interface UltraHdrDecodeResult {
|
|
45
|
+
/** The SDR base image as JPEG bytes */
|
|
46
|
+
sdrImage: Uint8Array;
|
|
47
|
+
|
|
48
|
+
/** The gain map as JPEG bytes */
|
|
49
|
+
gainMap: Uint8Array;
|
|
50
|
+
|
|
51
|
+
/** Gain map metadata */
|
|
52
|
+
metadata: GainMapMetadata;
|
|
53
|
+
|
|
54
|
+
/** Image width in pixels */
|
|
55
|
+
width: number;
|
|
56
|
+
|
|
57
|
+
/** Image height in pixels */
|
|
58
|
+
height: number;
|
|
59
|
+
|
|
60
|
+
/** Gain map width in pixels (may differ from image width) */
|
|
61
|
+
gainMapWidth: number;
|
|
62
|
+
|
|
63
|
+
/** Gain map height in pixels (may differ from image height) */
|
|
64
|
+
gainMapHeight: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Options for encoding UltraHDR images.
|
|
69
|
+
*/
|
|
70
|
+
export interface UltraHdrEncodeOptions {
|
|
71
|
+
/** JPEG quality for the base image (1-100) */
|
|
72
|
+
baseQuality: number;
|
|
73
|
+
|
|
74
|
+
/** JPEG quality for the gain map (1-100) */
|
|
75
|
+
gainMapQuality: number;
|
|
76
|
+
|
|
77
|
+
/** Target HDR capacity (typically 2.0-4.0) */
|
|
78
|
+
targetHdrCapacity: number;
|
|
79
|
+
|
|
80
|
+
/** Whether to include ISO 21496-1 metadata */
|
|
81
|
+
includeIsoMetadata: boolean;
|
|
82
|
+
|
|
83
|
+
/** Whether to include UltraHDR v1 metadata for Android compatibility */
|
|
84
|
+
includeUltrahdrV1: boolean;
|
|
85
|
+
|
|
86
|
+
/** Downscale factor for the gain map (1 = same size, 2 = half, 4 = quarter) */
|
|
87
|
+
gainMapScale: number;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Color gamut enumeration for HDR images.
|
|
92
|
+
*/
|
|
93
|
+
export enum ColorGamut {
|
|
94
|
+
/** Standard sRGB color space (BT.709 primaries) */
|
|
95
|
+
Srgb = 0,
|
|
96
|
+
/** Display P3 wide color gamut */
|
|
97
|
+
DisplayP3 = 1,
|
|
98
|
+
/** BT.2100/BT.2020 wide color gamut (HDR) */
|
|
99
|
+
Bt2100 = 2,
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Transfer function for encoding luminance.
|
|
104
|
+
*/
|
|
105
|
+
export enum TransferFunction {
|
|
106
|
+
/** sRGB transfer function (gamma ~2.2) */
|
|
107
|
+
Srgb = 0,
|
|
108
|
+
/** Linear (no gamma) */
|
|
109
|
+
Linear = 1,
|
|
110
|
+
/** Perceptual Quantizer (PQ) - SMPTE ST 2084 */
|
|
111
|
+
Pq = 2,
|
|
112
|
+
/** Hybrid Log-Gamma (HLG) - BT.2100 */
|
|
113
|
+
Hlg = 3,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Default encoding options.
|
|
118
|
+
*/
|
|
119
|
+
export const defaultEncodeOptions: UltraHdrEncodeOptions = {
|
|
120
|
+
baseQuality: 85,
|
|
121
|
+
gainMapQuality: 75,
|
|
122
|
+
targetHdrCapacity: 3.0,
|
|
123
|
+
includeIsoMetadata: true,
|
|
124
|
+
includeUltrahdrV1: true,
|
|
125
|
+
gainMapScale: 1,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* High quality encoding options.
|
|
130
|
+
*/
|
|
131
|
+
export const highQualityEncodeOptions: UltraHdrEncodeOptions = {
|
|
132
|
+
baseQuality: 95,
|
|
133
|
+
gainMapQuality: 85,
|
|
134
|
+
targetHdrCapacity: 4.0,
|
|
135
|
+
includeIsoMetadata: true,
|
|
136
|
+
includeUltrahdrV1: true,
|
|
137
|
+
gainMapScale: 1,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Small size encoding options.
|
|
142
|
+
*/
|
|
143
|
+
export const smallSizeEncodeOptions: UltraHdrEncodeOptions = {
|
|
144
|
+
baseQuality: 75,
|
|
145
|
+
gainMapQuality: 65,
|
|
146
|
+
targetHdrCapacity: 3.0,
|
|
147
|
+
includeIsoMetadata: true,
|
|
148
|
+
includeUltrahdrV1: true,
|
|
149
|
+
gainMapScale: 2,
|
|
150
|
+
};
|