* Build a 16-bit RGB PNG (colorType 2, bitDepth 16). PNG stores each 16-bit * sample as two big-endian bytes; the decoder must swap them to LE. * * @param pixels Flat array of [r16, g16, b16, r16, g16, b16, ...] values * (one entry per channel sample, 0–65535).
(width: number, height: number, pixels: number[])
| 360 | * (one entry per channel sample, 0–65535). |
| 361 | */ |
| 362 | function makePng16(width: number, height: number, pixels: number[]): Buffer { |
| 363 | const ihdr = Buffer.allocUnsafe(13); |
| 364 | ihdr.writeUInt32BE(width, 0); |
| 365 | ihdr.writeUInt32BE(height, 4); |
| 366 | ihdr[8] = 16; // bit depth |
| 367 | ihdr[9] = 2; // color type RGB |
| 368 | ihdr[10] = 0; |
| 369 | ihdr[11] = 0; |
| 370 | ihdr[12] = 0; |
| 371 | |
| 372 | const stride = width * 6; // 3 channels × 2 bytes |
| 373 | const filtered: number[] = []; |
| 374 | for (let y = 0; y < height; y++) { |
| 375 | filtered.push(0); // filter type None |
| 376 | for (let x = 0; x < width; x++) { |
| 377 | const baseSample = (y * width + x) * 3; |
| 378 | for (let ch = 0; ch < 3; ch++) { |
| 379 | const v = pixels[baseSample + ch] ?? 0; |
| 380 | filtered.push((v >> 8) & 0xff); // high byte (BE on wire) |
| 381 | filtered.push(v & 0xff); // low byte |
| 382 | } |
| 383 | } |
| 384 | void stride; |
| 385 | } |
| 386 | |
| 387 | const idat = deflateSync(Buffer.from(filtered)); |
| 388 | return Buffer.concat([ |
| 389 | PNG_SIG, |
| 390 | makeChunk("IHDR", ihdr), |
| 391 | makeChunk("IDAT", idat), |
| 392 | makeChunk("IEND", Buffer.alloc(0)), |
| 393 | ]); |
| 394 | } |
| 395 | |
| 396 | describe("decodePngToRgb48le", () => { |
| 397 | it("swaps PNG big-endian samples to little-endian rgb48le", () => { |
no test coverage detected