@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/README.md
CHANGED
|
@@ -87,7 +87,38 @@ hdr-toolbox cube-to-equirect \
|
|
|
87
87
|
|
|
88
88
|
SDR 文件名为 `<prefix>_[r,l,u,d,f,b].jpg`。gain map 同时兼容 `<prefix>_<face>_gainmap.jpg` 和示例里的 `<prefix>_<face>.gainmap.jpg`。配置自动读取输入目录下的 `<prefix>_gainmap_cfg.json`(找不到时回退 `<prefix>_gainmap_cfg.xmp`)。六面必须是同尺寸、正方形且边长为 2 的幂。输出尺寸是面宽的 4×2 倍。
|
|
89
89
|
|
|
90
|
-
### 4.
|
|
90
|
+
### 4. 线性 HDR(EXR / Radiance HDR)↔ Ultra HDR
|
|
91
|
+
|
|
92
|
+
`convert` 在线性浮点 HDR 文件和 Ultra HDR JPEG 之间互转,方向由输入/输出扩展名推断:一侧是线性 HDR(`.exr` 或 `.hdr`/`.pic`),另一侧是 Ultra HDR(`.jpg`/`.jpeg`)。
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Ultra HDR → EXR:按增益图重建线性 HDR,写成 32-bit float EXR
|
|
96
|
+
hdr-toolbox convert --input examples/ultra-hdr.jpg --output output/ultra-hdr.exr
|
|
97
|
+
|
|
98
|
+
# Ultra HDR → Radiance HDR:同样的重建,写成 RGBE 编码的 .hdr(体积更小)
|
|
99
|
+
hdr-toolbox convert --input examples/ultra-hdr.jpg --output output/ultra-hdr.hdr
|
|
100
|
+
|
|
101
|
+
# EXR / HDR → Ultra HDR:色调映射出 SDR 基图,反算增益图,封装成 Ultra HDR
|
|
102
|
+
hdr-toolbox convert --input output/ultra-hdr.exr --output output/from-exr.uhdr.jpg
|
|
103
|
+
hdr-toolbox convert --input output/ultra-hdr.hdr --output output/from-hdr.uhdr.jpg
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
支持两种线性 HDR 容器:
|
|
107
|
+
|
|
108
|
+
- **EXR**(OpenEXR):读取支持 HALF/FLOAT 通道、NO_COMPRESSION 与 ZIP/ZIPS 压缩;写入固定为单层、未压缩的 scanline FLOAT RGB,任意 EXR 读取器都能打开。
|
|
109
|
+
- **Radiance HDR**(RGBE,`.hdr`/`.pic`):读取支持 flat、旧式与新式 RLE 编码;写入新式 RLE。RGBE 的共享指数带来 ~0.4% 的量化,但体积明显小于未压缩 EXR。
|
|
110
|
+
|
|
111
|
+
`Ultra HDR → 线性 HDR` 按 Adobe/Android 增益图恢复公式逐像素重建,在满显示余量(weight = 1)下还原完整 HDR 意图:`hdr = (sdr_linear + offset_sdr) * 2^lerp(log2(min), log2(max), gain^(1/gamma)) - offset_hdr`。
|
|
112
|
+
|
|
113
|
+
`线性 HDR → Ultra HDR` 用 Reinhard 曲线把线性 HDR 压成 SDR 基图,再把 `HDR/SDR` 比值编码成增益图。可选项(仅此方向生效):
|
|
114
|
+
|
|
115
|
+
| 选项 | 说明 |
|
|
116
|
+
| --------------------- | ----------------------------------------------- |
|
|
117
|
+
| `--max-content-boost` | 要编码的线性 HDR 余量,默认取输入中的最大线性值 |
|
|
118
|
+
| `--sdr-quality` | SDR 基图 JPEG 质量(1-100,默认 95) |
|
|
119
|
+
| `--gainmap-quality` | 增益图 JPEG 质量(1-100,默认 95) |
|
|
120
|
+
|
|
121
|
+
### 5. equirect Ultra HDR → cubemap
|
|
91
122
|
|
|
92
123
|
```bash
|
|
93
124
|
hdr-toolbox equirect-to-cube \
|
|
@@ -118,6 +149,23 @@ await extractUltraHdr({
|
|
|
118
149
|
});
|
|
119
150
|
```
|
|
120
151
|
|
|
152
|
+
线性 HDR 互转(EXR / Radiance HDR,方向中立的函数名;旧的 `exrToUltraHdr` / `ultraHdrToExr` 作为别名保留):
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import { linearHdrToUltraHdr, ultraHdrToLinearHdr } from "@realsee/hdr-toolbox";
|
|
156
|
+
|
|
157
|
+
// 输出格式由扩展名推断:.exr 或 .hdr
|
|
158
|
+
await ultraHdrToLinearHdr({ input: "image.uhdr.jpg", output: "image.hdr" });
|
|
159
|
+
|
|
160
|
+
await linearHdrToUltraHdr({
|
|
161
|
+
input: "image.exr",
|
|
162
|
+
output: "image.uhdr.jpg",
|
|
163
|
+
maxContentBoost: 8, // 可选,不填则按输入峰值自动推断
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
底层的编解码函数 `readExr` / `writeExr` 和 `readHdr` / `writeHdr` 也一并导出,都以交错的线性浮点 RGB(`LinearHdrImage`)作为统一的像素表示。
|
|
168
|
+
|
|
121
169
|
## 校验
|
|
122
170
|
|
|
123
171
|
```bash
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,aAAa,IAAI,OAAO,CA2HvC"}
|
package/dist/cli.js
CHANGED
|
@@ -2,19 +2,24 @@
|
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { linearHdrToUltraHdr, ultraHdrToLinearHdr } from "./convert.js";
|
|
5
6
|
import { cubeToEquirectUltraHdr, equirectUltraHdrToCube } from "./panorama.js";
|
|
6
7
|
import { composeUltraHdr, extractUltraHdr } from "./ultrahdr.js";
|
|
8
|
+
/** Linear HDR float containers accepted on one side of `convert`. */
|
|
9
|
+
function isLinearHdrPath(path) {
|
|
10
|
+
return /\.(exr|hdr|pic)$/i.test(path);
|
|
11
|
+
}
|
|
7
12
|
export function createProgram() {
|
|
8
13
|
const program = new Command();
|
|
9
14
|
program
|
|
10
15
|
.name("hdr-toolbox")
|
|
11
16
|
.description("Compose, extract, and convert Android Ultra HDR JPEG images")
|
|
12
|
-
.version("1.0
|
|
17
|
+
.version("1.1.0");
|
|
13
18
|
program
|
|
14
19
|
.command("compose")
|
|
15
|
-
.description("Compose an SDR
|
|
16
|
-
.requiredOption("--sdr <path>", "SDR primary
|
|
17
|
-
.requiredOption("--gainmap <path>", "gain map
|
|
20
|
+
.description("Compose an SDR image, gain map image (avif/png/jpg/jpeg), and JSON/XMP config into Ultra HDR")
|
|
21
|
+
.requiredOption("--sdr <path>", "SDR primary image (avif, png, jpg, jpeg)")
|
|
22
|
+
.requiredOption("--gainmap <path>", "gain map image (avif, png, jpg, jpeg)")
|
|
18
23
|
.requiredOption("-c, --config <path>", "gain map config (.json or .xmp)")
|
|
19
24
|
.requiredOption("-o, --output <path>", "output Ultra HDR JPEG")
|
|
20
25
|
.action(async (options) => {
|
|
@@ -29,15 +34,17 @@ export function createProgram() {
|
|
|
29
34
|
.command("extract")
|
|
30
35
|
.description("Extract an Ultra HDR JPEG into SDR, gain map, and JSON/XMP config")
|
|
31
36
|
.requiredOption("-i, --input <path>", "input Ultra HDR JPEG")
|
|
32
|
-
.requiredOption("--sdr <path>", "output SDR
|
|
33
|
-
.requiredOption("--gainmap <path>", "output gain map
|
|
37
|
+
.requiredOption("--sdr <path>", "output SDR image (avif, png, jpg, jpeg)")
|
|
38
|
+
.requiredOption("--gainmap <path>", "output gain map image (avif, png, jpg, jpeg)")
|
|
34
39
|
.requiredOption("-c, --config <path>", "output config (.json or .xmp)")
|
|
40
|
+
.option("-f, --format <format>", "output image format (avif, png, jpg, jpeg); defaults to the output path extension, then jpeg")
|
|
35
41
|
.action(async (options) => {
|
|
36
42
|
await extractUltraHdr({
|
|
37
43
|
input: options.input,
|
|
38
44
|
sdr: options.sdr,
|
|
39
45
|
gainMap: options.gainmap,
|
|
40
46
|
config: options.config,
|
|
47
|
+
format: options.format,
|
|
41
48
|
});
|
|
42
49
|
});
|
|
43
50
|
program
|
|
@@ -66,6 +73,32 @@ export function createProgram() {
|
|
|
66
73
|
prefix: options.prefix,
|
|
67
74
|
});
|
|
68
75
|
});
|
|
76
|
+
program
|
|
77
|
+
.command("convert")
|
|
78
|
+
.description("Convert between a linear HDR file (.exr or .hdr) and an Ultra HDR JPEG (direction inferred from extensions)")
|
|
79
|
+
.requiredOption("-i, --input <path>", "input image (.exr, .hdr, or Ultra HDR .jpg/.jpeg)")
|
|
80
|
+
.requiredOption("-o, --output <path>", "output image (.exr, .hdr, or Ultra HDR .jpg/.jpeg)")
|
|
81
|
+
.option("--max-content-boost <ratio>", "HDR→Ultra HDR: linear HDR headroom to encode")
|
|
82
|
+
.option("--sdr-quality <quality>", "HDR→Ultra HDR: SDR base JPEG quality (1-100)")
|
|
83
|
+
.option("--gainmap-quality <quality>", "HDR→Ultra HDR: gain map JPEG quality (1-100)")
|
|
84
|
+
.action(async (options) => {
|
|
85
|
+
const inputIsLinearHdr = isLinearHdrPath(options.input);
|
|
86
|
+
const outputIsLinearHdr = isLinearHdrPath(options.output);
|
|
87
|
+
if (inputIsLinearHdr === outputIsLinearHdr)
|
|
88
|
+
throw new Error("convert needs exactly one linear HDR side: use a .exr/.hdr input with an Ultra HDR JPEG output, or vice versa.");
|
|
89
|
+
if (inputIsLinearHdr) {
|
|
90
|
+
await linearHdrToUltraHdr({
|
|
91
|
+
input: options.input,
|
|
92
|
+
output: options.output,
|
|
93
|
+
maxContentBoost: options.maxContentBoost === undefined ? undefined : Number(options.maxContentBoost),
|
|
94
|
+
sdrQuality: options.sdrQuality === undefined ? undefined : Number(options.sdrQuality),
|
|
95
|
+
gainMapQuality: options.gainmapQuality === undefined ? undefined : Number(options.gainmapQuality),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
await ultraHdrToLinearHdr({ input: options.input, output: options.output });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
69
102
|
return program;
|
|
70
103
|
}
|
|
71
104
|
function isMainModule() {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEjE,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,OAAO;SACJ,IAAI,CAAC,aAAa,CAAC;SACnB,WAAW,CAAC,6DAA6D,CAAC;SAC1E,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Linear HDR float container formats that `convert` reads and writes. */
|
|
2
|
+
export type LinearHdrFormat = "exr" | "hdr";
|
|
3
|
+
export interface UltraHdrToLinearHdrOptions {
|
|
4
|
+
input: string;
|
|
5
|
+
output: string;
|
|
6
|
+
/** Linear HDR output format; defaults to the output path extension. */
|
|
7
|
+
format?: LinearHdrFormat;
|
|
8
|
+
}
|
|
9
|
+
export interface LinearHdrToUltraHdrOptions {
|
|
10
|
+
input: string;
|
|
11
|
+
output: string;
|
|
12
|
+
/** Linear HDR input format; defaults to the input path extension. */
|
|
13
|
+
format?: LinearHdrFormat;
|
|
14
|
+
/** JPEG quality for the generated SDR base image (1-100, default 95). */
|
|
15
|
+
sdrQuality?: number;
|
|
16
|
+
/** JPEG quality for the generated gain map image (1-100, default 95). */
|
|
17
|
+
gainMapQuality?: number;
|
|
18
|
+
/** Linear ratio of HDR headroom to encode (max_content_boost, default auto). */
|
|
19
|
+
maxContentBoost?: number;
|
|
20
|
+
}
|
|
21
|
+
/** Back-compat alias for {@link UltraHdrToLinearHdrOptions}. */
|
|
22
|
+
export type UltraHdrToExrOptions = UltraHdrToLinearHdrOptions;
|
|
23
|
+
/** Back-compat alias for {@link LinearHdrToUltraHdrOptions}. */
|
|
24
|
+
export type ExrToUltraHdrOptions = LinearHdrToUltraHdrOptions;
|
|
25
|
+
/** Resolves a linear HDR format from an explicit option, then the path extension. */
|
|
26
|
+
export declare function resolveLinearHdrFormat(explicit: LinearHdrFormat | undefined, path: string): LinearHdrFormat;
|
|
27
|
+
/**
|
|
28
|
+
* Reconstructs a linear-light HDR image from an Ultra HDR JPEG and writes it as
|
|
29
|
+
* a linear float EXR or Radiance HDR file (chosen by the output extension).
|
|
30
|
+
*
|
|
31
|
+
* Applies the Adobe/Android gain map recovery per channel:
|
|
32
|
+
* logBoost = lerp(log2(min), log2(max), gain^(1/gamma))
|
|
33
|
+
* hdr = (sdr_linear + offsetSdr) * 2^logBoost - offsetHdr
|
|
34
|
+
* at full display headroom (weight = 1), so the output captures the complete HDR
|
|
35
|
+
* intent rather than a headroom-limited rendition.
|
|
36
|
+
*/
|
|
37
|
+
export declare function ultraHdrToLinearHdr(options: UltraHdrToLinearHdrOptions): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Builds an Ultra HDR JPEG from a linear float EXR or Radiance HDR file (chosen
|
|
40
|
+
* by the input extension). Tone maps the HDR data to an SDR base, derives a gain
|
|
41
|
+
* map as the per-pixel quotient between HDR and SDR, and composes the three into
|
|
42
|
+
* an Ultra HDR container.
|
|
43
|
+
*/
|
|
44
|
+
export declare function linearHdrToUltraHdr(options: LinearHdrToUltraHdrOptions): Promise<void>;
|
|
45
|
+
/** @deprecated Use {@link ultraHdrToLinearHdr}; retained for compatibility. */
|
|
46
|
+
export declare const ultraHdrToExr: typeof ultraHdrToLinearHdr;
|
|
47
|
+
/** @deprecated Use {@link linearHdrToUltraHdr}; retained for compatibility. */
|
|
48
|
+
export declare const exrToUltraHdr: typeof linearHdrToUltraHdr;
|
|
49
|
+
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAUA,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,KAAK,CAAC;AAE5C,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,gEAAgE;AAChE,MAAM,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAC9D,gEAAgE;AAChE,MAAM,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAE9D,qFAAqF;AACrF,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,eAAe,GAAG,SAAS,EACrC,IAAI,EAAE,MAAM,GACX,eAAe,CAQjB;AA6CD;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC5F;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAwE5F;AAED,+EAA+E;AAC/E,eAAO,MAAM,aAAa,4BAAsB,CAAC;AACjD,+EAA+E;AAC/E,eAAO,MAAM,aAAa,4BAAsB,CAAC"}
|
package/dist/convert.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, extname } from "node:path";
|
|
3
|
+
import sharp from "sharp";
|
|
4
|
+
import { readExr, writeExr } from "./exr.js";
|
|
5
|
+
import { readHdr, writeHdr } from "./hdr.js";
|
|
6
|
+
import { composeUltraHdrBuffers, extractUltraHdrBuffers } from "./ultrahdr.js";
|
|
7
|
+
import { normalizeGainMapConfig } from "./xmp.js";
|
|
8
|
+
/** Resolves a linear HDR format from an explicit option, then the path extension. */
|
|
9
|
+
export function resolveLinearHdrFormat(explicit, path) {
|
|
10
|
+
if (explicit)
|
|
11
|
+
return explicit;
|
|
12
|
+
const extension = extname(path).replace(/^\./, "").toLowerCase();
|
|
13
|
+
if (extension === "exr")
|
|
14
|
+
return "exr";
|
|
15
|
+
if (extension === "hdr" || extension === "pic")
|
|
16
|
+
return "hdr";
|
|
17
|
+
throw new Error(`Unable to infer a linear HDR format from "${path}". Use a .exr or .hdr extension.`);
|
|
18
|
+
}
|
|
19
|
+
function decodeLinearHdr(buffer, format) {
|
|
20
|
+
return format === "exr" ? readExr(buffer) : readHdr(buffer);
|
|
21
|
+
}
|
|
22
|
+
function encodeLinearHdr(image, format) {
|
|
23
|
+
return format === "exr" ? writeExr(image) : writeHdr(image);
|
|
24
|
+
}
|
|
25
|
+
/** Decode an 8-bit sRGB-encoded value (0-1) to linear light. */
|
|
26
|
+
function srgbToLinear(value) {
|
|
27
|
+
return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
|
|
28
|
+
}
|
|
29
|
+
/** Encode linear light (0-1) back to an 8-bit sRGB value (0-1). */
|
|
30
|
+
function linearToSrgb(value) {
|
|
31
|
+
const clamped = value < 0 ? 0 : value > 1 ? 1 : value;
|
|
32
|
+
return clamped <= 0.0031308 ? clamped * 12.92 : 1.055 * clamped ** (1 / 2.4) - 0.055;
|
|
33
|
+
}
|
|
34
|
+
/** Rec. 709 relative luminance of a linear RGB triple. */
|
|
35
|
+
function luminance(r, g, b) {
|
|
36
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Reinhard tone map: `x / (1 + x)`. Simple and reversible, it maps any linear
|
|
40
|
+
* luminance into [0, 1) without hard clipping. It compresses bright highlights
|
|
41
|
+
* aggressively, so the SDR base favours a well-exposed midrange; the full HDR
|
|
42
|
+
* detail is preserved in the gain map and recovered on HDR displays.
|
|
43
|
+
*/
|
|
44
|
+
function reinhard(value) {
|
|
45
|
+
return value / (1 + value);
|
|
46
|
+
}
|
|
47
|
+
async function decodeRgb(jpeg) {
|
|
48
|
+
const { data, info } = await sharp(jpeg)
|
|
49
|
+
.toColorspace("srgb")
|
|
50
|
+
.removeAlpha()
|
|
51
|
+
.raw()
|
|
52
|
+
.toBuffer({ resolveWithObject: true });
|
|
53
|
+
return { data, width: info.width, height: info.height };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Reconstructs a linear-light HDR image from an Ultra HDR JPEG and writes it as
|
|
57
|
+
* a linear float EXR or Radiance HDR file (chosen by the output extension).
|
|
58
|
+
*
|
|
59
|
+
* Applies the Adobe/Android gain map recovery per channel:
|
|
60
|
+
* logBoost = lerp(log2(min), log2(max), gain^(1/gamma))
|
|
61
|
+
* hdr = (sdr_linear + offsetSdr) * 2^logBoost - offsetHdr
|
|
62
|
+
* at full display headroom (weight = 1), so the output captures the complete HDR
|
|
63
|
+
* intent rather than a headroom-limited rendition.
|
|
64
|
+
*/
|
|
65
|
+
export async function ultraHdrToLinearHdr(options) {
|
|
66
|
+
const format = resolveLinearHdrFormat(options.format, options.output);
|
|
67
|
+
const extracted = extractUltraHdrBuffers(await readFile(options.input));
|
|
68
|
+
const config = normalizeGainMapConfig(extracted.config);
|
|
69
|
+
const sdr = await decodeRgb(extracted.sdr);
|
|
70
|
+
const gain = await decodeRgb(extracted.gainMap);
|
|
71
|
+
const width = sdr.width;
|
|
72
|
+
const height = sdr.height;
|
|
73
|
+
const output = new Float32Array(width * height * 3);
|
|
74
|
+
const logMin = Math.log2(config.minContentBoost);
|
|
75
|
+
const logMax = Math.log2(config.maxContentBoost);
|
|
76
|
+
const inverseGamma = 1 / config.gamma;
|
|
77
|
+
// The gain map is often downsampled; map SDR coordinates onto it by ratio.
|
|
78
|
+
const gainScaleX = gain.width / width;
|
|
79
|
+
const gainScaleY = gain.height / height;
|
|
80
|
+
for (let y = 0; y < height; y++) {
|
|
81
|
+
const gainY = Math.min(gain.height - 1, Math.floor(y * gainScaleY));
|
|
82
|
+
for (let x = 0; x < width; x++) {
|
|
83
|
+
const gainX = Math.min(gain.width - 1, Math.floor(x * gainScaleX));
|
|
84
|
+
const sdrIndex = (y * width + x) * 3;
|
|
85
|
+
const gainIndex = (gainY * gain.width + gainX) * 3;
|
|
86
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
87
|
+
const sdrLinear = srgbToLinear(sdr.data[sdrIndex + channel] / 255);
|
|
88
|
+
const gainValue = gain.data[gainIndex + channel] / 255;
|
|
89
|
+
const logRecovery = gainValue ** inverseGamma;
|
|
90
|
+
const logBoost = logMin + (logMax - logMin) * logRecovery;
|
|
91
|
+
const hdr = (sdrLinear + config.offsetSdr) * 2 ** logBoost - config.offsetHdr;
|
|
92
|
+
output[sdrIndex + channel] = hdr;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
await mkdir(dirname(options.output), { recursive: true });
|
|
97
|
+
await writeFile(options.output, encodeLinearHdr({ width, height, data: output }, format));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Builds an Ultra HDR JPEG from a linear float EXR or Radiance HDR file (chosen
|
|
101
|
+
* by the input extension). Tone maps the HDR data to an SDR base, derives a gain
|
|
102
|
+
* map as the per-pixel quotient between HDR and SDR, and composes the three into
|
|
103
|
+
* an Ultra HDR container.
|
|
104
|
+
*/
|
|
105
|
+
export async function linearHdrToUltraHdr(options) {
|
|
106
|
+
const format = resolveLinearHdrFormat(options.format, options.input);
|
|
107
|
+
const { width, height, data } = decodeLinearHdr(await readFile(options.input), format);
|
|
108
|
+
// Determine the HDR headroom from the brightest linear value so the gain map
|
|
109
|
+
// range covers the content without clipping.
|
|
110
|
+
let peak = 1;
|
|
111
|
+
for (let index = 0; index < data.length; index++) {
|
|
112
|
+
if (data[index] > peak)
|
|
113
|
+
peak = data[index];
|
|
114
|
+
}
|
|
115
|
+
const maxContentBoost = Math.max(1.0001, options.maxContentBoost ?? Math.min(peak, 2 ** 14));
|
|
116
|
+
const logMax = Math.log2(maxContentBoost);
|
|
117
|
+
const sdrPixels = Buffer.alloc(width * height * 3);
|
|
118
|
+
const gainPixels = Buffer.alloc(width * height * 3);
|
|
119
|
+
const offset = 0.015625;
|
|
120
|
+
for (let pixel = 0; pixel < width * height; pixel++) {
|
|
121
|
+
const base = pixel * 3;
|
|
122
|
+
const r = Math.max(0, data[base]);
|
|
123
|
+
const g = Math.max(0, data[base + 1]);
|
|
124
|
+
const b = Math.max(0, data[base + 2]);
|
|
125
|
+
// Drive the Reinhard compression by luminance and scale the chroma by the
|
|
126
|
+
// same factor, so hue and saturation survive tone mapping (a per-channel
|
|
127
|
+
// curve would desaturate bright, saturated highlights).
|
|
128
|
+
const y = luminance(r, g, b);
|
|
129
|
+
const ySdr = reinhard(y);
|
|
130
|
+
const scale = y > 1e-6 ? ySdr / y : 0;
|
|
131
|
+
for (let channel = 0; channel < 3; channel++) {
|
|
132
|
+
const hdr = Math.max(0, data[base + channel]);
|
|
133
|
+
// The quantised 8-bit code is what actually ships, so derive the gain map
|
|
134
|
+
// from the exact SDR light it decodes to, keeping reconstruction consistent.
|
|
135
|
+
const code = Math.round(linearToSrgb(Math.min(1, hdr * scale)) * 255);
|
|
136
|
+
sdrPixels[base + channel] = code;
|
|
137
|
+
const sdrLinear = srgbToLinear(code / 255);
|
|
138
|
+
// Gain is the ratio of HDR to SDR light, encoded in log2 space and
|
|
139
|
+
// normalised to [0,1] against the chosen max boost.
|
|
140
|
+
const ratio = (hdr + offset) / (sdrLinear + offset);
|
|
141
|
+
const logBoost = Math.log2(Math.max(1, ratio));
|
|
142
|
+
const normalized = logMax > 0 ? Math.min(1, logBoost / logMax) : 0;
|
|
143
|
+
gainPixels[base + channel] = Math.round(normalized * 255);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const sdrQuality = options.sdrQuality ?? 95;
|
|
147
|
+
const gainMapQuality = options.gainMapQuality ?? 95;
|
|
148
|
+
const [sdrJpeg, gainMapJpeg] = await Promise.all([
|
|
149
|
+
sharp(sdrPixels, { raw: { width, height, channels: 3 } })
|
|
150
|
+
.jpeg({ quality: sdrQuality })
|
|
151
|
+
.toBuffer(),
|
|
152
|
+
sharp(gainPixels, { raw: { width, height, channels: 3 } })
|
|
153
|
+
.jpeg({ quality: gainMapQuality })
|
|
154
|
+
.toBuffer(),
|
|
155
|
+
]);
|
|
156
|
+
const config = {
|
|
157
|
+
maxContentBoost,
|
|
158
|
+
minContentBoost: 1,
|
|
159
|
+
gamma: 1,
|
|
160
|
+
offsetSdr: offset,
|
|
161
|
+
offsetHdr: offset,
|
|
162
|
+
hdrCapacityMin: 1,
|
|
163
|
+
hdrCapacityMax: maxContentBoost,
|
|
164
|
+
useBaseColorSpace: true,
|
|
165
|
+
};
|
|
166
|
+
const container = await composeUltraHdrBuffers(sdrJpeg, gainMapJpeg, config);
|
|
167
|
+
await mkdir(dirname(options.output), { recursive: true });
|
|
168
|
+
await writeFile(options.output, container);
|
|
169
|
+
}
|
|
170
|
+
/** @deprecated Use {@link ultraHdrToLinearHdr}; retained for compatibility. */
|
|
171
|
+
export const ultraHdrToExr = ultraHdrToLinearHdr;
|
|
172
|
+
/** @deprecated Use {@link linearHdrToUltraHdr}; retained for compatibility. */
|
|
173
|
+
export const exrToUltraHdr = linearHdrToUltraHdr;
|
|
174
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"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"}
|
package/dist/exr.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal OpenEXR reader/writer for linear scanline RGB(A) images.
|
|
3
|
+
*
|
|
4
|
+
* This is intentionally small: it is only meant to move linear floating point
|
|
5
|
+
* HDR pixels in and out of the UltraHDR converter, not to be a general EXR
|
|
6
|
+
* implementation. On read it accepts single-part scanline files with HALF or
|
|
7
|
+
* FLOAT channels and NO_COMPRESSION, ZIPS or ZIP compression. On write it emits
|
|
8
|
+
* a single-part scanline FLOAT RGB file with NO_COMPRESSION, which every EXR
|
|
9
|
+
* reader understands.
|
|
10
|
+
*/
|
|
11
|
+
/** An in-memory linear HDR image: interleaved RGB, 3 floats per pixel, top row first. */
|
|
12
|
+
export interface LinearHdrImage {
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
data: Float32Array;
|
|
16
|
+
}
|
|
17
|
+
/** @deprecated Use {@link LinearHdrImage}; kept as an alias for compatibility. */
|
|
18
|
+
export type ExrImage = LinearHdrImage;
|
|
19
|
+
/** Reads a linear RGB EXR into interleaved float RGB, dropping any alpha. */
|
|
20
|
+
export declare function readExr(buffer: Buffer): LinearHdrImage;
|
|
21
|
+
/**
|
|
22
|
+
* Writes interleaved linear float RGB as an uncompressed single-part scanline
|
|
23
|
+
* EXR. Channels are emitted alphabetically (B, G, R) as the format requires.
|
|
24
|
+
*/
|
|
25
|
+
export declare function writeExr(image: LinearHdrImage): Buffer;
|
|
26
|
+
//# sourceMappingURL=exr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exr.d.ts","sourceRoot":"","sources":["../src/exr.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,yFAAyF;AACzF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,kFAAkF;AAClF,MAAM,MAAM,QAAQ,GAAG,cAAc,CAAC;AA0ItC,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CA0FtD;AASD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAsFtD"}
|