mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 12:54:29 +00:00
fix: render shader transitions for SDR compositions (#640)
* feat: cache shader transition preview frames * fix: move shader transition loading to player * fix: render shader transitions for sdr compositions
This commit is contained in:
@@ -511,6 +511,16 @@ describe("blitRgba8OverRgb48le", () => {
|
||||
expect(canvas.readUInt16LE(4)).toBe(0);
|
||||
});
|
||||
|
||||
it("fully opaque DOM with srgb transfer expands 8-bit channels to 16-bit SDR", () => {
|
||||
const canvas = makeHdrFrame(1, 1, 10000, 20000, 30000);
|
||||
const dom = makeDomRgba(1, 1, 255, 128, 1, 255);
|
||||
blitRgba8OverRgb48le(dom, canvas, 1, 1, "srgb");
|
||||
|
||||
expect(canvas.readUInt16LE(0)).toBe(65535);
|
||||
expect(canvas.readUInt16LE(2)).toBe(128 * 257);
|
||||
expect(canvas.readUInt16LE(4)).toBe(257);
|
||||
});
|
||||
|
||||
it("sRGB→HLG: black stays black, white stays white", () => {
|
||||
const canvasBlack = makeHdrFrame(1, 1, 0, 0, 0);
|
||||
const domBlack = makeDomRgba(1, 1, 0, 0, 0, 255);
|
||||
|
||||
@@ -249,7 +249,7 @@ export function decodePngToRgb48le(buf: Buffer): { width: number; height: number
|
||||
* bt2020). For neutral/near-neutral content (text, UI) the gamut difference
|
||||
* is negligible.
|
||||
*/
|
||||
function buildSrgbToHdrLut(transfer: "hlg" | "pq"): Uint16Array {
|
||||
function buildSrgbToSignalLut(transfer: "hlg" | "pq" | "srgb"): Uint16Array {
|
||||
const lut = new Uint16Array(256);
|
||||
|
||||
// HLG OETF constants (Rec. 2100)
|
||||
@@ -267,6 +267,11 @@ function buildSrgbToHdrLut(transfer: "hlg" | "pq"): Uint16Array {
|
||||
const sdrNits = 203.0;
|
||||
|
||||
for (let i = 0; i < 256; i++) {
|
||||
if (transfer === "srgb") {
|
||||
lut[i] = i * 257;
|
||||
continue;
|
||||
}
|
||||
|
||||
// sRGB EOTF: signal → linear (range 0–1, relative to SDR white)
|
||||
const v = i / 255;
|
||||
const linear = v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
||||
@@ -288,12 +293,15 @@ function buildSrgbToHdrLut(transfer: "hlg" | "pq"): Uint16Array {
|
||||
return lut;
|
||||
}
|
||||
|
||||
const SRGB_TO_HLG = buildSrgbToHdrLut("hlg");
|
||||
const SRGB_TO_PQ = buildSrgbToHdrLut("pq");
|
||||
const SRGB_TO_SRGB_16 = buildSrgbToSignalLut("srgb");
|
||||
const SRGB_TO_HLG = buildSrgbToSignalLut("hlg");
|
||||
const SRGB_TO_PQ = buildSrgbToSignalLut("pq");
|
||||
|
||||
/** Select the correct sRGB→HDR LUT for the given transfer function. */
|
||||
function getSrgbToHdrLut(transfer: "hlg" | "pq"): Uint16Array {
|
||||
return transfer === "pq" ? SRGB_TO_PQ : SRGB_TO_HLG;
|
||||
function getSrgbToSignalLut(transfer: "hlg" | "pq" | "srgb"): Uint16Array {
|
||||
if (transfer === "pq") return SRGB_TO_PQ;
|
||||
if (transfer === "hlg") return SRGB_TO_HLG;
|
||||
return SRGB_TO_SRGB_16;
|
||||
}
|
||||
|
||||
// ── Alpha compositing ─────────────────────────────────────────────────────────
|
||||
@@ -317,10 +325,10 @@ export function blitRgba8OverRgb48le(
|
||||
canvas: Buffer,
|
||||
width: number,
|
||||
height: number,
|
||||
transfer: "hlg" | "pq" = "hlg",
|
||||
transfer: "hlg" | "pq" | "srgb" = "hlg",
|
||||
): void {
|
||||
const pixelCount = width * height;
|
||||
const lut = getSrgbToHdrLut(transfer);
|
||||
const lut = getSrgbToSignalLut(transfer);
|
||||
|
||||
for (let i = 0; i < pixelCount; i++) {
|
||||
const da = domRgba[i * 4 + 3] ?? 0;
|
||||
|
||||
Reference in New Issue
Block a user