* Build a minimal RGBA PNG for testing. * pixels: flat RGBA array (row-major, 8-bit per channel)
(width: number, height: number, pixels: number[])
| 56 | * pixels: flat RGBA array (row-major, 8-bit per channel) |
| 57 | */ |
| 58 | function makePng(width: number, height: number, pixels: number[]): Buffer { |
| 59 | // IHDR |
| 60 | const ihdr = Buffer.allocUnsafe(13); |
| 61 | ihdr.writeUInt32BE(width, 0); |
| 62 | ihdr.writeUInt32BE(height, 4); |
| 63 | ihdr[8] = 8; // bit depth |
| 64 | ihdr[9] = 6; // color type RGBA |
| 65 | ihdr[10] = 0; // compression |
| 66 | ihdr[11] = 0; // filter method |
| 67 | ihdr[12] = 0; // interlace none |
| 68 | |
| 69 | // Raw scanlines with filter byte 0 (None) |
| 70 | const scanlines: number[] = []; |
| 71 | for (let y = 0; y < height; y++) { |
| 72 | scanlines.push(0); // filter type None |
| 73 | for (let x = 0; x < width; x++) { |
| 74 | const i = (y * width + x) * 4; |
| 75 | scanlines.push(pixels[i] ?? 0, pixels[i + 1] ?? 0, pixels[i + 2] ?? 0, pixels[i + 3] ?? 0); |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | const idatData = deflateSync(Buffer.from(scanlines)); |
| 80 | |
| 81 | return Buffer.concat([ |
| 82 | PNG_SIG, |
| 83 | makeChunk("IHDR", ihdr), |
| 84 | makeChunk("IDAT", idatData), |
| 85 | makeChunk("IEND", Buffer.alloc(0)), |
| 86 | ]); |
| 87 | } |
| 88 | |
| 89 | // ── decodePng tests ────────────────────────────────────────────────────────── |
| 90 |
no test coverage detected