| 1 | import { PNG } from 'pngjs' |
| 2 | |
| 3 | /** |
| 4 | * 把多张宽度相同的 PNG 纵向无缝拼接成一张长图,返回新 PNG 的 Buffer。 |
| 5 | * |
| 6 | * PNG 内部像素经过「逐行过滤 + zlib 压缩」,不能直接首尾相接;这里逐张解码出 |
| 7 | * 原始 RGBA 像素,按页顺序纵向块拷贝到一块总画布,再重新编码为单张 PNG。 |
| 8 | * 同一个 session 的所有页面共用 slideSize,宽度恒定,因此只累加高度。 |
| 9 | */ |
| 10 | export function stitchPngBuffersVertical(buffers: Buffer[]): Buffer { |
| 11 | if (buffers.length === 0) { |
| 12 | throw new Error('没有可拼接的页面') |
| 13 | } |
| 14 | |
| 15 | const images = buffers.map((buf) => PNG.sync.read(buf)) |
| 16 | const width = images[0].width |
| 17 | for (const img of images) { |
| 18 | if (img.width !== width) { |
| 19 | throw new Error('页面宽度不一致,无法拼接长图') |
| 20 | } |
| 21 | } |
| 22 | |
| 23 | const totalHeight = images.reduce((sum, img) => sum + img.height, 0) |
| 24 | const merged = new PNG({ width, height: totalHeight }) |
| 25 | |
| 26 | let yOffset = 0 |
| 27 | for (const img of images) { |
| 28 | PNG.bitblt(img, merged, 0, 0, img.width, img.height, 0, yOffset) |
| 29 | yOffset += img.height |
| 30 | } |
| 31 | |
| 32 | return PNG.sync.write(merged) |
| 33 | } |
| 34 |