feat(photos): добавить пресеты кривой и починить переключение фото
- PCHIP для предпросмотра и серверного рендера - пресеты всех каналов в профиле, импорт и экспорт - мерж настроек auth без потери разделов - сохранение вкладки и правок текущего фото при переключении
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
applyColorToPixels,
|
||||
buildCurveLUT,
|
||||
curveSvgPath,
|
||||
effectiveCurvePoints,
|
||||
emptyColor,
|
||||
emptyEditParams,
|
||||
isEmptyColor,
|
||||
@@ -182,3 +185,73 @@ describe('цветовые параметры', () => {
|
||||
expect(b).toBeCloseTo(g, 5);
|
||||
});
|
||||
});
|
||||
|
||||
describe('кривая', () => {
|
||||
const medium = [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 0.25, y: 0.2 },
|
||||
{ x: 0.5, y: 0.5 },
|
||||
{ x: 0.75, y: 0.8 },
|
||||
{ x: 1, y: 1 }
|
||||
];
|
||||
const strong = [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 0.2, y: 0.12 },
|
||||
{ x: 0.5, y: 0.5 },
|
||||
{ x: 0.8, y: 0.88 },
|
||||
{ x: 1, y: 1 }
|
||||
];
|
||||
const inner = [
|
||||
{ x: 0.1, y: 0.05 },
|
||||
{ x: 0.4, y: 0.3 },
|
||||
{ x: 0.9, y: 0.95 }
|
||||
];
|
||||
const samples = [0, 32, 64, 128, 192, 224, 255];
|
||||
|
||||
it('показывает крайние точки у пустого канала', () => {
|
||||
expect(effectiveCurvePoints(undefined)).toEqual([
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 1, y: 1 }
|
||||
]);
|
||||
expect(effectiveCurvePoints([{ x: 0.5, y: 0.4 }])).toEqual([
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 1, y: 1 }
|
||||
]);
|
||||
expect(effectiveCurvePoints(inner)).toEqual(inner);
|
||||
});
|
||||
|
||||
it('совпадает с серверной PCHIP-кривой', () => {
|
||||
const values = (points: { x: number; y: number }[]) => {
|
||||
const lut = buildCurveLUT(points);
|
||||
return samples.map((i) => lut[i]);
|
||||
};
|
||||
expect(values([{ x: 0, y: 0 }, { x: 1, y: 1 }])).toEqual([
|
||||
0, 32, 64, 128, 192, 224, 255
|
||||
]);
|
||||
expect(values(medium)).toEqual([0, 23, 51, 128, 205, 233, 255]);
|
||||
expect(values(strong)).toEqual([0, 17, 43, 128, 213, 239, 255]);
|
||||
expect(values(inner)).toEqual([13, 17, 42, 104, 186, 234, 242]);
|
||||
});
|
||||
|
||||
it('остаётся монотонной между точками', () => {
|
||||
for (const points of [medium, strong]) {
|
||||
const lut = buildCurveLUT(points);
|
||||
for (let i = 1; i < lut.length; i++) {
|
||||
expect(lut[i]).toBeGreaterThanOrEqual(lut[i - 1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('делает плоские полки вне крайних точек', () => {
|
||||
const lut = buildCurveLUT(inner);
|
||||
for (let i = 0; i <= Math.floor(0.1 * 255); i++) expect(lut[i]).toBe(13);
|
||||
for (let i = Math.ceil(0.9 * 255); i < 256; i++) expect(lut[i]).toBe(242);
|
||||
});
|
||||
|
||||
it('рисует плавный SVG-путь с полками', () => {
|
||||
const path = curveSvgPath(inner);
|
||||
expect(path.startsWith('M0.0000,95.0000 L10.0000,95.0000')).toBe(true);
|
||||
expect(path).toContain('C');
|
||||
expect(path.endsWith('L100.0000,5.0000')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user