oidn-webgpu 0.0.0-stage → 0.6.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.
Files changed (95) hide show
  1. package/CHANGELOG.md +182 -0
  2. package/LICENSE +21 -0
  3. package/README.md +89 -2
  4. package/dist/oidn.js +6140 -0
  5. package/dist/oidn.umd.cjs +1513 -0
  6. package/lib/UNet.d.ts +161 -0
  7. package/lib/UNet.js +536 -0
  8. package/lib/UNet.js.map +1 -0
  9. package/lib/WGPUComputePass.d.ts +62 -0
  10. package/lib/WGPUComputePass.js +278 -0
  11. package/lib/WGPUComputePass.js.map +1 -0
  12. package/lib/WGPUFullQuadPass.d.ts +50 -0
  13. package/lib/WGPUFullQuadPass.js +261 -0
  14. package/lib/WGPUFullQuadPass.js.map +1 -0
  15. package/lib/backend.d.ts +1 -0
  16. package/lib/backend.js +39 -0
  17. package/lib/backend.js.map +1 -0
  18. package/lib/finalRgbShader.d.ts +13 -0
  19. package/lib/finalRgbShader.js +160 -0
  20. package/lib/finalRgbShader.js.map +1 -0
  21. package/lib/gpuTypes.d.ts +158 -0
  22. package/lib/gpuTypes.js +27 -0
  23. package/lib/gpuTypes.js.map +1 -0
  24. package/lib/graphOptimizer.d.ts +54 -0
  25. package/lib/graphOptimizer.js +216 -0
  26. package/lib/graphOptimizer.js.map +1 -0
  27. package/lib/hdr.d.ts +31 -0
  28. package/lib/hdr.js +340 -0
  29. package/lib/hdr.js.map +1 -0
  30. package/lib/hdrTransfer.d.ts +22 -0
  31. package/lib/hdrTransfer.js +128 -0
  32. package/lib/hdrTransfer.js.map +1 -0
  33. package/lib/main.d.ts +57 -0
  34. package/lib/main.js +24 -0
  35. package/lib/main.js.map +1 -0
  36. package/lib/modelSpec.d.ts +80 -0
  37. package/lib/modelSpec.js +270 -0
  38. package/lib/modelSpec.js.map +1 -0
  39. package/lib/native/denoise.d.ts +25 -0
  40. package/lib/native/denoise.js +223 -0
  41. package/lib/native/denoise.js.map +1 -0
  42. package/lib/native/program.d.ts +53 -0
  43. package/lib/native/program.js +310 -0
  44. package/lib/native/program.js.map +1 -0
  45. package/lib/native/recordingDevice.d.ts +125 -0
  46. package/lib/native/recordingDevice.js +247 -0
  47. package/lib/native/recordingDevice.js.map +1 -0
  48. package/lib/nativeUNet.d.ts +25 -0
  49. package/lib/nativeUNet.js +184 -0
  50. package/lib/nativeUNet.js.map +1 -0
  51. package/lib/nativeUNetCore.d.ts +202 -0
  52. package/lib/nativeUNetCore.js +2945 -0
  53. package/lib/nativeUNetCore.js.map +1 -0
  54. package/lib/process.d.ts +37 -0
  55. package/lib/process.js +328 -0
  56. package/lib/process.js.map +1 -0
  57. package/lib/resourceTracker.d.ts +26 -0
  58. package/lib/resourceTracker.js +65 -0
  59. package/lib/resourceTracker.js.map +1 -0
  60. package/lib/sanitize.d.ts +15 -0
  61. package/lib/sanitize.js +28 -0
  62. package/lib/sanitize.js.map +1 -0
  63. package/lib/tileScheduler.d.ts +61 -0
  64. package/lib/tileScheduler.js +199 -0
  65. package/lib/tileScheduler.js.map +1 -0
  66. package/lib/tza.d.ts +15 -0
  67. package/lib/tza.js +114 -0
  68. package/lib/tza.js.map +1 -0
  69. package/lib/webnnUNet.d.ts +52 -0
  70. package/lib/webnnUNet.js +535 -0
  71. package/lib/webnnUNet.js.map +1 -0
  72. package/package.json +43 -4
  73. package/src/UNet.ts +861 -0
  74. package/src/WGPUComputePass.ts +382 -0
  75. package/src/WGPUFullQuadPass.ts +348 -0
  76. package/src/backend.ts +42 -0
  77. package/src/finalRgbShader.ts +186 -0
  78. package/src/gpuTypes.ts +179 -0
  79. package/src/graphOptimizer.ts +301 -0
  80. package/src/hdr.ts +398 -0
  81. package/src/hdrTransfer.ts +169 -0
  82. package/src/main.ts +126 -0
  83. package/src/modelSpec.ts +414 -0
  84. package/src/native/core-profile.json +40 -0
  85. package/src/native/denoise.ts +268 -0
  86. package/src/native/program.ts +326 -0
  87. package/src/native/recordingDevice.ts +341 -0
  88. package/src/nativeUNet.ts +269 -0
  89. package/src/nativeUNetCore.ts +3735 -0
  90. package/src/process.ts +368 -0
  91. package/src/resourceTracker.ts +94 -0
  92. package/src/sanitize.ts +29 -0
  93. package/src/tileScheduler.ts +330 -0
  94. package/src/tza.ts +136 -0
  95. package/src/webnnUNet.ts +812 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The WebGPU subset used by the native WGSL runtime, as structural types and
3
+ * spec-defined flag values. A browser GPUDevice implements these operations,
4
+ * but its branded TypeScript types need the conversion in nativeUNet.ts;
5
+ * they also let an embedder supply its own device (for example one that
6
+ * records the work for replay in a native wgpu host) without lib.dom or
7
+ * WebGPU globals.
8
+ */
9
+ /** GPUBufferUsage flag values from the WebGPU specification. */
10
+ export const BufferUsage = {
11
+ MAP_READ: 0x0001,
12
+ MAP_WRITE: 0x0002,
13
+ COPY_SRC: 0x0004,
14
+ COPY_DST: 0x0008,
15
+ INDEX: 0x0010,
16
+ VERTEX: 0x0020,
17
+ UNIFORM: 0x0040,
18
+ STORAGE: 0x0080,
19
+ INDIRECT: 0x0100,
20
+ QUERY_RESOLVE: 0x0200
21
+ };
22
+ /** GPUMapMode flag values from the WebGPU specification. */
23
+ export const MapMode = {
24
+ READ: 0x0001,
25
+ WRITE: 0x0002
26
+ };
27
+ //# sourceMappingURL=gpuTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpuTypes.js","sourceRoot":"","sources":["../src/gpuTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,gEAAgE;AAChE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,QAAQ,EAAE,MAAM;IAChB,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,MAAM;IACb,MAAM,EAAE,MAAM;IACd,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,MAAM;IACf,QAAQ,EAAE,MAAM;IAChB,aAAa,EAAE,MAAM;CACb,CAAC;AAEX,4DAA4D;AAC5D,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,MAAM;CACL,CAAC"}
@@ -0,0 +1,54 @@
1
+ import type { Conv2DNodeSpec, MaxPool2DNodeSpec, ModelNodeSpec, UNetModelSpec, Upsample2DNodeSpec, UNetModelGraph } from './modelSpec';
2
+ export interface FusedConvPoolNodeSpec {
3
+ op: 'fusedConvReluMaxPool2d';
4
+ id: string;
5
+ input: string;
6
+ conv: Conv2DNodeSpec;
7
+ pool: MaxPool2DNodeSpec;
8
+ }
9
+ export interface FusedUpsampleConcatConvNodeSpec {
10
+ op: 'fusedUpsampleConcatConv2d';
11
+ id: string;
12
+ /** Inputs stay in concat order because that order selects weight channels. */
13
+ inputs: readonly {
14
+ value: string;
15
+ upsample?: Upsample2DNodeSpec;
16
+ }[];
17
+ conv: Conv2DNodeSpec;
18
+ }
19
+ export type ExecutableModelNode = ModelNodeSpec | FusedConvPoolNodeSpec | FusedUpsampleConcatConvNodeSpec;
20
+ export interface GraphOptimizationOptions {
21
+ fuseConvPool?: boolean;
22
+ fuseUpsampleConcatConv?: boolean;
23
+ }
24
+ export interface OptimizedModelGraph {
25
+ spec: UNetModelSpec;
26
+ nodes: readonly ExecutableModelNode[];
27
+ fusions: {
28
+ convPool: number;
29
+ upsampleConcatConv: number;
30
+ };
31
+ }
32
+ /**
33
+ * Applies topology-only fusions. It never depends on a particular OIDN model
34
+ * name, so new descriptors automatically benefit from known graph patterns.
35
+ */
36
+ export declare function optimizeModelGraph(validated: UNetModelGraph, options?: GraphOptimizationOptions): OptimizedModelGraph;
37
+ export interface ModelValueShape {
38
+ width: number;
39
+ height: number;
40
+ channels: number;
41
+ }
42
+ export interface PlannedModelNode {
43
+ node: ExecutableModelNode;
44
+ outputShape: ModelValueShape;
45
+ /** Last planned node that reads the output; output itself uses nodes.length. */
46
+ lastUse: number;
47
+ }
48
+ export interface ModelExecutionPlan extends OptimizedModelGraph {
49
+ inputShape: ModelValueShape;
50
+ valueShapes: ReadonlyMap<string, ModelValueShape>;
51
+ plannedNodes: readonly PlannedModelNode[];
52
+ }
53
+ /** Resolve all runtime shapes and value lifetimes before allocating GPU data. */
54
+ export declare function planModelExecution(validated: UNetModelGraph, width: number, height: number, options?: GraphOptimizationOptions): ModelExecutionPlan;
@@ -0,0 +1,216 @@
1
+ function nodeInputs(node) {
2
+ return node.op === 'concat' ? node.inputs : [node.input];
3
+ }
4
+ function buildConsumers(spec) {
5
+ const consumers = new Map();
6
+ for (const node of spec.nodes) {
7
+ for (const input of nodeInputs(node)) {
8
+ const list = consumers.get(input) ?? [];
9
+ list.push(node);
10
+ consumers.set(input, list);
11
+ }
12
+ }
13
+ return consumers;
14
+ }
15
+ // Callers narrow on `op`; node ids are unique, so they compare consumers by id.
16
+ function onlyConsumer(consumers, value, op) {
17
+ const list = consumers.get(value);
18
+ if (list === undefined || list.length !== 1 || list[0].op !== op)
19
+ return undefined;
20
+ return list[0];
21
+ }
22
+ /**
23
+ * Applies topology-only fusions. It never depends on a particular OIDN model
24
+ * name, so new descriptors automatically benefit from known graph patterns.
25
+ */
26
+ export function optimizeModelGraph(validated, options = {}) {
27
+ const spec = validated.spec;
28
+ const consumers = buildConsumers(spec);
29
+ const nodesById = new Map(spec.nodes.map((node) => [node.id, node]));
30
+ const eliminated = new Set();
31
+ const fusedAt = new Map();
32
+ let convPool = 0;
33
+ let upsampleConcatConv = 0;
34
+ if (options.fuseConvPool !== false) {
35
+ for (const node of spec.nodes) {
36
+ if (node.op !== 'conv2d' || node.activation !== 'relu')
37
+ continue;
38
+ const pool = onlyConsumer(consumers, node.id, 'maxPool2d');
39
+ if (!pool || pool.op !== 'maxPool2d' || pool.size !== 2 || pool.stride !== 2)
40
+ continue;
41
+ eliminated.add(node.id);
42
+ fusedAt.set(pool.id, {
43
+ op: 'fusedConvReluMaxPool2d',
44
+ id: pool.id,
45
+ input: node.input,
46
+ conv: node,
47
+ pool
48
+ });
49
+ convPool++;
50
+ }
51
+ }
52
+ if (options.fuseUpsampleConcatConv !== false) {
53
+ for (const node of spec.nodes) {
54
+ if (node.op !== 'conv2d')
55
+ continue;
56
+ const concat = nodesById.get(node.input);
57
+ if (concat?.op !== 'concat' || concat.inputs.length !== 2)
58
+ continue;
59
+ if (onlyConsumer(consumers, concat.id, 'conv2d')?.id !== node.id)
60
+ continue;
61
+ // The native blocked layout can remove concat only when the source
62
+ // boundary is also a vec4 boundary. Other graphs keep the generic ops.
63
+ const firstInputChannels = validated.channelsByValue.get(concat.inputs[0]);
64
+ if (firstInputChannels === undefined || firstInputChannels % 4 !== 0) {
65
+ continue;
66
+ }
67
+ const inputs = concat.inputs.map((value) => {
68
+ const candidate = nodesById.get(value);
69
+ if (candidate?.op === 'upsample2d' &&
70
+ candidate.scale === 2 &&
71
+ candidate.mode === 'nearest' &&
72
+ onlyConsumer(consumers, candidate.id, 'concat')?.id === concat.id) {
73
+ return { value: candidate.input, upsample: candidate };
74
+ }
75
+ return { value };
76
+ });
77
+ const upsampleCount = inputs.filter((input) => input.upsample).length;
78
+ if (upsampleCount !== 1)
79
+ continue;
80
+ eliminated.add(concat.id);
81
+ for (const value of concat.inputs) {
82
+ const candidate = nodesById.get(value);
83
+ if (candidate?.op === 'upsample2d')
84
+ eliminated.add(candidate.id);
85
+ }
86
+ fusedAt.set(node.id, {
87
+ op: 'fusedUpsampleConcatConv2d',
88
+ id: node.id,
89
+ inputs,
90
+ conv: node
91
+ });
92
+ upsampleConcatConv++;
93
+ }
94
+ }
95
+ const nodes = [];
96
+ for (const node of spec.nodes) {
97
+ const fused = fusedAt.get(node.id);
98
+ if (fused) {
99
+ nodes.push(fused);
100
+ }
101
+ else if (!eliminated.has(node.id)) {
102
+ nodes.push(node);
103
+ }
104
+ }
105
+ return {
106
+ spec,
107
+ nodes,
108
+ fusions: { convPool, upsampleConcatConv }
109
+ };
110
+ }
111
+ function executableInputs(node) {
112
+ if (node.op === 'concat')
113
+ return node.inputs;
114
+ if (node.op === 'fusedUpsampleConcatConv2d') {
115
+ return node.inputs.map((input) => input.value);
116
+ }
117
+ return [node.input];
118
+ }
119
+ function sameSpatialShape(left, right) {
120
+ return left.width === right.width && left.height === right.height;
121
+ }
122
+ /** Resolve all runtime shapes and value lifetimes before allocating GPU data. */
123
+ export function planModelExecution(validated, width, height, options) {
124
+ if (!Number.isInteger(width) || width <= 0 || !Number.isInteger(height) || height <= 0) {
125
+ throw new Error(`Invalid model input size ${width}x${height}`);
126
+ }
127
+ const graph = optimizeModelGraph(validated, options);
128
+ const inputShape = { width, height, channels: validated.inputChannels };
129
+ const valueShapes = new Map([
130
+ [validated.spec.input, inputShape]
131
+ ]);
132
+ const outputShapes = [];
133
+ const shapeOf = (value, nodeId) => {
134
+ const shape = valueShapes.get(value);
135
+ if (!shape)
136
+ throw new Error(`Planned node ${nodeId} reads missing value ${value}`);
137
+ return shape;
138
+ };
139
+ for (const node of graph.nodes) {
140
+ let outputShape;
141
+ if (node.op === 'conv2d') {
142
+ const input = shapeOf(node.input, node.id);
143
+ outputShape = {
144
+ width: input.width,
145
+ height: input.height,
146
+ channels: validated.convChannels.get(node.id).outputChannels
147
+ };
148
+ }
149
+ else if (node.op === 'maxPool2d') {
150
+ const input = shapeOf(node.input, node.id);
151
+ outputShape = {
152
+ width: Math.ceil(input.width / 2),
153
+ height: Math.ceil(input.height / 2),
154
+ channels: input.channels
155
+ };
156
+ }
157
+ else if (node.op === 'upsample2d') {
158
+ const input = shapeOf(node.input, node.id);
159
+ outputShape = {
160
+ width: input.width * 2,
161
+ height: input.height * 2,
162
+ channels: input.channels
163
+ };
164
+ }
165
+ else if (node.op === 'concat') {
166
+ const inputs = node.inputs.map((value) => shapeOf(value, node.id));
167
+ if (inputs.some((shape) => !sameSpatialShape(shape, inputs[0]))) {
168
+ throw new Error(`Concat ${node.id} has mismatched spatial shapes`);
169
+ }
170
+ outputShape = {
171
+ width: inputs[0].width,
172
+ height: inputs[0].height,
173
+ channels: inputs.reduce((sum, shape) => sum + shape.channels, 0)
174
+ };
175
+ }
176
+ else if (node.op === 'fusedConvReluMaxPool2d') {
177
+ const input = shapeOf(node.input, node.id);
178
+ outputShape = {
179
+ width: Math.ceil(input.width / 2),
180
+ height: Math.ceil(input.height / 2),
181
+ channels: validated.convChannels.get(node.conv.id).outputChannels
182
+ };
183
+ }
184
+ else {
185
+ const inputs = node.inputs.map((input) => {
186
+ const source = shapeOf(input.value, node.id);
187
+ return input.upsample
188
+ ? { ...source, width: source.width * 2, height: source.height * 2 }
189
+ : source;
190
+ });
191
+ if (inputs.some((shape) => !sameSpatialShape(shape, inputs[0]))) {
192
+ throw new Error(`Fused decoder ${node.id} has mismatched spatial shapes`);
193
+ }
194
+ outputShape = {
195
+ width: inputs[0].width,
196
+ height: inputs[0].height,
197
+ channels: validated.convChannels.get(node.conv.id).outputChannels
198
+ };
199
+ }
200
+ valueShapes.set(node.id, outputShape);
201
+ outputShapes.push(outputShape);
202
+ }
203
+ const lastUses = new Map();
204
+ graph.nodes.forEach((node, index) => {
205
+ for (const input of executableInputs(node))
206
+ lastUses.set(input, index);
207
+ });
208
+ lastUses.set(validated.spec.output, graph.nodes.length);
209
+ const plannedNodes = graph.nodes.map((node, index) => ({
210
+ node,
211
+ outputShape: outputShapes[index],
212
+ lastUse: lastUses.get(node.id) ?? index
213
+ }));
214
+ return { ...graph, inputShape, valueShapes, plannedNodes };
215
+ }
216
+ //# sourceMappingURL=graphOptimizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphOptimizer.js","sourceRoot":"","sources":["../src/graphOptimizer.ts"],"names":[],"mappings":"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"}
package/lib/hdr.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Convert 4 byte uint8 buffer to 3 channels float data
3
+ * @param rgbe input uint8 buffer
4
+ * @param float output float data
5
+ */
6
+ declare function rgbe2float(rgbe: Uint8Array, float: Float32Array): void;
7
+ /**
8
+ * Convert 3 channels float data to 4 byte uint8 buffer
9
+ * @param float input float data
10
+ * @param rgbe output uint8 buffer
11
+ */
12
+ declare function float2rgbe(float: Float32Array, rgbe: Uint8Array): void;
13
+ /**
14
+ * Write float data to RGBE(.hdr) file buffer
15
+ * @param w image width
16
+ * @param h image height
17
+ * @param data float data, RGB 3 channels.
18
+ * @returns file buffer
19
+ */
20
+ declare function write_hdr(w: number, h: number, data: Float32Array): Uint8Array;
21
+ /**
22
+ * Read a RGBE(.hdr) file from buffer
23
+ * @param uint8 RGBE(.hdr) file buffer
24
+ * @returns Failure reason or resolved data.
25
+ */
26
+ declare function read_hdr(uint8: Uint8Array): string | {
27
+ rgbFloat: Float32Array;
28
+ width: number;
29
+ height: number;
30
+ };
31
+ export { read_hdr as readHDR, write_hdr as writeHDR, float2rgbe, rgbe2float };
package/lib/hdr.js ADDED
@@ -0,0 +1,340 @@
1
+ // https://github.com/bbbbx/hdr.js/blob/main/src/hdr.ts
2
+ function frexp(v) {
3
+ v = Number(v);
4
+ const result = { f: v, e: 0 };
5
+ if (v !== 0 && Number.isFinite(v)) {
6
+ const absV = Math.abs(v);
7
+ const log2 = Math.log2 ||
8
+ function log2(n) {
9
+ return Math.log(n) * Math.LOG2E;
10
+ };
11
+ // Math.pow(2, -exp) === Infinity when exp <= -1024
12
+ let e = Math.max(-1023, Math.floor(log2(absV)) + 1);
13
+ let f = absV * Math.pow(2.0, -e);
14
+ while (f >= 1.0) {
15
+ f *= 0.5;
16
+ e++;
17
+ }
18
+ while (f < 0.5) {
19
+ f *= 2;
20
+ e--;
21
+ }
22
+ if (v < 0) {
23
+ f = -f;
24
+ }
25
+ result.f = f;
26
+ result.e = e;
27
+ }
28
+ return result;
29
+ }
30
+ function ldexp(f, e) {
31
+ return f * Math.pow(2.0, e);
32
+ }
33
+ /**
34
+ * Convert 4 byte uint8 buffer to 3 channels float data
35
+ * @param rgbe input uint8 buffer
36
+ * @param float output float data
37
+ */
38
+ function rgbe2float(rgbe, float) {
39
+ if (rgbe[3] !== 0) {
40
+ const f1 = ldexp(1.0, rgbe[3] - (128 + 8));
41
+ float[0] = rgbe[0] * f1;
42
+ float[1] = rgbe[1] * f1;
43
+ float[2] = rgbe[2] * f1;
44
+ }
45
+ else {
46
+ float[0] = float[1] = float[2] = 0.0;
47
+ }
48
+ }
49
+ /**
50
+ * Convert 3 channels float data to 4 byte uint8 buffer
51
+ * @param float input float data
52
+ * @param rgbe output uint8 buffer
53
+ */
54
+ function float2rgbe(float, rgbe) {
55
+ const red = float[0];
56
+ const green = float[1];
57
+ const blue = float[2];
58
+ const v = Math.max(red, Math.max(green, blue));
59
+ if (v < 1e-32) {
60
+ rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
61
+ }
62
+ else {
63
+ const { f, e } = frexp(v);
64
+ const s = (f / v) * 256.0;
65
+ rgbe[0] = red * s;
66
+ rgbe[1] = green * s;
67
+ rgbe[2] = blue * s;
68
+ rgbe[3] = e + 128;
69
+ }
70
+ }
71
+ /**
72
+ * Write float data to RGBE(.hdr) file buffer
73
+ * @param w image width
74
+ * @param h image height
75
+ * @param data float data, RGB 3 channels.
76
+ * @returns file buffer
77
+ */
78
+ function write_hdr(w, h, data) {
79
+ const s = [];
80
+ const comp = 3;
81
+ write_hdr_core(s, w, h, comp, data);
82
+ return new Uint8Array(s);
83
+ }
84
+ function write_hdr_core(s, x, y, comp, data) {
85
+ if (y <= 0 || x <= 0 || !data) {
86
+ return;
87
+ }
88
+ const header = '#?RADIANCE\n' +
89
+ 'FORMAT=32-bit_rle_rgbe\n' +
90
+ 'EXPOSURE=1.0\n' +
91
+ '\n' +
92
+ '-Y ' +
93
+ y +
94
+ ' +X ' +
95
+ x +
96
+ '\n';
97
+ header.split('').forEach((c) => {
98
+ const charCode = c.charCodeAt(0);
99
+ s.push(charCode);
100
+ });
101
+ const scratch = new Uint8Array(x * 4);
102
+ const stbi__flip_vertically_on_write = false;
103
+ for (let i = 0; i < y; i++) {
104
+ write_hdr_scanline(s, x, comp, scratch, data.subarray(comp * x * (stbi__flip_vertically_on_write ? y - 1 - i : i)));
105
+ }
106
+ }
107
+ function write_hdr_scanline(s, width, ncomp, scratch, scanline) {
108
+ const scanlineheader = new Uint8Array([2, 2, 0, 0]);
109
+ const rgbe = new Uint8Array(4);
110
+ const linear = new Float32Array(3);
111
+ let x;
112
+ scanlineheader[2] = (width & 0xff00) >> 8;
113
+ scanlineheader[3] = width & 0x00ff;
114
+ /* skip RLE for images too small or large */
115
+ if (width < 8 || width >= 32768) {
116
+ for (x = 0; x < width; x++) {
117
+ switch (ncomp) {
118
+ case 4: /* fallthrough */
119
+ case 3:
120
+ linear[2] = scanline[x * ncomp + 2];
121
+ linear[1] = scanline[x * ncomp + 1];
122
+ linear[0] = scanline[x * ncomp + 0];
123
+ break;
124
+ default:
125
+ linear[0] = linear[1] = linear[2] = scanline[x * ncomp + 0];
126
+ break;
127
+ }
128
+ float2rgbe(linear, rgbe);
129
+ s.push(rgbe[0], rgbe[1], rgbe[2], rgbe[3]);
130
+ }
131
+ }
132
+ else {
133
+ let c, r;
134
+ /* encode into scratch buffer */
135
+ for (x = 0; x < width; x++) {
136
+ switch (ncomp) {
137
+ case 4: /* fallthrough */
138
+ case 3:
139
+ linear[2] = scanline[x * ncomp + 2];
140
+ linear[1] = scanline[x * ncomp + 1];
141
+ linear[0] = scanline[x * ncomp + 0];
142
+ break;
143
+ default:
144
+ linear[0] = linear[1] = linear[2] = scanline[x * ncomp + 0];
145
+ break;
146
+ }
147
+ float2rgbe(linear, rgbe);
148
+ scratch[x + width * 0] = rgbe[0];
149
+ scratch[x + width * 1] = rgbe[1];
150
+ scratch[x + width * 2] = rgbe[2];
151
+ scratch[x + width * 3] = rgbe[3];
152
+ }
153
+ s.push(scanlineheader[0], scanlineheader[1], scanlineheader[2], scanlineheader[3]);
154
+ /* RLE each component separately */
155
+ for (c = 0; c < 4; c++) {
156
+ const comp = scratch.subarray(width * c);
157
+ x = 0;
158
+ while (x < width) {
159
+ // find first run
160
+ r = x;
161
+ while (r + 2 < width) {
162
+ if (comp[r] === comp[r + 1] && comp[r] === comp[r + 2])
163
+ break;
164
+ ++r;
165
+ }
166
+ if (r + 2 >= width)
167
+ r = width;
168
+ // dump up to first run
169
+ while (x < r) {
170
+ let len = r - x;
171
+ if (len > 128)
172
+ len = 128;
173
+ write_dump_data(s, len, comp.subarray(x));
174
+ x += len;
175
+ }
176
+ // if there's a run, output it
177
+ if (r + 2 < width) {
178
+ // same test as what we break out of in search loop, so only true if we break'd
179
+ // find next byte after run
180
+ while (r < width && comp[r] == comp[x])
181
+ ++r;
182
+ // output run up to r
183
+ while (x < r) {
184
+ let len = r - x;
185
+ if (len > 127)
186
+ len = 127;
187
+ write_run_data(s, len, comp[x]);
188
+ x += len;
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
194
+ }
195
+ function write_dump_data(s, length, data) {
196
+ const lengthbyte = length & 0xff;
197
+ if (!(length <= 128))
198
+ throw new Error('length is greater than 128');
199
+ s.push(lengthbyte);
200
+ for (let i = 0; i < length; i++) {
201
+ s.push(data[i]);
202
+ }
203
+ }
204
+ function write_run_data(s, length, databyte) {
205
+ const lengthbyte = (length + 128) & 0xff;
206
+ if (!(length + 128 <= 255))
207
+ throw new Error('length is greater than 128');
208
+ s.push(lengthbyte, databyte);
209
+ }
210
+ function testMagic(uint8, signature) {
211
+ const l = signature.length;
212
+ for (let i = 0; i < l; i++) {
213
+ if (uint8[i] !== signature.charCodeAt(i)) {
214
+ return false;
215
+ }
216
+ }
217
+ return true;
218
+ }
219
+ function isHdr(uint8) {
220
+ let r = testMagic(uint8, '#?RADIANCE\n');
221
+ if (!r) {
222
+ r = testMagic(uint8, '#?RGBE\n');
223
+ }
224
+ return r;
225
+ }
226
+ const MAX_HEADER_LENGTH = 1024 * 10;
227
+ const MAX_DIMENSIONS = 1 << 24;
228
+ /**
229
+ * Read a RGBE(.hdr) file from buffer
230
+ * @param uint8 RGBE(.hdr) file buffer
231
+ * @returns Failure reason or resolved data.
232
+ */
233
+ function read_hdr(uint8) {
234
+ let header = '';
235
+ let pos = 0;
236
+ if (!isHdr(uint8)) {
237
+ return 'Corrupt HDR image.';
238
+ }
239
+ // read header
240
+ while (!header.match(/\n\n[^\n]+\n/g) && pos < MAX_HEADER_LENGTH) {
241
+ header += String.fromCharCode(uint8[pos++]);
242
+ }
243
+ // check format
244
+ const format = header.match(/FORMAT=(.*)$/m)?.[1];
245
+ if (format !== '32-bit_rle_rgbe') {
246
+ return 'Unsupported HDR format: ' + format;
247
+ }
248
+ // parse resolution
249
+ const rez = header.split(/\n/).reverse()[1].split(' ');
250
+ if (rez[0] !== '-Y' || rez[2] !== '+X') {
251
+ return 'Unsupported HDR format';
252
+ }
253
+ const width = Number.parseFloat(rez[3]);
254
+ const height = Number.parseFloat(rez[1]);
255
+ if (width > MAX_DIMENSIONS || height > MAX_DIMENSIONS) {
256
+ return 'Very large image (corrupt?)';
257
+ }
258
+ let i, j;
259
+ let c1 = uint8[pos];
260
+ let c2 = uint8[pos + 1];
261
+ let len = uint8[pos + 2];
262
+ // not run-length encoded, so we have to actually use THIS data as a decoded
263
+ // pixel (note this can't be a valid pixel--one of RGB must be >= 128)
264
+ const notRLE = c1 !== 2 || c2 !== 2 || !!(len & 0x80); // not run-length encoded
265
+ const hdrData = new Float32Array(width * height * 3);
266
+ if (width < 8 || width >= 32768 || notRLE) {
267
+ // 32768: 2^15
268
+ // Read flat data
269
+ for (j = 0; j < height; ++j) {
270
+ for (i = 0; i < width; ++i) {
271
+ const rgbe = uint8.subarray(pos, pos + 4);
272
+ pos += 4;
273
+ const start = (j * width + i) * 3;
274
+ rgbe2float(rgbe, hdrData.subarray(start, start + 3));
275
+ }
276
+ }
277
+ }
278
+ else {
279
+ // Read RLE-encoded data
280
+ let scanline;
281
+ let c1;
282
+ let c2;
283
+ let len;
284
+ for (let j = 0; j < height; j++) {
285
+ c1 = uint8[pos++];
286
+ c2 = uint8[pos++];
287
+ len = uint8[pos++];
288
+ if (c1 !== 2 || c2 !== 2 || len & 0x80) {
289
+ return 'Invalid scanline';
290
+ }
291
+ len = len << 8;
292
+ len |= uint8[pos++];
293
+ if (len !== width) {
294
+ return 'invalid decoded scanline length';
295
+ }
296
+ if (!scanline) {
297
+ scanline = new Uint8Array(width * 4);
298
+ }
299
+ let count;
300
+ let value;
301
+ for (let k = 0; k < 4; k++) {
302
+ let nLeft;
303
+ i = 0;
304
+ while ((nLeft = width - i) > 0) {
305
+ count = uint8[pos++];
306
+ if (count > 128) {
307
+ // is RUN
308
+ value = uint8[pos++];
309
+ count -= 128;
310
+ if (count > nLeft) {
311
+ return 'bad RLE data in HDR';
312
+ }
313
+ for (let z = 0; z < count; z++) {
314
+ scanline[i++ * 4 + k] = value;
315
+ }
316
+ }
317
+ else {
318
+ // is DUMP
319
+ if (count > nLeft) {
320
+ return 'bad RLE data in HDR';
321
+ }
322
+ for (let z = 0; z < count; z++) {
323
+ scanline[i++ * 4 + k] = uint8[pos++];
324
+ }
325
+ }
326
+ }
327
+ }
328
+ for (let i = 0; i < width; i++) {
329
+ rgbe2float(scanline.subarray(i * 4), hdrData.subarray((j * width + i) * 3));
330
+ }
331
+ }
332
+ }
333
+ return {
334
+ rgbFloat: hdrData,
335
+ width: width,
336
+ height: height
337
+ };
338
+ }
339
+ export { read_hdr as readHDR, write_hdr as writeHDR, float2rgbe, rgbe2float };
340
+ //# sourceMappingURL=hdr.js.map