| 1 | import { describe, expect, it } from 'vitest' |
| 2 | import { PNG } from 'pngjs' |
| 3 | import { stitchPngBuffersVertical } from '../../../../src/main/io/thumbnails/png-stitch' |
| 4 | |
| 5 | type Rgba = [number, number, number, number] |
| 6 | |
| 7 | type DecodedPng = { width: number; height: number; data: Buffer } |
| 8 | |
| 9 | function makeSolidPng(width: number, height: number, rgba: Rgba): Buffer { |
| 10 | const png = new PNG({ width, height }) |
| 11 | for (let i = 0; i < png.data.length; i += 4) { |
| 12 | png.data[i] = rgba[0] |
| 13 | png.data[i + 1] = rgba[1] |
| 14 | png.data[i + 2] = rgba[2] |
| 15 | png.data[i + 3] = rgba[3] |
| 16 | } |
| 17 | return PNG.sync.write(png) |
| 18 | } |
| 19 | |
| 20 | function readPixel(img: DecodedPng, x: number, y: number): Rgba { |
| 21 | const i = (img.width * y + x) * 4 |
| 22 | return [img.data[i], img.data[i + 1], img.data[i + 2], img.data[i + 3]] |
| 23 | } |
| 24 | |
| 25 | describe('stitchPngBuffersVertical', () => { |
| 26 | it('纵向无缝拼接多张同宽 PNG,尺寸与像素按页顺序正确', () => { |
| 27 | const red = makeSolidPng(4, 2, [255, 0, 0, 255]) |
| 28 | const blue = makeSolidPng(4, 3, [0, 0, 255, 255]) |
| 29 | |
| 30 | const merged = stitchPngBuffersVertical([red, blue]) |
| 31 | const img = PNG.sync.read(merged) as DecodedPng |
| 32 | |
| 33 | expect(img.width).toBe(4) |
| 34 | expect(img.height).toBe(5) // 2 + 3 |
| 35 | // 第一段(y=0..1)红,第二段(y=2..4)蓝,边界无缝 |
| 36 | expect(readPixel(img, 0, 0)).toEqual([255, 0, 0, 255]) |
| 37 | expect(readPixel(img, 0, 1)).toEqual([255, 0, 0, 255]) |
| 38 | expect(readPixel(img, 0, 2)).toEqual([0, 0, 255, 255]) |
| 39 | expect(readPixel(img, 0, 4)).toEqual([0, 0, 255, 255]) |
| 40 | }) |
| 41 | |
| 42 | it('单张 PNG 原样返回等尺寸结果', () => { |
| 43 | const green = makeSolidPng(3, 3, [0, 255, 0, 255]) |
| 44 | const merged = stitchPngBuffersVertical([green]) |
| 45 | const img = PNG.sync.read(merged) as DecodedPng |
| 46 | |
| 47 | expect(img.width).toBe(3) |
| 48 | expect(img.height).toBe(3) |
| 49 | expect(readPixel(img, 1, 1)).toEqual([0, 255, 0, 255]) |
| 50 | }) |
| 51 | |
| 52 | it('宽度不一致时抛错', () => { |
| 53 | const a = makeSolidPng(4, 2, [0, 0, 0, 255]) |
| 54 | const b = makeSolidPng(3, 2, [0, 0, 0, 255]) |
| 55 | expect(() => stitchPngBuffersVertical([a, b])).toThrow() |
| 56 | }) |
| 57 | |
| 58 | it('空数组抛错', () => { |
| 59 | expect(() => stitchPngBuffersVertical([])).toThrow() |
| 60 | }) |
| 61 | }) |
| 62 |