open-ultrahdr 0.1.0 → 0.1.1

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/dist/index.d.mts CHANGED
@@ -28,6 +28,34 @@ interface GainMapMetadata {
28
28
  /** Maximum HDR capacity (log2 scale) for full HDR output */
29
29
  hdrCapacityMax: number;
30
30
  }
31
+ /**
32
+ * Result of probing an image to check if it's UltraHDR.
33
+ *
34
+ * Provides detailed information about what components were found
35
+ * without fully decoding the image. Useful for batch processing and filtering.
36
+ */
37
+ interface UltraHdrProbeResult {
38
+ /** Whether the image is a valid UltraHDR image (has all required components) */
39
+ isValid: boolean;
40
+ /** Whether a primary JPEG image was found */
41
+ hasPrimaryImage: boolean;
42
+ /** Whether a gain map image was found */
43
+ hasGainMap: boolean;
44
+ /** Whether gain map metadata (XMP) was found */
45
+ hasMetadata: boolean;
46
+ /** Primary image width in pixels (0 if not found) */
47
+ width: number;
48
+ /** Primary image height in pixels (0 if not found) */
49
+ height: number;
50
+ /** Gain map width in pixels (0 if not found) */
51
+ gainMapWidth: number;
52
+ /** Gain map height in pixels (0 if not found) */
53
+ gainMapHeight: number;
54
+ /** HDR capacity (max additional stops of dynamic range), 0 if not found */
55
+ hdrCapacity: number;
56
+ /** Metadata version string (empty if not found) */
57
+ metadataVersion: string;
58
+ }
31
59
  /**
32
60
  * Result of decoding an UltraHDR image.
33
61
  */
@@ -157,6 +185,37 @@ declare function setLocation(newLocation: string): void;
157
185
  * ```
158
186
  */
159
187
  declare function isUltraHdr(buffer: ArrayBuffer): Promise<boolean>;
188
+ /**
189
+ * Probes an image to check if it's UltraHDR and extracts component information.
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);
205
+ *
206
+ * if (result.isValid) {
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
+ * ```
217
+ */
218
+ declare function probeUltraHdr(buffer: ArrayBuffer): Promise<UltraHdrProbeResult>;
160
219
  /**
161
220
  * Decodes an UltraHDR image, extracting all components.
162
221
  *
@@ -263,4 +322,4 @@ declare function estimateHdrHeadroom(metadata: GainMapMetadata): Promise<number>
263
322
  */
264
323
  declare function isMeaningfulHdr(metadata: GainMapMetadata): Promise<boolean>;
265
324
 
266
- export { ColorGamut, type GainMapMetadata, type ItemId, TransferFunction, type UltraHdrDecodeResult, type UltraHdrEncodeOptions, decodeUltraHdr, defaultEncodeOptions, encodeUltraHdr, estimateHdrHeadroom, extractSdrBase, getMetadata, highQualityEncodeOptions, isMeaningfulHdr, isUltraHdr, setLocation, smallSizeEncodeOptions, validateMetadata };
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 };
package/dist/index.d.ts CHANGED
@@ -28,6 +28,34 @@ interface GainMapMetadata {
28
28
  /** Maximum HDR capacity (log2 scale) for full HDR output */
29
29
  hdrCapacityMax: number;
30
30
  }
31
+ /**
32
+ * Result of probing an image to check if it's UltraHDR.
33
+ *
34
+ * Provides detailed information about what components were found
35
+ * without fully decoding the image. Useful for batch processing and filtering.
36
+ */
37
+ interface UltraHdrProbeResult {
38
+ /** Whether the image is a valid UltraHDR image (has all required components) */
39
+ isValid: boolean;
40
+ /** Whether a primary JPEG image was found */
41
+ hasPrimaryImage: boolean;
42
+ /** Whether a gain map image was found */
43
+ hasGainMap: boolean;
44
+ /** Whether gain map metadata (XMP) was found */
45
+ hasMetadata: boolean;
46
+ /** Primary image width in pixels (0 if not found) */
47
+ width: number;
48
+ /** Primary image height in pixels (0 if not found) */
49
+ height: number;
50
+ /** Gain map width in pixels (0 if not found) */
51
+ gainMapWidth: number;
52
+ /** Gain map height in pixels (0 if not found) */
53
+ gainMapHeight: number;
54
+ /** HDR capacity (max additional stops of dynamic range), 0 if not found */
55
+ hdrCapacity: number;
56
+ /** Metadata version string (empty if not found) */
57
+ metadataVersion: string;
58
+ }
31
59
  /**
32
60
  * Result of decoding an UltraHDR image.
33
61
  */
@@ -157,6 +185,37 @@ declare function setLocation(newLocation: string): void;
157
185
  * ```
158
186
  */
159
187
  declare function isUltraHdr(buffer: ArrayBuffer): Promise<boolean>;
188
+ /**
189
+ * Probes an image to check if it's UltraHDR and extracts component information.
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);
205
+ *
206
+ * if (result.isValid) {
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
+ * ```
217
+ */
218
+ declare function probeUltraHdr(buffer: ArrayBuffer): Promise<UltraHdrProbeResult>;
160
219
  /**
161
220
  * Decodes an UltraHDR image, extracting all components.
162
221
  *
@@ -263,4 +322,4 @@ declare function estimateHdrHeadroom(metadata: GainMapMetadata): Promise<number>
263
322
  */
264
323
  declare function isMeaningfulHdr(metadata: GainMapMetadata): Promise<boolean>;
265
324
 
266
- export { ColorGamut, type GainMapMetadata, type ItemId, TransferFunction, type UltraHdrDecodeResult, type UltraHdrEncodeOptions, decodeUltraHdr, defaultEncodeOptions, encodeUltraHdr, estimateHdrHeadroom, extractSdrBase, getMetadata, highQualityEncodeOptions, isMeaningfulHdr, isUltraHdr, setLocation, smallSizeEncodeOptions, validateMetadata };
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 };
package/dist/index.js CHANGED
@@ -41,6 +41,7 @@ __export(index_exports, {
41
41
  highQualityEncodeOptions: () => highQualityEncodeOptions,
42
42
  isMeaningfulHdr: () => isMeaningfulHdr,
43
43
  isUltraHdr: () => isUltraHdr,
44
+ probeUltraHdr: () => probeUltraHdr,
44
45
  setLocation: () => setLocation,
45
46
  smallSizeEncodeOptions: () => smallSizeEncodeOptions,
46
47
  validateMetadata: () => validateMetadata
@@ -121,15 +122,27 @@ async function getWasm() {
121
122
  return initPromise;
122
123
  }
123
124
  initPromise = (async () => {
124
- const UltraHdrWasm = await import("open-ultrahdr-wasm");
125
- if (location) {
126
- const wasmUrl = location + "open_ultrahdr_bg.wasm";
127
- await UltraHdrWasm.default(wasmUrl);
128
- } else {
129
- await UltraHdrWasm.default();
125
+ try {
126
+ const UltraHdrWasm = await import("open-ultrahdr-wasm");
127
+ if (location) {
128
+ const base = location.endsWith("/") ? location : `${location}/`;
129
+ const wasmPath = base + "open_ultrahdr_bg.wasm";
130
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
131
+ const fs = await import("fs");
132
+ const wasmBytes = await fs.promises.readFile(wasmPath);
133
+ await UltraHdrWasm.default(wasmBytes);
134
+ } else {
135
+ await UltraHdrWasm.default(wasmPath);
136
+ }
137
+ } else {
138
+ await UltraHdrWasm.default();
139
+ }
140
+ wasmInstance = UltraHdrWasm;
141
+ return wasmInstance;
142
+ } catch (err) {
143
+ initPromise = null;
144
+ throw err;
130
145
  }
131
- wasmInstance = UltraHdrWasm;
132
- return wasmInstance;
133
146
  })();
134
147
  return initPromise;
135
148
  }
@@ -137,6 +150,10 @@ async function isUltraHdr(buffer) {
137
150
  const wasm = await getWasm();
138
151
  return wasm.isUltraHdr(new Uint8Array(buffer));
139
152
  }
153
+ async function probeUltraHdr(buffer) {
154
+ const wasm = await getWasm();
155
+ return wasm.probeUltraHdr(new Uint8Array(buffer));
156
+ }
140
157
  async function decodeUltraHdr(id, buffer) {
141
158
  const wasm = await getWasm();
142
159
  return wasm.decodeUltraHdr(new Uint8Array(buffer));
@@ -156,12 +173,18 @@ async function encodeUltraHdr(id, sdrBuffer, hdrBuffer, options) {
156
173
  new Float32Array(hdrBuffer),
157
174
  wasmOpts
158
175
  );
159
- return result.buffer.slice(0);
176
+ return result.buffer.slice(
177
+ result.byteOffset,
178
+ result.byteOffset + result.byteLength
179
+ );
160
180
  }
161
181
  async function extractSdrBase(buffer) {
162
182
  const wasm = await getWasm();
163
183
  const result = wasm.extractSdrBase(new Uint8Array(buffer));
164
- return result.buffer.slice(0);
184
+ return result.buffer.slice(
185
+ result.byteOffset,
186
+ result.byteOffset + result.byteLength
187
+ );
165
188
  }
166
189
  async function getMetadata(buffer) {
167
190
  const wasm = await getWasm();
@@ -195,6 +218,7 @@ async function isMeaningfulHdr(metadata) {
195
218
  highQualityEncodeOptions,
196
219
  isMeaningfulHdr,
197
220
  isUltraHdr,
221
+ probeUltraHdr,
198
222
  setLocation,
199
223
  smallSizeEncodeOptions,
200
224
  validateMetadata
package/dist/index.mjs CHANGED
@@ -72,15 +72,27 @@ async function getWasm() {
72
72
  return initPromise;
73
73
  }
74
74
  initPromise = (async () => {
75
- const UltraHdrWasm = await import("open-ultrahdr-wasm");
76
- if (location) {
77
- const wasmUrl = location + "open_ultrahdr_bg.wasm";
78
- await UltraHdrWasm.default(wasmUrl);
79
- } else {
80
- await UltraHdrWasm.default();
75
+ try {
76
+ const UltraHdrWasm = await import("open-ultrahdr-wasm");
77
+ if (location) {
78
+ const base = location.endsWith("/") ? location : `${location}/`;
79
+ const wasmPath = base + "open_ultrahdr_bg.wasm";
80
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
81
+ const fs = await import("fs");
82
+ const wasmBytes = await fs.promises.readFile(wasmPath);
83
+ await UltraHdrWasm.default(wasmBytes);
84
+ } else {
85
+ await UltraHdrWasm.default(wasmPath);
86
+ }
87
+ } else {
88
+ await UltraHdrWasm.default();
89
+ }
90
+ wasmInstance = UltraHdrWasm;
91
+ return wasmInstance;
92
+ } catch (err) {
93
+ initPromise = null;
94
+ throw err;
81
95
  }
82
- wasmInstance = UltraHdrWasm;
83
- return wasmInstance;
84
96
  })();
85
97
  return initPromise;
86
98
  }
@@ -88,6 +100,10 @@ async function isUltraHdr(buffer) {
88
100
  const wasm = await getWasm();
89
101
  return wasm.isUltraHdr(new Uint8Array(buffer));
90
102
  }
103
+ async function probeUltraHdr(buffer) {
104
+ const wasm = await getWasm();
105
+ return wasm.probeUltraHdr(new Uint8Array(buffer));
106
+ }
91
107
  async function decodeUltraHdr(id, buffer) {
92
108
  const wasm = await getWasm();
93
109
  return wasm.decodeUltraHdr(new Uint8Array(buffer));
@@ -107,12 +123,18 @@ async function encodeUltraHdr(id, sdrBuffer, hdrBuffer, options) {
107
123
  new Float32Array(hdrBuffer),
108
124
  wasmOpts
109
125
  );
110
- return result.buffer.slice(0);
126
+ return result.buffer.slice(
127
+ result.byteOffset,
128
+ result.byteOffset + result.byteLength
129
+ );
111
130
  }
112
131
  async function extractSdrBase(buffer) {
113
132
  const wasm = await getWasm();
114
133
  const result = wasm.extractSdrBase(new Uint8Array(buffer));
115
- return result.buffer.slice(0);
134
+ return result.buffer.slice(
135
+ result.byteOffset,
136
+ result.byteOffset + result.byteLength
137
+ );
116
138
  }
117
139
  async function getMetadata(buffer) {
118
140
  const wasm = await getWasm();
@@ -145,6 +167,7 @@ export {
145
167
  highQualityEncodeOptions,
146
168
  isMeaningfulHdr,
147
169
  isUltraHdr,
170
+ probeUltraHdr,
148
171
  setLocation,
149
172
  smallSizeEncodeOptions,
150
173
  validateMetadata
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-ultrahdr",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "UltraHDR (ISO 21496-1) gain map support for JavaScript/TypeScript",
5
5
  "author": "Adam Silverstein",
6
6
  "license": "GPL-2.0-or-later",
@@ -15,14 +15,14 @@
15
15
  "homepage": "https://github.com/adamsilverstein/lib-open-ultrahdr",
16
16
  "repository": {
17
17
  "type": "git",
18
- "url": "https://github.com/adamsilverstein/lib-open-ultrahdr.git",
18
+ "url": "git+https://github.com/adamsilverstein/lib-open-ultrahdr.git",
19
19
  "directory": "js"
20
20
  },
21
21
  "bugs": {
22
22
  "url": "https://github.com/adamsilverstein/lib-open-ultrahdr/issues"
23
23
  },
24
24
  "engines": {
25
- "node": ">=18.0.0"
25
+ "node": ">=20.0.0"
26
26
  },
27
27
  "files": [
28
28
  "src",
@@ -52,11 +52,12 @@
52
52
  "lint:fix": "eslint src __tests__ --fix"
53
53
  },
54
54
  "dependencies": {
55
- "open-ultrahdr-wasm": "^0.1.1"
55
+ "open-ultrahdr-wasm": "^0.1.2"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@eslint/js": "^9.0.0",
59
- "@vitest/coverage-v8": "^2.0.0",
59
+ "@types/node": "^25.1.0",
60
+ "@vitest/coverage-v8": "^4.0.0",
60
61
  "eslint": "^9.0.0",
61
62
  "eslint-config-prettier": "^9.0.0",
62
63
  "tsup": "^8.0.0",
@@ -64,7 +65,7 @@
64
65
  "typescript-eslint": "^8.0.0",
65
66
  "vite-plugin-top-level-await": "^1.6.0",
66
67
  "vite-plugin-wasm": "^3.5.0",
67
- "vitest": "^2.0.0"
68
+ "vitest": "^4.0.0"
68
69
  },
69
70
  "publishConfig": {
70
71
  "access": "public"
package/src/index.ts CHANGED
@@ -22,7 +22,13 @@
22
22
  */
23
23
 
24
24
  // Re-export types
25
- export type { ItemId, GainMapMetadata, UltraHdrDecodeResult, UltraHdrEncodeOptions } from './types';
25
+ export type {
26
+ ItemId,
27
+ GainMapMetadata,
28
+ UltraHdrDecodeResult,
29
+ UltraHdrEncodeOptions,
30
+ UltraHdrProbeResult,
31
+ } from './types';
26
32
 
27
33
  export {
28
34
  ColorGamut,
@@ -32,7 +38,13 @@ export {
32
38
  smallSizeEncodeOptions,
33
39
  } from './types';
34
40
 
35
- import type { ItemId, GainMapMetadata, UltraHdrDecodeResult, UltraHdrEncodeOptions } from './types';
41
+ import type {
42
+ ItemId,
43
+ GainMapMetadata,
44
+ UltraHdrDecodeResult,
45
+ UltraHdrEncodeOptions,
46
+ UltraHdrProbeResult,
47
+ } from './types';
36
48
 
37
49
  import { defaultEncodeOptions } from './types';
38
50
 
@@ -62,6 +74,7 @@ interface WasmGainMapMetadata {
62
74
  interface UltraHdrWasmModule {
63
75
  default: (moduleOrPath?: string | URL | Response | BufferSource) => Promise<unknown>;
64
76
  isUltraHdr: (buffer: Uint8Array) => boolean;
77
+ probeUltraHdr: (buffer: Uint8Array) => UltraHdrProbeResult;
65
78
  decodeUltraHdr: (buffer: Uint8Array) => UltraHdrDecodeResult;
66
79
  encodeUltraHdr: (
67
80
  sdrBuffer: Uint8Array,
@@ -159,21 +172,37 @@ async function getWasm(): Promise<UltraHdrWasmModule> {
159
172
  }
160
173
 
161
174
  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();
175
+ try {
176
+ // Dynamic import of the WASM package
177
+ const UltraHdrWasm = (await import('open-ultrahdr-wasm')) as unknown as UltraHdrWasmModule;
178
+
179
+ // Initialize WASM with the location prefix for the .wasm file
180
+ // If location is set, construct the full URL to the WASM file
181
+ if (location) {
182
+ const base = location.endsWith('/') ? location : `${location}/`;
183
+ const wasmPath = base + 'open_ultrahdr_bg.wasm';
184
+
185
+ // In Node.js, load the WASM file from the filesystem
186
+ // instead of using fetch which doesn't work with file:// URLs
187
+ if (typeof process !== 'undefined' && process.versions && process.versions.node) {
188
+ const fs = await import('fs');
189
+ const wasmBytes = await fs.promises.readFile(wasmPath);
190
+ await UltraHdrWasm.default(wasmBytes);
191
+ } else {
192
+ // In browser, use the URL directly
193
+ await UltraHdrWasm.default(wasmPath);
194
+ }
195
+ } else {
196
+ // Let the WASM module use its default URL resolution (import.meta.url)
197
+ await UltraHdrWasm.default();
198
+ }
199
+
200
+ wasmInstance = UltraHdrWasm as unknown as UltraHdrWasmModule;
201
+ return wasmInstance;
202
+ } catch (err) {
203
+ initPromise = null;
204
+ throw err;
173
205
  }
174
-
175
- wasmInstance = UltraHdrWasm as unknown as UltraHdrWasmModule;
176
- return wasmInstance;
177
206
  })();
178
207
 
179
208
  return initPromise;
@@ -201,6 +230,41 @@ export async function isUltraHdr(buffer: ArrayBuffer): Promise<boolean> {
201
230
  return wasm.isUltraHdr(new Uint8Array(buffer));
202
231
  }
203
232
 
233
+ /**
234
+ * Probes an image to check if it's UltraHDR and extracts component information.
235
+ *
236
+ * This function efficiently validates if an image is UltraHDR by checking for
237
+ * required components (primary image, gain map, metadata) without full decoding.
238
+ * Returns structured results useful for batch processing and filtering.
239
+ *
240
+ * Unlike `isUltraHdr`, this function provides detailed information about what
241
+ * was found, making it useful for diagnostics and filtering workflows.
242
+ *
243
+ * @param buffer - Image file contents.
244
+ * @return Probe result with detailed component information.
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * const buffer = await file.arrayBuffer();
249
+ * const result = await probeUltraHdr(buffer);
250
+ *
251
+ * if (result.isValid) {
252
+ * console.log('UltraHDR image:', result.width, 'x', result.height);
253
+ * console.log('HDR capacity:', result.hdrCapacity, 'stops');
254
+ * console.log('Gain map:', result.gainMapWidth, 'x', result.gainMapHeight);
255
+ * } else {
256
+ * // Diagnose why it's not a valid UltraHDR
257
+ * if (!result.hasPrimaryImage) console.log('Not a valid JPEG');
258
+ * if (!result.hasGainMap) console.log('Missing gain map');
259
+ * if (!result.hasMetadata) console.log('Missing HDR metadata');
260
+ * }
261
+ * ```
262
+ */
263
+ export async function probeUltraHdr(buffer: ArrayBuffer): Promise<UltraHdrProbeResult> {
264
+ const wasm = await getWasm();
265
+ return wasm.probeUltraHdr(new Uint8Array(buffer));
266
+ }
267
+
204
268
  /**
205
269
  * Decodes an UltraHDR image, extracting all components.
206
270
  *
@@ -281,7 +345,10 @@ export async function encodeUltraHdr(
281
345
  );
282
346
 
283
347
  // Ensure we return a proper ArrayBuffer (not SharedArrayBuffer)
284
- return result.buffer.slice(0) as ArrayBuffer;
348
+ return result.buffer.slice(
349
+ result.byteOffset,
350
+ result.byteOffset + result.byteLength
351
+ ) as ArrayBuffer;
285
352
  }
286
353
 
287
354
  /**
@@ -306,7 +373,10 @@ export async function extractSdrBase(buffer: ArrayBuffer): Promise<ArrayBuffer>
306
373
  const wasm = await getWasm();
307
374
  const result = wasm.extractSdrBase(new Uint8Array(buffer));
308
375
  // Ensure we return a proper ArrayBuffer (not SharedArrayBuffer)
309
- return result.buffer.slice(0) as ArrayBuffer;
376
+ return result.buffer.slice(
377
+ result.byteOffset,
378
+ result.byteOffset + result.byteLength
379
+ ) as ArrayBuffer;
310
380
  }
311
381
 
312
382
  /**
package/src/types.ts CHANGED
@@ -38,6 +38,44 @@ export interface GainMapMetadata {
38
38
  hdrCapacityMax: number;
39
39
  }
40
40
 
41
+ /**
42
+ * Result of probing an image to check if it's UltraHDR.
43
+ *
44
+ * Provides detailed information about what components were found
45
+ * without fully decoding the image. Useful for batch processing and filtering.
46
+ */
47
+ export interface UltraHdrProbeResult {
48
+ /** Whether the image is a valid UltraHDR image (has all required components) */
49
+ isValid: boolean;
50
+
51
+ /** Whether a primary JPEG image was found */
52
+ hasPrimaryImage: boolean;
53
+
54
+ /** Whether a gain map image was found */
55
+ hasGainMap: boolean;
56
+
57
+ /** Whether gain map metadata (XMP) was found */
58
+ hasMetadata: boolean;
59
+
60
+ /** Primary image width in pixels (0 if not found) */
61
+ width: number;
62
+
63
+ /** Primary image height in pixels (0 if not found) */
64
+ height: number;
65
+
66
+ /** Gain map width in pixels (0 if not found) */
67
+ gainMapWidth: number;
68
+
69
+ /** Gain map height in pixels (0 if not found) */
70
+ gainMapHeight: number;
71
+
72
+ /** HDR capacity (max additional stops of dynamic range), 0 if not found */
73
+ hdrCapacity: number;
74
+
75
+ /** Metadata version string (empty if not found) */
76
+ metadataVersion: string;
77
+ }
78
+
41
79
  /**
42
80
  * Result of decoding an UltraHDR image.
43
81
  */