96 lines
1.9 KiB
TypeScript
96 lines
1.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { samplePixels } from "../../src/palette/sample";
|
|
|
|
const pixels = (
|
|
width: number,
|
|
colours: readonly (readonly [number, number, number, number])[],
|
|
) => ({
|
|
width,
|
|
height: colours.length / width,
|
|
data: new Uint8ClampedArray(colours.flat()),
|
|
});
|
|
|
|
describe("pixel sampling", () => {
|
|
it("returns the exact pixel for a zero-radius sample", () => {
|
|
const result = samplePixels(
|
|
pixels(2, [
|
|
[12, 34, 56, 255],
|
|
[200, 100, 50, 128],
|
|
]),
|
|
1,
|
|
0,
|
|
0,
|
|
"average",
|
|
);
|
|
|
|
expect(result).toMatchObject({
|
|
r: 200,
|
|
g: 100,
|
|
b: 50,
|
|
a: 128,
|
|
hex: "#C8643280",
|
|
pixelCount: 1,
|
|
});
|
|
});
|
|
|
|
it("uses a circular neighbourhood and alpha-weighted RGB average", () => {
|
|
const data = pixels(3, [
|
|
[0, 0, 0, 0],
|
|
[255, 0, 0, 255],
|
|
[0, 0, 0, 0],
|
|
[0, 255, 0, 255],
|
|
[0, 0, 255, 0],
|
|
[0, 0, 0, 0],
|
|
[0, 0, 0, 0],
|
|
[255, 255, 255, 255],
|
|
[0, 0, 0, 0],
|
|
]);
|
|
const result = samplePixels(data, 1, 1, 1, "average");
|
|
|
|
expect(result).toMatchObject({
|
|
r: 170,
|
|
g: 170,
|
|
b: 85,
|
|
a: 153,
|
|
pixelCount: 5,
|
|
});
|
|
});
|
|
|
|
it("calculates channel medians from visible samples", () => {
|
|
const result = samplePixels(
|
|
pixels(3, [
|
|
[10, 90, 200, 255],
|
|
[200, 50, 10, 128],
|
|
[100, 10, 90, 0],
|
|
]),
|
|
1,
|
|
0,
|
|
1,
|
|
"median",
|
|
);
|
|
|
|
expect(result).toMatchObject({
|
|
r: 105,
|
|
g: 70,
|
|
b: 105,
|
|
a: 128,
|
|
pixelCount: 3,
|
|
});
|
|
});
|
|
|
|
it("rejects invalid coordinates and truncated buffers", () => {
|
|
expect(
|
|
samplePixels(pixels(1, [[1, 2, 3, 4]]), 1, 0, 0, "average"),
|
|
).toBeNull();
|
|
expect(
|
|
samplePixels(
|
|
{ width: 2, height: 2, data: new Uint8ClampedArray(4) },
|
|
0,
|
|
0,
|
|
0,
|
|
"average",
|
|
),
|
|
).toBeNull();
|
|
});
|
|
});
|