docs(openspec): изменение photo-color-editing
Предложение, дельта-спека photos, дизайн и задачи для инструмента «Цвет».
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# Design
|
||||
|
||||
## Context
|
||||
|
||||
Неразрушающее редактирование фото уже реализовано: параметры правок хранятся в
|
||||
`photo.edit_params` (`map[string]any` JSON-блоб), сервер рендерит отредактированную
|
||||
копию как отдельные объекты ролей `edit`, `edit_thumb`, `edit_medium`,
|
||||
`edit_preview` рядом с исходными, оригинал не меняется. На сегодня поддерживается
|
||||
только блок «Свет» (`LightParams` в `backend/internal/photos/edit.go`,
|
||||
зеркало на клиенте `frontend/src/lib/edit.ts`, живой превью через
|
||||
`frontend/wasm/light/` → `static/light.wasm` с тестом паритета
|
||||
`wasmMatchesReference`). Хранение в JSON-блобе обратноли не требует миграции:
|
||||
старые фото без ключа `color` рендерятся без цветовых правок.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Добавить блок «Цвет» к неразрушающему редактированию: баланс белого
|
||||
(Темп, Оттенок), Вибрация, Насыщенность, Цветовой микшер по оттенкам,
|
||||
Точечный цвет, Цветокоррекция.
|
||||
- Живой клиентский превью с паритетом трёх реализаций: сервер Go, клиент TypeScript,
|
||||
WASM (Rust) — как для «Света».
|
||||
- Рендер цветовых правок по пикселям исходного объекта, после световых правок.
|
||||
- Обратная совместимость: фото без ключа `color` в `edit_params` рендерятся как
|
||||
прежде.
|
||||
|
||||
**Non-Goals:**
|
||||
- Синхронизация правок между устройствами или через Android-клиент.
|
||||
- Изменение ролей хранения или формата объектов (`edit`, `edit_thumb`, … остаются).
|
||||
- Миграция схемы базы данных.
|
||||
|
||||
## Decisions
|
||||
|
||||
**Цвет хранится в том же `edit_params`, рядом с `light`.**
|
||||
- Обоснование: `EditParams` уже расширяется полем `Color ColorParams`; `map[string]any`
|
||||
на бэкенде и `EditParams` на клиенте принимают новый ключ без cambios схемы.
|
||||
- Альтернатива: отдельная колонка/таблица для цветовых правок — отвергнута, добавила бы
|
||||
миграцию и не сочетается с текущей моделью хранения.
|
||||
|
||||
**Порядок операций при рендере: свет, затем цвет.**
|
||||
- Обоснование: цветовые коррекции (баланс белого, насыщенность) логично применять
|
||||
к уже скорректированной по тональности картинке; сервер и клиент должны следовать
|
||||
одному порядку, иначе превью не совпадёт с результатом.
|
||||
- Альтернатива: цвет до света — отвергнуто, несоответствие Lightroom-поведению и
|
||||
текущему клиентскому конвейеру.
|
||||
|
||||
**Цветовая математика реализована трижды и держится в паритете: Go (сервер),
|
||||
TypeScript (клиент), Rust/WASM (живой превью).**
|
||||
- Обоснование: текущий подход со «Светом» (`applyLight` в Go, `applyLightToPixels`
|
||||
в TS, `light.wasm` в Rust, тест `wasmMatchesReference`) гарантирует, что превью
|
||||
в браузере совпадает с финальным рендером. Для цвета повторяем эту схему.
|
||||
- Альтернатива: считать цвет только на сервере и показывать превью после рендера —
|
||||
отвергнуто, пользователь ожидает мгновенного отклика при движении ползунков, как
|
||||
сейчас со светом.
|
||||
|
||||
**Цветовые параметры применяются в пространстве RGB с промежуточным HSL.**
|
||||
- Обоснование: баланс белого, вибрация, насыщенность и тонирование естественно
|
||||
выражаются через HSL; пиксели хранятся в RGBA, поэтому пересчёт RGB→HSL→RGB
|
||||
на пиксельном цикле.
|
||||
- Альтернатива: чистые операции над RGB-каналами — отвергнуто, менее точно
|
||||
соответствует цветовым инструментам Lightroom.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
[Расхождение реализаций Go / TS / Rust] → mitigation: тест паритета
|
||||
`wasmMatchesReference` расширяется на цвет, изменение любой реализации требует
|
||||
обновления остальных и теста.
|
||||
|
||||
[Сложность UI] → mitigation: цветовой микшер по 8 оттенкам и точечное тонирование
|
||||
добавляют много элементов управления в `PhotoEditPanel`; раздел «Цвет» делаем
|
||||
сворачиваемым, как «Свет».
|
||||
|
||||
[Производительность рендера] → mitigation: цвет добавляет один пиксельный проход
|
||||
(или объединяется с существующим циклом света); параллелизация по строкам
|
||||
(`applyLightRows`) остаётся.
|
||||
|
||||
[Обратная совместимость] → mitigation: отсутствие ключа `color` в `edit_params`
|
||||
трактуется как нулевые цветовые правки; старые фото не затрагиваются.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
Миграция схемы не требуется: `edit_params` — JSON-блоб, новый ключ `color`
|
||||
дополняет существующий `light`. Откат: удаление ключа `color` из `edit_params`
|
||||
возвращает фото к состоянию без цветовых правок.
|
||||
|
||||
## Open Questions
|
||||
|
||||
Нет — все проектные решения (объём цвета, живой превью с паритетом) согласованы.
|
||||
Reference in New Issue
Block a user