Add harmonize utils
This commit is contained in:
@@ -31,7 +31,9 @@ cargo run --release -- /path/to/screenshot.png
|
||||
|
||||
## Color grouping and mapping
|
||||
|
||||
**Group similar colors** is enabled by default in the **Palette**. Nearby shades
|
||||
**Group similar colors** is enabled by default in the **Palette**. The default
|
||||
**Edited** view shows the resulting colors. Switch to **Source / map** to select
|
||||
original colors for replacement. Nearby shades
|
||||
from scaling or compression share a row showing their combined percentage and
|
||||
shade count. Adjust **Tolerance** (default 8, range 0–32) to control the maximum
|
||||
difference in each RGB channel from the group's most frequent color. Groups do
|
||||
@@ -39,7 +41,8 @@ not chain together through intermediate shades. Turn grouping off or set toleran
|
||||
to zero for the exact palette. Hover a row to highlight its pixels in magenta in
|
||||
the crop preview; this temporary highlight is never exported.
|
||||
|
||||
Freeze a capture or import an image, then click **Map** beside a palette row.
|
||||
Freeze a capture or import an image, choose **Source / map**, then click **Map**
|
||||
beside a palette row.
|
||||
In **Color mapping**, click its replacement swatch to choose another color or enter
|
||||
RGB values. Every original shade in that group maps to the chosen replacement.
|
||||
Add multiple mappings to try a new palette. Each mapping keeps its original group
|
||||
@@ -54,13 +57,68 @@ changes, pause during live capture, and return when frozen again. Opening a new
|
||||
image or choosing a new capture source clears them.
|
||||
|
||||
Mappings apply before the preview adjustments or vision filter. Source preview,
|
||||
analysis, copied pixel values, and **Save crop PNG** still use the original.
|
||||
copied pixel values, and **Save crop PNG** still use the original. Color analysis
|
||||
and the vision check use the edited selection.
|
||||
**Save mapped crop PNG** exports the crop with replacements, preserving alpha
|
||||
and excluding preview adjustments and filters.
|
||||
|
||||
## Automatic harmony
|
||||
|
||||
Freeze a capture or import an image, open **Harmonize**, and enable **Preview
|
||||
harmony**. Choose **Monochromatic**, **Analogous**, **Complementary**,
|
||||
**Split-Complementary**, or **Triadic**. The app fits that rule to the crop automatically, then moves its hue families toward the
|
||||
chosen harmony while preserving shading. **Strength** blends from the input
|
||||
at 0% to the full transformation at 100%. **Rotation**, or dragging the color
|
||||
wheel, changes the palette's direction. White dots on the wheel mark input hue
|
||||
families; colored spokes mark target hues. The wheel shows targets at full
|
||||
strength. **Auto fit** resets rotation and fits the current crop again.
|
||||
|
||||
**Protect neutrals** is enabled by default: gray and near-gray colors stay
|
||||
unchanged, with a gradual transition into chromatic colors. **Reset harmony**
|
||||
turns harmony off and restores its defaults. Disabling **Preview harmony** lets
|
||||
you compare with the input (including any enabled manual mappings). Settings
|
||||
pause during live capture, resume when frozen, and reset for a new image or
|
||||
capture source. Changing the crop or manual mappings refits the harmony while
|
||||
retaining your rotation and strength.
|
||||
|
||||
Harmony works in OKLCH: it holds perceptual lightness and chroma while shifting
|
||||
hue, reducing chroma when needed to fit sRGB. It retains small hue variations
|
||||
within a family and compresses broad families into bands around target hues.
|
||||
Monochromatic instead converges to a single hue at full strength, retaining
|
||||
lightness and chroma variations (with neutral protection still applied).
|
||||
The offsets are 0° for monochromatic, −30°/0°/+30° for analogous, 0°/180° for
|
||||
complementary, 0°/150°/210° for split-complementary, and 0°/120°/240° for triadic,
|
||||
on the **OKLCH** wheel. These angles do not produce
|
||||
identical color pairs to HSV or traditional artist color wheels.
|
||||
|
||||
The fit uses a circular hue histogram, finds hue families, and searches for the
|
||||
orientation requiring the least weighted squared hue movement. Counts are
|
||||
square-root weighted after hue binning so a large background has less influence
|
||||
and compression-generated near-duplicates don't each get a separate vote. This
|
||||
is an experimental palette heuristic: it does not recognize objects, protect
|
||||
skin or gameplay indicators automatically, or guarantee that every target hue
|
||||
is used. Families may merge, and family boundaries can still affect subtle hue
|
||||
ramps. Start with moderate strength and compare the result in context.
|
||||
|
||||
The processing order is **source → manual mappings → harmony → preview filter
|
||||
or adjustments**. The source preview and copied pixel values remain original; color analysis and
|
||||
the vision check use the edited selection. **Save harmonized crop PNG** includes enabled mappings and harmony,
|
||||
preserving transparency, without hover highlights, preview filters, or
|
||||
adjustments. **Save mapped crop PNG** still saves only manual replacements;
|
||||
**Save crop PNG** still saves the original.
|
||||
|
||||
The conversion uses [Björn Ottosson's Oklab transforms](https://bottosson.github.io/posts/oklab/).
|
||||
|
||||
## Color analysis and vision checks
|
||||
|
||||
The **Color analysis** tab has four distributions:
|
||||
The **Color analysis** tab uses the edited selection after active mappings,
|
||||
harmony, and the selected filter or adjustments. Histograms, means, neutral
|
||||
counts, distinct-color weighting, and the **Edited** palette all update together.
|
||||
Merged colors count once for distinct-color weighting. Diagnostic simulation
|
||||
previews and hover highlights are excluded, just as in the vision check.
|
||||
**Source / map** keeps the original palette available for choosing replacements.
|
||||
|
||||
The tab has four distributions:
|
||||
|
||||
- **Hue**: HSV hue in 36 ten-degree bins; saturation below 5% counts as neutral.
|
||||
- **Saturation**: HSV saturation, from neutral to fully saturated.
|
||||
@@ -80,8 +138,8 @@ tritanopia, or grayscale directly to the crop preview, or select **Original**
|
||||
to use the live color adjustment sliders. The first three use the
|
||||
Machado–Oliveira–Fernandes full-severity model, applied in linear RGB and then
|
||||
encoded back to sRGB. Grayscale uses relative luminance and tests removal of color
|
||||
cues; it does not model all aspects of achromatopsia. Preview mode does not change
|
||||
histograms, copied pixel values, or the exported PNG: those always use the original.
|
||||
cues; it does not model all aspects of achromatopsia. The selected filter updates color analysis and the vision check. Copied pixel
|
||||
values and **Save crop PNG** still use the original.
|
||||
|
||||
**Invert** replaces each RGB channel with its complement (255 minus the channel).
|
||||
With **Original** selected, adjust **Hue shift** (−180° to +180°), **Saturation**
|
||||
@@ -94,12 +152,24 @@ while another filter is selected and applied again when returning to Original.
|
||||
Filters preserve alpha and always start from source pixels, so edits do not
|
||||
accumulate rounding errors.
|
||||
|
||||
**Vision check** automatically checks all four scenarios. It flags pairs whose
|
||||
OKLab distance falls from at least 0.08 to at most 0.04, losing at least 50% of the
|
||||
original separation. These are project-specific screening heuristics, not
|
||||
validated visibility thresholds or WCAG criteria. Each scenario shows original
|
||||
**Vision check** automatically checks all four scenarios against the **edited
|
||||
selection**, after enabled group/manual mappings, harmony, and the selected
|
||||
filter or adjustments. It updates when these edits or the crop change. Palette
|
||||
grouping alone only organizes colors; mapping a group changes the checked pixels.
|
||||
Colors that merge through editing count as one color, and opaque-pixel coverage
|
||||
is recalculated from the result. Color distributions and the edited palette use
|
||||
those same pixels; **Source / map** remains available for mapping input colors.
|
||||
|
||||
The report's **Preview** buttons add a separate simulation of those edited
|
||||
pixels. They do not change the selected filter or feed simulated pixels back into
|
||||
the report. Use **Return to edited preview** to remove this simulation. Temporary
|
||||
palette hover highlights are also excluded from the check.
|
||||
|
||||
The check flags pairs whose OKLab distance falls from at least 0.08 to at most 0.04, losing at least 50% of the
|
||||
separation in the edited image. These are project-specific screening heuristics, not
|
||||
validated visibility thresholds or WCAG criteria. Each scenario shows edited
|
||||
and simulated swatches, numeric hex values, and up to six closest candidate pairs.
|
||||
The preview button opens the corresponding simulation for the current crop.
|
||||
The preview button opens the corresponding simulation for the edited crop.
|
||||
|
||||
The check is bounded to the 64 most frequent **opaque** colors and reports both
|
||||
color and pixel coverage. Partially/fully transparent pixels have no known
|
||||
@@ -156,6 +226,9 @@ repeated portal requests during/after capture. The portal regression test requir
|
||||
bus and does not open desktop dialogs. Color tests cover histogram endpoints and
|
||||
weighting, sRGB gamma, simulation reference colors, alpha handling, warning
|
||||
positives/negatives, palette coverage, and preserving source pixels.
|
||||
Harmony tests cover color-space reference values, gamut reduction, circular hue
|
||||
fitting, neutral protection, shading, alpha, preset rendering, crop and capture
|
||||
lifecycle, and exported PNG pixels.
|
||||
Actual portal capture requires a running
|
||||
Wayland desktop and permission through KDE's picker.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user