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 ADDED
@@ -0,0 +1,31 @@
1
+ # Open UltraHDR
2
+
3
+ TypeScript/JavaScript library for UltraHDR (ISO 21496-1) gain map support.
4
+
5
+ See the [main README](../README.md) for full documentation.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install open-ultrahdr
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { isUltraHdr, extractSdrBase, setLocation } from 'open-ultrahdr';
17
+
18
+ // Set WASM file location
19
+ setLocation('/assets/wasm/');
20
+
21
+ // Check if image is UltraHDR
22
+ const buffer = await file.arrayBuffer();
23
+ if (await isUltraHdr(buffer)) {
24
+ const sdrBuffer = await extractSdrBase(buffer);
25
+ // Use sdrBuffer for display on non-HDR screens
26
+ }
27
+ ```
28
+
29
+ ## License
30
+
31
+ GPL-2.0-or-later
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Unique identifier for an item being processed.
3
+ */
4
+ type ItemId = string;
5
+ /**
6
+ * ISO 21496-1 Gain Map Metadata.
7
+ *
8
+ * Contains all the metadata required to interpret and apply a gain map
9
+ * according to the ISO 21496-1 specification.
10
+ */
11
+ interface GainMapMetadata {
12
+ /** Specification version (e.g., "1.0") */
13
+ version: string;
14
+ /** Whether the base rendition is HDR (false = SDR base, true = HDR base) */
15
+ baseRenditionIsHdr: boolean;
16
+ /** Minimum gain value per channel (RGB), in log2 scale */
17
+ gainMapMin: number[];
18
+ /** Maximum gain value per channel (RGB), in log2 scale */
19
+ gainMapMax: number[];
20
+ /** Gamma correction per channel (RGB) */
21
+ gamma: number[];
22
+ /** SDR offset per channel (RGB), used for black point adjustment */
23
+ offsetSdr: number[];
24
+ /** HDR offset per channel (RGB), used for black point adjustment */
25
+ offsetHdr: number[];
26
+ /** Minimum HDR capacity (log2 scale) where gain map starts to apply */
27
+ hdrCapacityMin: number;
28
+ /** Maximum HDR capacity (log2 scale) for full HDR output */
29
+ hdrCapacityMax: number;
30
+ }
31
+ /**
32
+ * Result of decoding an UltraHDR image.
33
+ */
34
+ interface UltraHdrDecodeResult {
35
+ /** The SDR base image as JPEG bytes */
36
+ sdrImage: Uint8Array;
37
+ /** The gain map as JPEG bytes */
38
+ gainMap: Uint8Array;
39
+ /** Gain map metadata */
40
+ metadata: GainMapMetadata;
41
+ /** Image width in pixels */
42
+ width: number;
43
+ /** Image height in pixels */
44
+ height: number;
45
+ /** Gain map width in pixels (may differ from image width) */
46
+ gainMapWidth: number;
47
+ /** Gain map height in pixels (may differ from image height) */
48
+ gainMapHeight: number;
49
+ }
50
+ /**
51
+ * Options for encoding UltraHDR images.
52
+ */
53
+ interface UltraHdrEncodeOptions {
54
+ /** JPEG quality for the base image (1-100) */
55
+ baseQuality: number;
56
+ /** JPEG quality for the gain map (1-100) */
57
+ gainMapQuality: number;
58
+ /** Target HDR capacity (typically 2.0-4.0) */
59
+ targetHdrCapacity: number;
60
+ /** Whether to include ISO 21496-1 metadata */
61
+ includeIsoMetadata: boolean;
62
+ /** Whether to include UltraHDR v1 metadata for Android compatibility */
63
+ includeUltrahdrV1: boolean;
64
+ /** Downscale factor for the gain map (1 = same size, 2 = half, 4 = quarter) */
65
+ gainMapScale: number;
66
+ }
67
+ /**
68
+ * Color gamut enumeration for HDR images.
69
+ */
70
+ declare enum ColorGamut {
71
+ /** Standard sRGB color space (BT.709 primaries) */
72
+ Srgb = 0,
73
+ /** Display P3 wide color gamut */
74
+ DisplayP3 = 1,
75
+ /** BT.2100/BT.2020 wide color gamut (HDR) */
76
+ Bt2100 = 2
77
+ }
78
+ /**
79
+ * Transfer function for encoding luminance.
80
+ */
81
+ declare enum TransferFunction {
82
+ /** sRGB transfer function (gamma ~2.2) */
83
+ Srgb = 0,
84
+ /** Linear (no gamma) */
85
+ Linear = 1,
86
+ /** Perceptual Quantizer (PQ) - SMPTE ST 2084 */
87
+ Pq = 2,
88
+ /** Hybrid Log-Gamma (HLG) - BT.2100 */
89
+ Hlg = 3
90
+ }
91
+ /**
92
+ * Default encoding options.
93
+ */
94
+ declare const defaultEncodeOptions: UltraHdrEncodeOptions;
95
+ /**
96
+ * High quality encoding options.
97
+ */
98
+ declare const highQualityEncodeOptions: UltraHdrEncodeOptions;
99
+ /**
100
+ * Small size encoding options.
101
+ */
102
+ declare const smallSizeEncodeOptions: UltraHdrEncodeOptions;
103
+
104
+ /**
105
+ * Open UltraHDR Library
106
+ *
107
+ * TypeScript bindings for the UltraHDR WASM library.
108
+ * Provides detection, encoding, and decoding of UltraHDR JPEG images
109
+ * implementing ISO 21496-1 (gain map) specification.
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * import { isUltraHdr, decodeUltraHdr, setLocation } from 'open-ultrahdr';
114
+ *
115
+ * // Set the location for WASM files
116
+ * setLocation('/path/to/wasm/');
117
+ *
118
+ * // Check if an image is UltraHDR
119
+ * const buffer = await file.arrayBuffer();
120
+ * if (await isUltraHdr(buffer)) {
121
+ * const result = await decodeUltraHdr('item-1', buffer);
122
+ * console.log('HDR headroom:', result.metadata.hdrCapacityMax);
123
+ * }
124
+ * ```
125
+ */
126
+
127
+ /**
128
+ * Sets the location/public path for loading WASM files.
129
+ *
130
+ * This must be called before using any other functions when the WASM
131
+ * files are not in the same directory as the JavaScript bundle.
132
+ *
133
+ * @param newLocation - Base URL or path where WASM files are located.
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * // Set location before any other calls
138
+ * setLocation('/assets/wasm/');
139
+ * ```
140
+ */
141
+ declare function setLocation(newLocation: string): void;
142
+ /**
143
+ * Checks if a buffer contains an UltraHDR image.
144
+ *
145
+ * This is a fast check that looks for gain map metadata without
146
+ * fully decoding the image.
147
+ *
148
+ * @param buffer - JPEG file contents.
149
+ * @return True if the image contains UltraHDR/gain map data.
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * const buffer = await file.arrayBuffer();
154
+ * if (await isUltraHdr(buffer)) {
155
+ * console.log('This is an UltraHDR image!');
156
+ * }
157
+ * ```
158
+ */
159
+ declare function isUltraHdr(buffer: ArrayBuffer): Promise<boolean>;
160
+ /**
161
+ * Decodes an UltraHDR image, extracting all components.
162
+ *
163
+ * @param id - Unique identifier for this operation (for cancellation).
164
+ * @param buffer - UltraHDR JPEG file contents.
165
+ * @return Decoded result with SDR image, gain map, and metadata.
166
+ *
167
+ * @throws Error if the buffer is not a valid UltraHDR JPEG.
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const buffer = await file.arrayBuffer();
172
+ * const result = await decodeUltraHdr('upload-1', buffer);
173
+ *
174
+ * // Access components
175
+ * const sdrBlob = new Blob([result.sdrImage], { type: 'image/jpeg' });
176
+ * console.log('Image size:', result.width, 'x', result.height);
177
+ * console.log('HDR capacity:', result.metadata.hdrCapacityMax);
178
+ * ```
179
+ */
180
+ declare function decodeUltraHdr(id: ItemId, buffer: ArrayBuffer): Promise<UltraHdrDecodeResult>;
181
+ /**
182
+ * Encodes an UltraHDR JPEG from SDR and HDR inputs.
183
+ *
184
+ * @param id - Unique identifier for this operation.
185
+ * @param sdrBuffer - SDR JPEG image bytes.
186
+ * @param hdrBuffer - HDR linear RGB data (Float32Array, 3 values per pixel).
187
+ * @param options - Encoding options.
188
+ * @return Encoded UltraHDR JPEG as ArrayBuffer.
189
+ *
190
+ * @throws Error if inputs are invalid or dimensions don't match.
191
+ *
192
+ * @example
193
+ * ```typescript
194
+ * const sdrBuffer = await sdrFile.arrayBuffer();
195
+ * const hdrData = await getHdrLinearData(); // Float32Array
196
+ *
197
+ * const ultraHdr = await encodeUltraHdr('encode-1', sdrBuffer, hdrData, {
198
+ * ...defaultEncodeOptions,
199
+ * targetHdrCapacity: 4.0,
200
+ * });
201
+ *
202
+ * // Create downloadable file
203
+ * const blob = new Blob([ultraHdr], { type: 'image/jpeg' });
204
+ * ```
205
+ */
206
+ declare function encodeUltraHdr(id: ItemId, sdrBuffer: ArrayBuffer, hdrBuffer: ArrayBuffer, options?: Partial<UltraHdrEncodeOptions>): Promise<ArrayBuffer>;
207
+ /**
208
+ * Extracts the SDR base image from an UltraHDR JPEG.
209
+ *
210
+ * This produces a standard JPEG that can be displayed on any device,
211
+ * without the gain map metadata. Useful for backwards compatibility.
212
+ *
213
+ * @param buffer - UltraHDR JPEG file contents.
214
+ * @return Standard JPEG without gain map.
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * const ultraHdrBuffer = await file.arrayBuffer();
219
+ * const sdrBuffer = await extractSdrBase(ultraHdrBuffer);
220
+ *
221
+ * // Use the SDR image for non-HDR displays
222
+ * const blob = new Blob([sdrBuffer], { type: 'image/jpeg' });
223
+ * ```
224
+ */
225
+ declare function extractSdrBase(buffer: ArrayBuffer): Promise<ArrayBuffer>;
226
+ /**
227
+ * Gets gain map metadata from an UltraHDR JPEG.
228
+ *
229
+ * This is faster than `decodeUltraHdr` when you only need the metadata.
230
+ *
231
+ * @param buffer - UltraHDR JPEG file contents.
232
+ * @return Gain map metadata.
233
+ *
234
+ * @throws Error if the buffer doesn't contain gain map metadata.
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * const metadata = await getMetadata(buffer);
239
+ * console.log('Version:', metadata.version);
240
+ * console.log('HDR headroom:', metadata.hdrCapacityMax, 'stops');
241
+ * ```
242
+ */
243
+ declare function getMetadata(buffer: ArrayBuffer): Promise<GainMapMetadata>;
244
+ /**
245
+ * Validates gain map metadata.
246
+ *
247
+ * @param metadata - The metadata to validate.
248
+ * @return True if the metadata is valid.
249
+ */
250
+ declare function validateMetadata(metadata: GainMapMetadata): Promise<boolean>;
251
+ /**
252
+ * Estimates the HDR headroom from metadata.
253
+ *
254
+ * @param metadata - The gain map metadata.
255
+ * @return Maximum additional stops of dynamic range above SDR.
256
+ */
257
+ declare function estimateHdrHeadroom(metadata: GainMapMetadata): Promise<number>;
258
+ /**
259
+ * Checks if metadata indicates a meaningful HDR image.
260
+ *
261
+ * @param metadata - The gain map metadata.
262
+ * @return True if the gain map provides significant dynamic range extension.
263
+ */
264
+ declare function isMeaningfulHdr(metadata: GainMapMetadata): Promise<boolean>;
265
+
266
+ export { ColorGamut, type GainMapMetadata, type ItemId, TransferFunction, type UltraHdrDecodeResult, type UltraHdrEncodeOptions, decodeUltraHdr, defaultEncodeOptions, encodeUltraHdr, estimateHdrHeadroom, extractSdrBase, getMetadata, highQualityEncodeOptions, isMeaningfulHdr, isUltraHdr, setLocation, smallSizeEncodeOptions, validateMetadata };
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Unique identifier for an item being processed.
3
+ */
4
+ type ItemId = string;
5
+ /**
6
+ * ISO 21496-1 Gain Map Metadata.
7
+ *
8
+ * Contains all the metadata required to interpret and apply a gain map
9
+ * according to the ISO 21496-1 specification.
10
+ */
11
+ interface GainMapMetadata {
12
+ /** Specification version (e.g., "1.0") */
13
+ version: string;
14
+ /** Whether the base rendition is HDR (false = SDR base, true = HDR base) */
15
+ baseRenditionIsHdr: boolean;
16
+ /** Minimum gain value per channel (RGB), in log2 scale */
17
+ gainMapMin: number[];
18
+ /** Maximum gain value per channel (RGB), in log2 scale */
19
+ gainMapMax: number[];
20
+ /** Gamma correction per channel (RGB) */
21
+ gamma: number[];
22
+ /** SDR offset per channel (RGB), used for black point adjustment */
23
+ offsetSdr: number[];
24
+ /** HDR offset per channel (RGB), used for black point adjustment */
25
+ offsetHdr: number[];
26
+ /** Minimum HDR capacity (log2 scale) where gain map starts to apply */
27
+ hdrCapacityMin: number;
28
+ /** Maximum HDR capacity (log2 scale) for full HDR output */
29
+ hdrCapacityMax: number;
30
+ }
31
+ /**
32
+ * Result of decoding an UltraHDR image.
33
+ */
34
+ interface UltraHdrDecodeResult {
35
+ /** The SDR base image as JPEG bytes */
36
+ sdrImage: Uint8Array;
37
+ /** The gain map as JPEG bytes */
38
+ gainMap: Uint8Array;
39
+ /** Gain map metadata */
40
+ metadata: GainMapMetadata;
41
+ /** Image width in pixels */
42
+ width: number;
43
+ /** Image height in pixels */
44
+ height: number;
45
+ /** Gain map width in pixels (may differ from image width) */
46
+ gainMapWidth: number;
47
+ /** Gain map height in pixels (may differ from image height) */
48
+ gainMapHeight: number;
49
+ }
50
+ /**
51
+ * Options for encoding UltraHDR images.
52
+ */
53
+ interface UltraHdrEncodeOptions {
54
+ /** JPEG quality for the base image (1-100) */
55
+ baseQuality: number;
56
+ /** JPEG quality for the gain map (1-100) */
57
+ gainMapQuality: number;
58
+ /** Target HDR capacity (typically 2.0-4.0) */
59
+ targetHdrCapacity: number;
60
+ /** Whether to include ISO 21496-1 metadata */
61
+ includeIsoMetadata: boolean;
62
+ /** Whether to include UltraHDR v1 metadata for Android compatibility */
63
+ includeUltrahdrV1: boolean;
64
+ /** Downscale factor for the gain map (1 = same size, 2 = half, 4 = quarter) */
65
+ gainMapScale: number;
66
+ }
67
+ /**
68
+ * Color gamut enumeration for HDR images.
69
+ */
70
+ declare enum ColorGamut {
71
+ /** Standard sRGB color space (BT.709 primaries) */
72
+ Srgb = 0,
73
+ /** Display P3 wide color gamut */
74
+ DisplayP3 = 1,
75
+ /** BT.2100/BT.2020 wide color gamut (HDR) */
76
+ Bt2100 = 2
77
+ }
78
+ /**
79
+ * Transfer function for encoding luminance.
80
+ */
81
+ declare enum TransferFunction {
82
+ /** sRGB transfer function (gamma ~2.2) */
83
+ Srgb = 0,
84
+ /** Linear (no gamma) */
85
+ Linear = 1,
86
+ /** Perceptual Quantizer (PQ) - SMPTE ST 2084 */
87
+ Pq = 2,
88
+ /** Hybrid Log-Gamma (HLG) - BT.2100 */
89
+ Hlg = 3
90
+ }
91
+ /**
92
+ * Default encoding options.
93
+ */
94
+ declare const defaultEncodeOptions: UltraHdrEncodeOptions;
95
+ /**
96
+ * High quality encoding options.
97
+ */
98
+ declare const highQualityEncodeOptions: UltraHdrEncodeOptions;
99
+ /**
100
+ * Small size encoding options.
101
+ */
102
+ declare const smallSizeEncodeOptions: UltraHdrEncodeOptions;
103
+
104
+ /**
105
+ * Open UltraHDR Library
106
+ *
107
+ * TypeScript bindings for the UltraHDR WASM library.
108
+ * Provides detection, encoding, and decoding of UltraHDR JPEG images
109
+ * implementing ISO 21496-1 (gain map) specification.
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * import { isUltraHdr, decodeUltraHdr, setLocation } from 'open-ultrahdr';
114
+ *
115
+ * // Set the location for WASM files
116
+ * setLocation('/path/to/wasm/');
117
+ *
118
+ * // Check if an image is UltraHDR
119
+ * const buffer = await file.arrayBuffer();
120
+ * if (await isUltraHdr(buffer)) {
121
+ * const result = await decodeUltraHdr('item-1', buffer);
122
+ * console.log('HDR headroom:', result.metadata.hdrCapacityMax);
123
+ * }
124
+ * ```
125
+ */
126
+
127
+ /**
128
+ * Sets the location/public path for loading WASM files.
129
+ *
130
+ * This must be called before using any other functions when the WASM
131
+ * files are not in the same directory as the JavaScript bundle.
132
+ *
133
+ * @param newLocation - Base URL or path where WASM files are located.
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * // Set location before any other calls
138
+ * setLocation('/assets/wasm/');
139
+ * ```
140
+ */
141
+ declare function setLocation(newLocation: string): void;
142
+ /**
143
+ * Checks if a buffer contains an UltraHDR image.
144
+ *
145
+ * This is a fast check that looks for gain map metadata without
146
+ * fully decoding the image.
147
+ *
148
+ * @param buffer - JPEG file contents.
149
+ * @return True if the image contains UltraHDR/gain map data.
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * const buffer = await file.arrayBuffer();
154
+ * if (await isUltraHdr(buffer)) {
155
+ * console.log('This is an UltraHDR image!');
156
+ * }
157
+ * ```
158
+ */
159
+ declare function isUltraHdr(buffer: ArrayBuffer): Promise<boolean>;
160
+ /**
161
+ * Decodes an UltraHDR image, extracting all components.
162
+ *
163
+ * @param id - Unique identifier for this operation (for cancellation).
164
+ * @param buffer - UltraHDR JPEG file contents.
165
+ * @return Decoded result with SDR image, gain map, and metadata.
166
+ *
167
+ * @throws Error if the buffer is not a valid UltraHDR JPEG.
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const buffer = await file.arrayBuffer();
172
+ * const result = await decodeUltraHdr('upload-1', buffer);
173
+ *
174
+ * // Access components
175
+ * const sdrBlob = new Blob([result.sdrImage], { type: 'image/jpeg' });
176
+ * console.log('Image size:', result.width, 'x', result.height);
177
+ * console.log('HDR capacity:', result.metadata.hdrCapacityMax);
178
+ * ```
179
+ */
180
+ declare function decodeUltraHdr(id: ItemId, buffer: ArrayBuffer): Promise<UltraHdrDecodeResult>;
181
+ /**
182
+ * Encodes an UltraHDR JPEG from SDR and HDR inputs.
183
+ *
184
+ * @param id - Unique identifier for this operation.
185
+ * @param sdrBuffer - SDR JPEG image bytes.
186
+ * @param hdrBuffer - HDR linear RGB data (Float32Array, 3 values per pixel).
187
+ * @param options - Encoding options.
188
+ * @return Encoded UltraHDR JPEG as ArrayBuffer.
189
+ *
190
+ * @throws Error if inputs are invalid or dimensions don't match.
191
+ *
192
+ * @example
193
+ * ```typescript
194
+ * const sdrBuffer = await sdrFile.arrayBuffer();
195
+ * const hdrData = await getHdrLinearData(); // Float32Array
196
+ *
197
+ * const ultraHdr = await encodeUltraHdr('encode-1', sdrBuffer, hdrData, {
198
+ * ...defaultEncodeOptions,
199
+ * targetHdrCapacity: 4.0,
200
+ * });
201
+ *
202
+ * // Create downloadable file
203
+ * const blob = new Blob([ultraHdr], { type: 'image/jpeg' });
204
+ * ```
205
+ */
206
+ declare function encodeUltraHdr(id: ItemId, sdrBuffer: ArrayBuffer, hdrBuffer: ArrayBuffer, options?: Partial<UltraHdrEncodeOptions>): Promise<ArrayBuffer>;
207
+ /**
208
+ * Extracts the SDR base image from an UltraHDR JPEG.
209
+ *
210
+ * This produces a standard JPEG that can be displayed on any device,
211
+ * without the gain map metadata. Useful for backwards compatibility.
212
+ *
213
+ * @param buffer - UltraHDR JPEG file contents.
214
+ * @return Standard JPEG without gain map.
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * const ultraHdrBuffer = await file.arrayBuffer();
219
+ * const sdrBuffer = await extractSdrBase(ultraHdrBuffer);
220
+ *
221
+ * // Use the SDR image for non-HDR displays
222
+ * const blob = new Blob([sdrBuffer], { type: 'image/jpeg' });
223
+ * ```
224
+ */
225
+ declare function extractSdrBase(buffer: ArrayBuffer): Promise<ArrayBuffer>;
226
+ /**
227
+ * Gets gain map metadata from an UltraHDR JPEG.
228
+ *
229
+ * This is faster than `decodeUltraHdr` when you only need the metadata.
230
+ *
231
+ * @param buffer - UltraHDR JPEG file contents.
232
+ * @return Gain map metadata.
233
+ *
234
+ * @throws Error if the buffer doesn't contain gain map metadata.
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * const metadata = await getMetadata(buffer);
239
+ * console.log('Version:', metadata.version);
240
+ * console.log('HDR headroom:', metadata.hdrCapacityMax, 'stops');
241
+ * ```
242
+ */
243
+ declare function getMetadata(buffer: ArrayBuffer): Promise<GainMapMetadata>;
244
+ /**
245
+ * Validates gain map metadata.
246
+ *
247
+ * @param metadata - The metadata to validate.
248
+ * @return True if the metadata is valid.
249
+ */
250
+ declare function validateMetadata(metadata: GainMapMetadata): Promise<boolean>;
251
+ /**
252
+ * Estimates the HDR headroom from metadata.
253
+ *
254
+ * @param metadata - The gain map metadata.
255
+ * @return Maximum additional stops of dynamic range above SDR.
256
+ */
257
+ declare function estimateHdrHeadroom(metadata: GainMapMetadata): Promise<number>;
258
+ /**
259
+ * Checks if metadata indicates a meaningful HDR image.
260
+ *
261
+ * @param metadata - The gain map metadata.
262
+ * @return True if the gain map provides significant dynamic range extension.
263
+ */
264
+ declare function isMeaningfulHdr(metadata: GainMapMetadata): Promise<boolean>;
265
+
266
+ export { ColorGamut, type GainMapMetadata, type ItemId, TransferFunction, type UltraHdrDecodeResult, type UltraHdrEncodeOptions, decodeUltraHdr, defaultEncodeOptions, encodeUltraHdr, estimateHdrHeadroom, extractSdrBase, getMetadata, highQualityEncodeOptions, isMeaningfulHdr, isUltraHdr, setLocation, smallSizeEncodeOptions, validateMetadata };