@realsee/hdr-toolbox 1.0.2 → 1.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 +49 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +39 -6
- package/dist/cli.js.map +1 -1
- package/dist/convert.d.ts +49 -0
- package/dist/convert.d.ts.map +1 -0
- package/dist/convert.js +174 -0
- package/dist/convert.js.map +1 -0
- package/dist/exr.d.ts +26 -0
- package/dist/exr.d.ts.map +1 -0
- package/dist/exr.js +291 -0
- package/dist/exr.js.map +1 -0
- package/dist/hdr.d.ts +6 -0
- package/dist/hdr.d.ts.map +1 -0
- package/dist/hdr.js +263 -0
- package/dist/hdr.js.map +1 -0
- package/dist/image-format.d.ts +30 -0
- package/dist/image-format.d.ts.map +1 -0
- package/dist/image-format.js +67 -0
- package/dist/image-format.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/jpeg.d.ts +8 -0
- package/dist/jpeg.d.ts.map +1 -1
- package/dist/jpeg.js +57 -6
- package/dist/jpeg.js.map +1 -1
- package/dist/ultrahdr.d.ts +3 -1
- package/dist/ultrahdr.d.ts.map +1 -1
- package/dist/ultrahdr.js +16 -3
- package/dist/ultrahdr.js.map +1 -1
- package/package.json +1 -1
package/dist/exr.js
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { inflateSync } from "node:zlib";
|
|
2
|
+
const MAGIC = 20000630;
|
|
3
|
+
const PIXEL_TYPE_HALF = 1;
|
|
4
|
+
const PIXEL_TYPE_FLOAT = 2;
|
|
5
|
+
const COMPRESSION_NONE = 0;
|
|
6
|
+
const COMPRESSION_RLE = 1;
|
|
7
|
+
const COMPRESSION_ZIPS = 2;
|
|
8
|
+
const COMPRESSION_ZIP = 3;
|
|
9
|
+
/** ZIP/ZIPS pack 16 scanlines per chunk; ZIPS packs a single scanline. */
|
|
10
|
+
const ZIP_ROWS_PER_CHUNK = 16;
|
|
11
|
+
function halfToFloat(half) {
|
|
12
|
+
const sign = (half & 0x8000) >> 15;
|
|
13
|
+
const exponent = (half & 0x7c00) >> 10;
|
|
14
|
+
const fraction = half & 0x03ff;
|
|
15
|
+
if (exponent === 0) {
|
|
16
|
+
return (sign ? -1 : 1) * 2 ** -14 * (fraction / 1024);
|
|
17
|
+
}
|
|
18
|
+
if (exponent === 0x1f) {
|
|
19
|
+
return fraction ? Number.NaN : (sign ? -1 : 1) * Number.POSITIVE_INFINITY;
|
|
20
|
+
}
|
|
21
|
+
return (sign ? -1 : 1) * 2 ** (exponent - 15) * (1 + fraction / 1024);
|
|
22
|
+
}
|
|
23
|
+
class ByteReader {
|
|
24
|
+
view;
|
|
25
|
+
offset = 0;
|
|
26
|
+
constructor(view) {
|
|
27
|
+
this.view = view;
|
|
28
|
+
}
|
|
29
|
+
uint8() {
|
|
30
|
+
return this.view.getUint8(this.offset++);
|
|
31
|
+
}
|
|
32
|
+
int32() {
|
|
33
|
+
const value = this.view.getInt32(this.offset, true);
|
|
34
|
+
this.offset += 4;
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
uint32() {
|
|
38
|
+
const value = this.view.getUint32(this.offset, true);
|
|
39
|
+
this.offset += 4;
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
uint64() {
|
|
43
|
+
const low = this.view.getUint32(this.offset, true);
|
|
44
|
+
const high = this.view.getUint32(this.offset + 4, true);
|
|
45
|
+
this.offset += 8;
|
|
46
|
+
return high * 0x1_0000_0000 + low;
|
|
47
|
+
}
|
|
48
|
+
nullString() {
|
|
49
|
+
let result = "";
|
|
50
|
+
for (let byte = this.uint8(); byte !== 0; byte = this.uint8()) {
|
|
51
|
+
result += String.fromCharCode(byte);
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
skip(count) {
|
|
56
|
+
this.offset += count;
|
|
57
|
+
}
|
|
58
|
+
get position() {
|
|
59
|
+
return this.offset;
|
|
60
|
+
}
|
|
61
|
+
set position(value) {
|
|
62
|
+
this.offset = value;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function parseChannels(reader) {
|
|
66
|
+
const channels = [];
|
|
67
|
+
let byteOffset = 0;
|
|
68
|
+
// The channel list ends with an empty channel name (a lone null byte).
|
|
69
|
+
while (true) {
|
|
70
|
+
const name = reader.nullString();
|
|
71
|
+
if (name === "")
|
|
72
|
+
break;
|
|
73
|
+
const pixelType = reader.int32();
|
|
74
|
+
reader.skip(4); // pLinear + reserved
|
|
75
|
+
reader.skip(8); // xSampling + ySampling
|
|
76
|
+
const byteSize = pixelType === PIXEL_TYPE_FLOAT ? 4 : pixelType === PIXEL_TYPE_HALF ? 2 : 0;
|
|
77
|
+
if (byteSize === 0)
|
|
78
|
+
throw new Error(`Unsupported EXR channel pixel type for "${name}": ${pixelType}.`);
|
|
79
|
+
channels.push({ name, pixelType, byteOffset, byteSize });
|
|
80
|
+
byteOffset += byteSize;
|
|
81
|
+
}
|
|
82
|
+
// EXR stores channels alphabetically; byte offsets within a pixel follow that
|
|
83
|
+
// same order, which is exactly how we accumulated them above.
|
|
84
|
+
return channels;
|
|
85
|
+
}
|
|
86
|
+
function decompressChunk(compression, payload, expectedSize) {
|
|
87
|
+
if (compression === COMPRESSION_NONE)
|
|
88
|
+
return payload;
|
|
89
|
+
if (compression === COMPRESSION_ZIP || compression === COMPRESSION_ZIPS) {
|
|
90
|
+
const inflated = inflateSync(payload);
|
|
91
|
+
return reconstructZip(inflated, expectedSize);
|
|
92
|
+
}
|
|
93
|
+
throw new Error(`Unsupported EXR compression type: ${compression}.`);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Undoes the two reversible transforms the EXR ZIP codec applies before
|
|
97
|
+
* deflate: a per-byte delta (predictor) and an interleave of the two byte
|
|
98
|
+
* halves. Mirrors the reference OpenEXR implementation.
|
|
99
|
+
*/
|
|
100
|
+
function reconstructZip(source, expectedSize) {
|
|
101
|
+
const buffer = Uint8Array.prototype.slice.call(source, 0, expectedSize);
|
|
102
|
+
for (let index = 1; index < buffer.length; index++) {
|
|
103
|
+
const delta = buffer[index - 1] + buffer[index] - 128;
|
|
104
|
+
buffer[index] = delta & 0xff;
|
|
105
|
+
}
|
|
106
|
+
const result = new Uint8Array(buffer.length);
|
|
107
|
+
const half = Math.floor((buffer.length + 1) / 2);
|
|
108
|
+
let low = 0;
|
|
109
|
+
let high = half;
|
|
110
|
+
let out = 0;
|
|
111
|
+
while (out < result.length) {
|
|
112
|
+
result[out++] = buffer[low++];
|
|
113
|
+
if (out < result.length)
|
|
114
|
+
result[out++] = buffer[high++];
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
/** Reads a linear RGB EXR into interleaved float RGB, dropping any alpha. */
|
|
119
|
+
export function readExr(buffer) {
|
|
120
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
121
|
+
const reader = new ByteReader(view);
|
|
122
|
+
if (reader.uint32() !== MAGIC)
|
|
123
|
+
throw new Error("Not an OpenEXR file (bad magic number).");
|
|
124
|
+
reader.skip(4); // version + flags; single-part scanline only
|
|
125
|
+
let channels;
|
|
126
|
+
let compression = COMPRESSION_NONE;
|
|
127
|
+
let dataWindow;
|
|
128
|
+
// Header: a sequence of (name,type,size,value) attributes ending at a null byte.
|
|
129
|
+
while (true) {
|
|
130
|
+
const attributeName = reader.nullString();
|
|
131
|
+
if (attributeName === "")
|
|
132
|
+
break;
|
|
133
|
+
reader.nullString(); // attribute type
|
|
134
|
+
const size = reader.int32();
|
|
135
|
+
const next = reader.position + size;
|
|
136
|
+
if (attributeName === "channels") {
|
|
137
|
+
channels = parseChannels(reader);
|
|
138
|
+
}
|
|
139
|
+
else if (attributeName === "compression") {
|
|
140
|
+
compression = reader.uint8();
|
|
141
|
+
}
|
|
142
|
+
else if (attributeName === "dataWindow") {
|
|
143
|
+
dataWindow = {
|
|
144
|
+
xMin: reader.int32(),
|
|
145
|
+
yMin: reader.int32(),
|
|
146
|
+
xMax: reader.int32(),
|
|
147
|
+
yMax: reader.int32(),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
reader.position = next;
|
|
151
|
+
}
|
|
152
|
+
if (!channels || !dataWindow)
|
|
153
|
+
throw new Error("EXR header is missing channels or dataWindow.");
|
|
154
|
+
if (compression === COMPRESSION_RLE)
|
|
155
|
+
throw new Error("RLE-compressed EXR files are not supported.");
|
|
156
|
+
const width = dataWindow.xMax - dataWindow.xMin + 1;
|
|
157
|
+
const height = dataWindow.yMax - dataWindow.yMin + 1;
|
|
158
|
+
if (width <= 0 || height <= 0)
|
|
159
|
+
throw new Error("EXR data window is empty.");
|
|
160
|
+
const channelByName = new Map(channels.map((channel) => [channel.name, channel]));
|
|
161
|
+
const red = channelByName.get("R");
|
|
162
|
+
const green = channelByName.get("G");
|
|
163
|
+
const blue = channelByName.get("B");
|
|
164
|
+
if (!red || !green || !blue)
|
|
165
|
+
throw new Error("EXR file must contain R, G and B channels for HDR conversion.");
|
|
166
|
+
const bytesPerPixel = channels.reduce((sum, channel) => sum + channel.byteSize, 0);
|
|
167
|
+
const rowsPerChunk = compression === COMPRESSION_ZIP ? ZIP_ROWS_PER_CHUNK : 1;
|
|
168
|
+
const chunkCount = Math.ceil(height / rowsPerChunk);
|
|
169
|
+
// Offset table: one uint64 file offset per chunk, in scanline order.
|
|
170
|
+
const chunkOffsets = [];
|
|
171
|
+
for (let index = 0; index < chunkCount; index++)
|
|
172
|
+
chunkOffsets.push(reader.uint64());
|
|
173
|
+
const output = new Float32Array(width * height * 3);
|
|
174
|
+
const readSample = (block, offset, pixelType) => pixelType === PIXEL_TYPE_FLOAT
|
|
175
|
+
? block.getFloat32(offset, true)
|
|
176
|
+
: halfToFloat(block.getUint16(offset, true));
|
|
177
|
+
for (let chunk = 0; chunk < chunkCount; chunk++) {
|
|
178
|
+
reader.position = chunkOffsets[chunk];
|
|
179
|
+
const firstRow = reader.int32();
|
|
180
|
+
const dataSize = reader.int32();
|
|
181
|
+
const start = reader.position;
|
|
182
|
+
const rowsInChunk = Math.min(rowsPerChunk, height - (firstRow - dataWindow.yMin));
|
|
183
|
+
const expectedSize = rowsInChunk * width * bytesPerPixel;
|
|
184
|
+
const payload = new Uint8Array(buffer.buffer, buffer.byteOffset + start, dataSize);
|
|
185
|
+
const pixels = decompressChunk(compression, payload, expectedSize);
|
|
186
|
+
const block = new DataView(pixels.buffer, pixels.byteOffset, pixels.byteLength);
|
|
187
|
+
for (let row = 0; row < rowsInChunk; row++) {
|
|
188
|
+
const imageRow = firstRow - dataWindow.yMin + row;
|
|
189
|
+
const rowStart = row * width * bytesPerPixel;
|
|
190
|
+
for (let channel of channels) {
|
|
191
|
+
if (channel.name !== "R" && channel.name !== "G" && channel.name !== "B")
|
|
192
|
+
continue;
|
|
193
|
+
const target = channel.name === "R" ? 0 : channel.name === "G" ? 1 : 2;
|
|
194
|
+
let sampleOffset = rowStart + channel.byteOffset * width;
|
|
195
|
+
let pixelIndex = imageRow * width * 3 + target;
|
|
196
|
+
for (let x = 0; x < width; x++) {
|
|
197
|
+
output[pixelIndex] = readSample(block, sampleOffset, channel.pixelType);
|
|
198
|
+
sampleOffset += channel.byteSize;
|
|
199
|
+
pixelIndex += 3;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return { width, height, data: output };
|
|
205
|
+
}
|
|
206
|
+
function writeAttribute(parts, name, type, value) {
|
|
207
|
+
parts.push(Buffer.from(`${name}\0${type}\0`, "latin1"));
|
|
208
|
+
const size = Buffer.alloc(4);
|
|
209
|
+
size.writeInt32LE(value.length, 0);
|
|
210
|
+
parts.push(size, value);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Writes interleaved linear float RGB as an uncompressed single-part scanline
|
|
214
|
+
* EXR. Channels are emitted alphabetically (B, G, R) as the format requires.
|
|
215
|
+
*/
|
|
216
|
+
export function writeExr(image) {
|
|
217
|
+
const { width, height, data } = image;
|
|
218
|
+
if (data.length !== width * height * 3)
|
|
219
|
+
throw new Error("EXR pixel data length does not match width * height * 3.");
|
|
220
|
+
const header = [];
|
|
221
|
+
const magic = Buffer.alloc(8);
|
|
222
|
+
magic.writeUInt32LE(MAGIC, 0);
|
|
223
|
+
magic.writeUInt32LE(2, 4); // version 2, scanline, single-part
|
|
224
|
+
header.push(magic);
|
|
225
|
+
// channels: alphabetical B, G, R, each FLOAT with xSampling=ySampling=1.
|
|
226
|
+
const channelParts = [];
|
|
227
|
+
for (const name of ["B", "G", "R"]) {
|
|
228
|
+
const entry = Buffer.alloc(name.length + 1 + 16);
|
|
229
|
+
entry.write(`${name}\0`, 0, "latin1");
|
|
230
|
+
let p = name.length + 1;
|
|
231
|
+
entry.writeInt32LE(PIXEL_TYPE_FLOAT, p); // pixelType
|
|
232
|
+
p += 4;
|
|
233
|
+
entry.writeInt32LE(0, p); // pLinear + reserved
|
|
234
|
+
p += 4;
|
|
235
|
+
entry.writeInt32LE(1, p); // xSampling
|
|
236
|
+
p += 4;
|
|
237
|
+
entry.writeInt32LE(1, p); // ySampling
|
|
238
|
+
channelParts.push(entry);
|
|
239
|
+
}
|
|
240
|
+
channelParts.push(Buffer.from([0]));
|
|
241
|
+
writeAttribute(header, "channels", "chlist", Buffer.concat(channelParts));
|
|
242
|
+
writeAttribute(header, "compression", "compression", Buffer.from([COMPRESSION_NONE]));
|
|
243
|
+
const window = Buffer.alloc(16);
|
|
244
|
+
window.writeInt32LE(0, 0);
|
|
245
|
+
window.writeInt32LE(0, 4);
|
|
246
|
+
window.writeInt32LE(width - 1, 8);
|
|
247
|
+
window.writeInt32LE(height - 1, 12);
|
|
248
|
+
writeAttribute(header, "dataWindow", "box2i", window);
|
|
249
|
+
writeAttribute(header, "displayWindow", "box2i", window);
|
|
250
|
+
const lineOrder = Buffer.from([0]); // INCREASING_Y
|
|
251
|
+
writeAttribute(header, "lineOrder", "lineOrder", lineOrder);
|
|
252
|
+
const screenWindowCenter = Buffer.alloc(8); // 0,0 floats
|
|
253
|
+
writeAttribute(header, "screenWindowCenter", "v2f", screenWindowCenter);
|
|
254
|
+
const screenWindowWidth = Buffer.alloc(4);
|
|
255
|
+
screenWindowWidth.writeFloatLE(1, 0);
|
|
256
|
+
writeAttribute(header, "screenWindowWidth", "float", screenWindowWidth);
|
|
257
|
+
const pixelAspectRatio = Buffer.alloc(4);
|
|
258
|
+
pixelAspectRatio.writeFloatLE(1, 0);
|
|
259
|
+
writeAttribute(header, "pixelAspectRatio", "float", pixelAspectRatio);
|
|
260
|
+
header.push(Buffer.from([0])); // end of header
|
|
261
|
+
const bytesPerChannelRow = width * 4;
|
|
262
|
+
const scanlineDataSize = bytesPerChannelRow * 3;
|
|
263
|
+
const scanlineRecord = 8 + scanlineDataSize; // y (int) + size (int) + data
|
|
264
|
+
const headerBuffer = Buffer.concat(header);
|
|
265
|
+
const offsetTableSize = height * 8;
|
|
266
|
+
const pixelDataStart = headerBuffer.length + offsetTableSize;
|
|
267
|
+
const offsetTable = Buffer.alloc(offsetTableSize);
|
|
268
|
+
for (let y = 0; y < height; y++) {
|
|
269
|
+
offsetTable.writeBigUInt64LE(BigInt(pixelDataStart + y * scanlineRecord), y * 8);
|
|
270
|
+
}
|
|
271
|
+
const pixelData = Buffer.alloc(height * scanlineRecord);
|
|
272
|
+
for (let y = 0; y < height; y++) {
|
|
273
|
+
const base = y * scanlineRecord;
|
|
274
|
+
pixelData.writeInt32LE(y, base);
|
|
275
|
+
pixelData.writeInt32LE(scanlineDataSize, base + 4);
|
|
276
|
+
const rowStart = base + 8;
|
|
277
|
+
// Channel order within a scanline matches the (alphabetical) channel list.
|
|
278
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
279
|
+
const source = channel === 0 ? 2 : channel === 1 ? 1 : 0; // B,G,R -> data index
|
|
280
|
+
let out = rowStart + channel * bytesPerChannelRow;
|
|
281
|
+
let pixel = y * width * 3 + source;
|
|
282
|
+
for (let x = 0; x < width; x++) {
|
|
283
|
+
pixelData.writeFloatLE(data[pixel], out);
|
|
284
|
+
out += 4;
|
|
285
|
+
pixel += 3;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return Buffer.concat([headerBuffer, offsetTable, pixelData]);
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=exr.js.map
|
package/dist/exr.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exr.js","sourceRoot":"","sources":["../src/exr.ts"],"names":[],"mappings":"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"}
|
package/dist/hdr.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LinearHdrImage } from "./exr.js";
|
|
2
|
+
/** Reads a Radiance HDR file into interleaved linear float RGB. */
|
|
3
|
+
export declare function readHdr(buffer: Buffer): LinearHdrImage;
|
|
4
|
+
/** Writes interleaved linear float RGB as a new-style RLE Radiance HDR file. */
|
|
5
|
+
export declare function writeHdr(image: LinearHdrImage): Buffer;
|
|
6
|
+
//# sourceMappingURL=hdr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hdr.d.ts","sourceRoot":"","sources":["../src/hdr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAsH/C,mEAAmE;AACnE,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAwBtD;AA6ED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CA6BtD"}
|
package/dist/hdr.js
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal Radiance HDR (RGBE, ".hdr"/".pic") reader and writer for linear
|
|
3
|
+
* scanline RGB images.
|
|
4
|
+
*
|
|
5
|
+
* RGBE stores three 8-bit mantissas plus one shared 8-bit exponent per pixel,
|
|
6
|
+
* giving a wide dynamic range in 32 bits. This module reads the flat and
|
|
7
|
+
* new-style (adaptive) RLE encodings and always writes the new-style RLE form,
|
|
8
|
+
* which every Radiance reader understands. Pixels are exchanged as interleaved
|
|
9
|
+
* linear float RGB, matching the EXR codec so both share one conversion path.
|
|
10
|
+
*/
|
|
11
|
+
const EXPONENT_BIAS = 128;
|
|
12
|
+
/**
|
|
13
|
+
* Converts one RGBE quadruple to linear float RGB, writing into `out`.
|
|
14
|
+
*
|
|
15
|
+
* With the shared exponent byte `e`, each mantissa byte decodes as
|
|
16
|
+
* `byte * 2^(e - 128 - 8)`, where the -8 undoes the 0-255 mantissa scale. This
|
|
17
|
+
* matches the common three.js/parse-hdr convention (no half-bucket bias), which
|
|
18
|
+
* keeps near-zero channels at zero.
|
|
19
|
+
*/
|
|
20
|
+
function rgbeToFloat(r, g, b, e, out, offset) {
|
|
21
|
+
if (e === 0) {
|
|
22
|
+
out[offset] = 0;
|
|
23
|
+
out[offset + 1] = 0;
|
|
24
|
+
out[offset + 2] = 0;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const scale = 2 ** (e - (EXPONENT_BIAS + 8));
|
|
28
|
+
out[offset] = r * scale;
|
|
29
|
+
out[offset + 1] = g * scale;
|
|
30
|
+
out[offset + 2] = b * scale;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Converts one linear float RGB pixel to an RGBE quadruple.
|
|
34
|
+
*
|
|
35
|
+
* Mirrors the reference Radiance encoder: decompose the channel maximum as
|
|
36
|
+
* `max = mantissa * 2^exponent` with `mantissa` in [0.5, 1) (i.e. frexp), then
|
|
37
|
+
* scale each channel by `mantissa / max * 256` and store `exponent + 128`.
|
|
38
|
+
*/
|
|
39
|
+
function floatToRgbe(r, g, b) {
|
|
40
|
+
const max = Math.max(r, g, b);
|
|
41
|
+
if (max <= 1e-32)
|
|
42
|
+
return [0, 0, 0, 0];
|
|
43
|
+
// frexp exponent: the e with max / 2^e in [0.5, 1).
|
|
44
|
+
const exponent = Math.floor(Math.log2(max)) + 1;
|
|
45
|
+
const factor = 2 ** -exponent * 256;
|
|
46
|
+
// Round (not floor) so the quantisation error is centred, since the decoder
|
|
47
|
+
// does not add a half-bucket bias.
|
|
48
|
+
const clampByte = (value) => {
|
|
49
|
+
const byte = Math.round(value * factor);
|
|
50
|
+
return byte < 0 ? 0 : byte > 255 ? 255 : byte;
|
|
51
|
+
};
|
|
52
|
+
return [clampByte(r), clampByte(g), clampByte(b), exponent + EXPONENT_BIAS];
|
|
53
|
+
}
|
|
54
|
+
function readHeader(buffer) {
|
|
55
|
+
let offset = 0;
|
|
56
|
+
const readLine = () => {
|
|
57
|
+
let line = "";
|
|
58
|
+
while (offset < buffer.length) {
|
|
59
|
+
const byte = buffer[offset++];
|
|
60
|
+
if (byte === 0x0a)
|
|
61
|
+
break;
|
|
62
|
+
line += String.fromCharCode(byte);
|
|
63
|
+
}
|
|
64
|
+
return line;
|
|
65
|
+
};
|
|
66
|
+
const magic = readLine();
|
|
67
|
+
if (!magic.startsWith("#?"))
|
|
68
|
+
throw new Error("Not a Radiance HDR file (missing #? signature).");
|
|
69
|
+
let format;
|
|
70
|
+
// Header lines continue until a blank line separates them from the resolution.
|
|
71
|
+
while (offset < buffer.length) {
|
|
72
|
+
const line = readLine();
|
|
73
|
+
if (line === "")
|
|
74
|
+
break;
|
|
75
|
+
const match = /^FORMAT=(.+)$/.exec(line);
|
|
76
|
+
if (match)
|
|
77
|
+
format = match[1].trim();
|
|
78
|
+
}
|
|
79
|
+
if (format && format !== "32-bit_rle_rgbe")
|
|
80
|
+
throw new Error(`Unsupported Radiance HDR format "${format}" (only 32-bit_rle_rgbe).`);
|
|
81
|
+
const resolution = readLine();
|
|
82
|
+
// Standard orientation is "-Y height +X width"; accept the common variants.
|
|
83
|
+
const match = /([+-][XY])\s+(\d+)\s+([+-][XY])\s+(\d+)/.exec(resolution);
|
|
84
|
+
if (!match)
|
|
85
|
+
throw new Error(`Unsupported Radiance HDR resolution line: "${resolution}".`);
|
|
86
|
+
const [, axis1, size1, axis2, size2] = match;
|
|
87
|
+
let width;
|
|
88
|
+
let height;
|
|
89
|
+
let flipY = false;
|
|
90
|
+
if (axis1.endsWith("Y")) {
|
|
91
|
+
height = Number(size1);
|
|
92
|
+
width = Number(size2);
|
|
93
|
+
flipY = axis1.startsWith("+");
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
width = Number(size1);
|
|
97
|
+
height = Number(size2);
|
|
98
|
+
flipY = axis2.startsWith("+");
|
|
99
|
+
}
|
|
100
|
+
if (axis1.endsWith(axis2.charAt(1)))
|
|
101
|
+
throw new Error("Radiance HDR resolution line must specify one X and one Y axis.");
|
|
102
|
+
return { width, height, flipY, dataStart: offset };
|
|
103
|
+
}
|
|
104
|
+
/** Reads a Radiance HDR file into interleaved linear float RGB. */
|
|
105
|
+
export function readHdr(buffer) {
|
|
106
|
+
const { width, height, flipY, dataStart } = readHeader(buffer);
|
|
107
|
+
const data = new Float32Array(width * height * 3);
|
|
108
|
+
let offset = dataStart;
|
|
109
|
+
const scanline = new Uint8Array(width * 4);
|
|
110
|
+
for (let row = 0; row < height; row++) {
|
|
111
|
+
offset = readScanline(buffer, offset, width, scanline);
|
|
112
|
+
const targetRow = flipY ? height - 1 - row : row;
|
|
113
|
+
let out = targetRow * width * 3;
|
|
114
|
+
for (let x = 0; x < width; x++) {
|
|
115
|
+
rgbeToFloat(scanline[x * 4], scanline[x * 4 + 1], scanline[x * 4 + 2], scanline[x * 4 + 3], data, out);
|
|
116
|
+
out += 3;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return { width, height, data };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Decodes one scanline into `scanline` as width*4 RGBE bytes and returns the new
|
|
123
|
+
* read offset. Handles new-style adaptive RLE, old-style RLE, and flat pixels.
|
|
124
|
+
*/
|
|
125
|
+
function readScanline(buffer, start, width, scanline) {
|
|
126
|
+
let offset = start;
|
|
127
|
+
// New-style RLE scanlines begin with the marker 0x02 0x02 and a 16-bit width.
|
|
128
|
+
const isNewStyle = width >= 8 &&
|
|
129
|
+
width <= 0x7fff &&
|
|
130
|
+
buffer[offset] === 2 &&
|
|
131
|
+
buffer[offset + 1] === 2 &&
|
|
132
|
+
((buffer[offset + 2] << 8) | buffer[offset + 3]) === width;
|
|
133
|
+
if (!isNewStyle)
|
|
134
|
+
return readFlatOrOldScanline(buffer, offset, width, scanline);
|
|
135
|
+
offset += 4;
|
|
136
|
+
// Each of the four RGBE components is run-length encoded separately.
|
|
137
|
+
for (let channel = 0; channel < 4; channel++) {
|
|
138
|
+
let x = 0;
|
|
139
|
+
while (x < width) {
|
|
140
|
+
let count = buffer[offset++];
|
|
141
|
+
if (count > 128) {
|
|
142
|
+
// A run: the next byte repeats (count - 128) times.
|
|
143
|
+
const value = buffer[offset++];
|
|
144
|
+
count -= 128;
|
|
145
|
+
while (count-- > 0)
|
|
146
|
+
scanline[(x++ << 2) + channel] = value;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
// A dump: `count` literal bytes follow.
|
|
150
|
+
while (count-- > 0)
|
|
151
|
+
scanline[(x++ << 2) + channel] = buffer[offset++];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return offset;
|
|
156
|
+
}
|
|
157
|
+
/** Reads a flat (uncompressed) or old-style RLE scanline. */
|
|
158
|
+
function readFlatOrOldScanline(buffer, start, width, scanline) {
|
|
159
|
+
let offset = start;
|
|
160
|
+
let x = 0;
|
|
161
|
+
let repeatShift = 0;
|
|
162
|
+
while (x < width) {
|
|
163
|
+
const r = buffer[offset++];
|
|
164
|
+
const g = buffer[offset++];
|
|
165
|
+
const b = buffer[offset++];
|
|
166
|
+
const e = buffer[offset++];
|
|
167
|
+
// Old-style RLE: an (1,1,1,count) pixel repeats the previous one count<<shift times.
|
|
168
|
+
if (r === 1 && g === 1 && b === 1 && x > 0) {
|
|
169
|
+
let count = e << repeatShift;
|
|
170
|
+
const base = (x - 1) * 4;
|
|
171
|
+
while (count-- > 0 && x < width) {
|
|
172
|
+
scanline[x * 4] = scanline[base];
|
|
173
|
+
scanline[x * 4 + 1] = scanline[base + 1];
|
|
174
|
+
scanline[x * 4 + 2] = scanline[base + 2];
|
|
175
|
+
scanline[x * 4 + 3] = scanline[base + 3];
|
|
176
|
+
x++;
|
|
177
|
+
}
|
|
178
|
+
repeatShift += 8;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
scanline[x * 4] = r;
|
|
182
|
+
scanline[x * 4 + 1] = g;
|
|
183
|
+
scanline[x * 4 + 2] = b;
|
|
184
|
+
scanline[x * 4 + 3] = e;
|
|
185
|
+
x++;
|
|
186
|
+
repeatShift = 0;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return offset;
|
|
190
|
+
}
|
|
191
|
+
/** Writes interleaved linear float RGB as a new-style RLE Radiance HDR file. */
|
|
192
|
+
export function writeHdr(image) {
|
|
193
|
+
const { width, height, data } = image;
|
|
194
|
+
if (data.length !== width * height * 3)
|
|
195
|
+
throw new Error("HDR pixel data length does not match width * height * 3.");
|
|
196
|
+
const header = Buffer.from(`#?RADIANCE\nFORMAT=32-bit_rle_rgbe\n\n-Y ${height} +X ${width}\n`, "latin1");
|
|
197
|
+
const chunks = [header];
|
|
198
|
+
const rgbe = new Uint8Array(width * 4);
|
|
199
|
+
// New-style RLE requires widths in [8, 32767]; otherwise write flat pixels.
|
|
200
|
+
const useRle = width >= 8 && width <= 0x7fff;
|
|
201
|
+
for (let row = 0; row < height; row++) {
|
|
202
|
+
let source = row * width * 3;
|
|
203
|
+
for (let x = 0; x < width; x++) {
|
|
204
|
+
const [r, g, b, e] = floatToRgbe(data[source], data[source + 1], data[source + 2]);
|
|
205
|
+
rgbe[x * 4] = r;
|
|
206
|
+
rgbe[x * 4 + 1] = g;
|
|
207
|
+
rgbe[x * 4 + 2] = b;
|
|
208
|
+
rgbe[x * 4 + 3] = e;
|
|
209
|
+
source += 3;
|
|
210
|
+
}
|
|
211
|
+
chunks.push(useRle ? encodeRleScanline(rgbe, width) : Buffer.from(rgbe.slice()));
|
|
212
|
+
}
|
|
213
|
+
return Buffer.concat(chunks);
|
|
214
|
+
}
|
|
215
|
+
/** Length of the run starting at `index` for one interleaved RGBE channel. */
|
|
216
|
+
function runLengthAt(rgbe, channel, index, width) {
|
|
217
|
+
const value = rgbe[index * 4 + channel];
|
|
218
|
+
let length = 1;
|
|
219
|
+
while (index + length < width && rgbe[(index + length) * 4 + channel] === value)
|
|
220
|
+
length++;
|
|
221
|
+
return length;
|
|
222
|
+
}
|
|
223
|
+
/** Encodes one width*4 RGBE scanline using new-style adaptive RLE. */
|
|
224
|
+
function encodeRleScanline(rgbe, width) {
|
|
225
|
+
const out = [2, 2, (width >> 8) & 0xff, width & 0xff];
|
|
226
|
+
// Runs of >= 4 bytes are worth encoding; shorter spans go in literal dumps.
|
|
227
|
+
const minRun = 4;
|
|
228
|
+
for (let channel = 0; channel < 4; channel++) {
|
|
229
|
+
let x = 0;
|
|
230
|
+
while (x < width) {
|
|
231
|
+
// Scan forward over bytes that do not start a worthwhile run; those bytes
|
|
232
|
+
// become a literal dump. `runStart` always advances, so this terminates.
|
|
233
|
+
let runStart = x;
|
|
234
|
+
let run = 0;
|
|
235
|
+
while (runStart < width) {
|
|
236
|
+
run = runLengthAt(rgbe, channel, runStart, width);
|
|
237
|
+
if (run >= minRun)
|
|
238
|
+
break;
|
|
239
|
+
runStart += run;
|
|
240
|
+
}
|
|
241
|
+
// Emit the literal span [x, runStart) in chunks of at most 128 bytes.
|
|
242
|
+
while (x < runStart) {
|
|
243
|
+
const dumpLength = Math.min(128, runStart - x);
|
|
244
|
+
out.push(dumpLength);
|
|
245
|
+
for (let i = 0; i < dumpLength; i++)
|
|
246
|
+
out.push(rgbe[(x + i) * 4 + channel]);
|
|
247
|
+
x += dumpLength;
|
|
248
|
+
}
|
|
249
|
+
// Emit the run [runStart, runStart + run) in chunks of at most 127 repeats.
|
|
250
|
+
if (runStart < width) {
|
|
251
|
+
const value = rgbe[runStart * 4 + channel];
|
|
252
|
+
while (run > 0) {
|
|
253
|
+
const chunk = Math.min(127, run);
|
|
254
|
+
out.push(128 + chunk, value);
|
|
255
|
+
run -= chunk;
|
|
256
|
+
x += chunk;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return Buffer.from(out);
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=hdr.js.map
|
package/dist/hdr.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hdr.js","sourceRoot":"","sources":["../src/hdr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Bitmap formats accepted for SDR/gain-map input and produced on extract output. */
|
|
2
|
+
export declare const supportedImageFormats: readonly ["jpeg", "jpg", "png", "avif"];
|
|
3
|
+
export type ImageFormat = (typeof supportedImageFormats)[number];
|
|
4
|
+
/** Canonical form used internally; "jpg" is an alias of "jpeg". */
|
|
5
|
+
export type CanonicalImageFormat = "jpeg" | "png" | "avif";
|
|
6
|
+
export declare function canonicalizeImageFormat(format: ImageFormat): CanonicalImageFormat;
|
|
7
|
+
export declare function isSupportedImageFormat(value: string): value is ImageFormat;
|
|
8
|
+
/**
|
|
9
|
+
* Resolves the desired output format for extraction, preferring an explicit
|
|
10
|
+
* `--format` flag, then the output path extension, then defaulting to JPEG.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveOutputFormat(explicit: string | undefined, outputPath: string): CanonicalImageFormat;
|
|
13
|
+
/**
|
|
14
|
+
* Detects the bitmap format of a buffer via sharp. Returns the canonical format
|
|
15
|
+
* when it is one we support, otherwise throws so callers reject unknown inputs.
|
|
16
|
+
* AVIF is reported by sharp as HEIF with "av1" compression.
|
|
17
|
+
*/
|
|
18
|
+
export declare function detectImageFormat(buffer: Buffer): Promise<CanonicalImageFormat>;
|
|
19
|
+
/**
|
|
20
|
+
* Ensures a buffer is JPEG, transcoding from PNG/AVIF when needed. JPEG inputs
|
|
21
|
+
* are returned untouched so Ultra HDR composition stays byte-for-byte lossless
|
|
22
|
+
* for the common JPEG-in path. The ICC profile, if present, is preserved.
|
|
23
|
+
*/
|
|
24
|
+
export declare function ensureJpegBuffer(buffer: Buffer): Promise<Buffer>;
|
|
25
|
+
/**
|
|
26
|
+
* Transcodes an extracted JPEG subimage to the requested output format. JPEG
|
|
27
|
+
* output is a passthrough of the original bytes to preserve the exact subimage.
|
|
28
|
+
*/
|
|
29
|
+
export declare function encodeImage(jpeg: Buffer, format: CanonicalImageFormat): Promise<Buffer>;
|
|
30
|
+
//# sourceMappingURL=image-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-format.d.ts","sourceRoot":"","sources":["../src/image-format.ts"],"names":[],"mappings":"AAGA,qFAAqF;AACrF,eAAO,MAAM,qBAAqB,yCAA0C,CAAC;AAE7E,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,mEAAmE;AACnE,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAO3D,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,oBAAoB,CAEjF;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,WAAW,CAE1E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,UAAU,EAAE,MAAM,GACjB,oBAAoB,CAWtB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAQrF;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGtE;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAK7F"}
|