perf(hdr): reduce layered composite overhead (#538)

This commit is contained in:
Vance Ingalls
2026-04-28 15:30:35 -07:00
committed by GitHub
parent fc3c601870
commit ad44c3133a
3 changed files with 362 additions and 62 deletions
@@ -775,6 +775,25 @@ describe("blitRgb48leRegion", () => {
expect(canvas.readUInt16LE(0)).toBe(20000);
});
it("blends opacity over existing destination pixels", () => {
const canvas = makeHdrFrame(2, 1, 10000, 20000, 30000);
const source = makeHdrFrame(2, 1, 50000, 10000, 60000);
blitRgb48leRegion(canvas, source, 0, 0, 2, 1, 2, 1, 0.25);
expect(canvas.readUInt16LE(0)).toBe(20000);
expect(canvas.readUInt16LE(2)).toBe(17500);
expect(canvas.readUInt16LE(4)).toBe(37500);
expect(canvas.readUInt16LE(6)).toBe(20000);
});
it("skips exact-zero opacity without mutating the destination", () => {
const canvas = makeHdrFrame(1, 1, 10000, 20000, 30000);
const source = makeHdrFrame(1, 1, 50000, 50000, 50000);
blitRgb48leRegion(canvas, source, 0, 0, 1, 1, 1, 1, 0);
expect(canvas.readUInt16LE(0)).toBe(10000);
expect(canvas.readUInt16LE(2)).toBe(20000);
expect(canvas.readUInt16LE(4)).toBe(30000);
});
it("no-op for zero-size region", () => {
const canvas = Buffer.alloc(4 * 4 * 6);
const source = makeHdrFrame(2, 2, 10000, 20000, 30000);
+29
View File
@@ -423,6 +423,7 @@ export function blitRgb48leRegion(
if (sw <= 0 || sh <= 0) return;
const op = opacity ?? 1.0;
if (op <= 0) return;
const x0 = Math.max(0, dx);
const y0 = Math.max(0, dy);
@@ -442,6 +443,33 @@ export function blitRgb48leRegion(
const dstRowOff = ((y0 + y) * canvasWidth + x0) * 6;
source.copy(canvas, dstRowOff, srcRowOff, srcRowOff + clippedW * 6);
}
} else if (!hasMask) {
const invOp = 1 - op;
for (let y = 0; y < y1 - y0; y++) {
let srcOff = ((srcOffsetY + y) * sw + srcOffsetX) * 6;
let dstOff = ((y0 + y) * canvasWidth + x0) * 6;
for (let x = 0; x < clippedW; x++) {
const sr = source[srcOff]! | (source[srcOff + 1]! << 8);
const sg = source[srcOff + 2]! | (source[srcOff + 3]! << 8);
const sb = source[srcOff + 4]! | (source[srcOff + 5]! << 8);
const dr = canvas[dstOff]! | (canvas[dstOff + 1]! << 8);
const dg = canvas[dstOff + 2]! | (canvas[dstOff + 3]! << 8);
const db = canvas[dstOff + 4]! | (canvas[dstOff + 5]! << 8);
const r = (sr * op + dr * invOp + 0.5) | 0;
const g = (sg * op + dg * invOp + 0.5) | 0;
const b = (sb * op + db * invOp + 0.5) | 0;
canvas[dstOff] = r & 0xff;
canvas[dstOff + 1] = r >>> 8;
canvas[dstOff + 2] = g & 0xff;
canvas[dstOff + 3] = g >>> 8;
canvas[dstOff + 4] = b & 0xff;
canvas[dstOff + 5] = b >>> 8;
srcOff += 6;
dstOff += 6;
}
}
} else {
for (let y = 0; y < y1 - y0; y++) {
for (let x = 0; x < clippedW; x++) {
@@ -528,6 +556,7 @@ export function blitRgb48leAffine(
const invTy = -(invB * tx + invD * ty);
const op = opacity ?? 1.0;
if (op <= 0) return;
const hasMask = borderRadius !== undefined;