@@ -10,9 +10,7 @@ import (
1010// colors. Slots 8 and 9-15 are left empty — pass through finalizePalette to fill them.
1111// Mode transforms call this directly when they intend to overwrite bg/fg/ANSI in OKLCH,
1212// avoiding wasted slot 8/9-15 generation that the full chromatic pipeline would do.
13- //
14- // Slot 1-6 hues are taken verbatim from the image's best matches (no synthesis at
15- // canonical sRGB primary hues). NormalizeBrightness handles AA contrast downstream.
13+ // Slot 1-6 are taken verbatim from the image's best matches; no canonical-hue synthesis.
1614func extractChromaticHues (dominantColors []string , lightMode bool ) [16 ]string {
1715 topCount := 12
1816 if len (dominantColors ) < topCount {
@@ -35,38 +33,17 @@ func extractChromaticHues(dominantColors []string, lightMode bool) [16]string {
3533 palette [0 ] = bgColor
3634 palette [7 ] = fgColor
3735
36+ // ExtractColors guarantees len(dominantColors) ≥ 8 and at most 2 are pre-claimed
37+ // for bg/fg, so FindOptimalAnsiAssignment always fills all 6 ANSI slots.
3838 assignments := FindOptimalAnsiAssignment (dominantColors , usedIndices , lightMode )
39-
4039 for i := 0 ; i < 6 ; i ++ {
41- assignment := assignments [i ]
42- if assignment != nil {
43- palette [i + 1 ] = dominantColors [assignment .PoolIndex ]
44- usedIndices [assignment .PoolIndex ] = true
45- continue
46- }
47- // Pool exhausted — the optimal-assignment loop ran out of unused colors.
48- // Fall back to the next available pool entry rather than synthesizing a
49- // canonical-hue color that isn't in the image.
50- palette [i + 1 ] = nextUnusedColor (dominantColors , usedIndices )
40+ palette [i + 1 ] = dominantColors [assignments [i ].PoolIndex ]
41+ usedIndices [assignments [i ].PoolIndex ] = true
5142 }
5243
5344 return palette
5445}
5546
56- // nextUnusedColor returns the first dominant color not yet claimed by another slot,
57- // marking it used. Returns the first pool entry as a last resort when the pool is
58- // fully consumed (extremely degenerate — len(dominantColors) is bounded ≥ 8 by
59- // ExtractColors).
60- func nextUnusedColor (dominantColors []string , usedIndices map [int ]bool ) string {
61- for i , c := range dominantColors {
62- if ! usedIndices [i ] {
63- usedIndices [i ] = true
64- return c
65- }
66- }
67- return dominantColors [0 ]
68- }
69-
7047// synthesizeBgIfTooMid replaces a mid-lightness image bg with a synthesized OKLCH
7148// color at a sane bg lightness, preserving hue. Without this, images with no truly
7249// dark/light pixels (e.g. a sunset photo or a Nord-themed wallpaper) produce muddy
@@ -86,10 +63,7 @@ func synthesizeBgIfTooMid(bgColor string, lightMode bool) string {
8663}
8764
8865// GenerateChromaticPalette: vibrant chromatic palette from image-derived hues.
89- // OKLCH-based optimal assignment for slots 1-6, contrast-aware bg/fg. Slots 1-6
90- // always come from the image — the pipeline does not synthesize canonical-hue
91- // fallbacks, so wallpapers without a strong red/green/etc. produce palettes
92- // faithful to the source rather than to ANSI conventions.
66+ // OKLCH-based optimal assignment for slots 1-6, contrast-aware bg/fg.
9367// finalizePalette derives slots 8/9-15 and enforces AA contrast.
9468func GenerateChromaticPalette (dominantColors []string , lightMode bool ) [16 ]string {
9569 palette := extractChromaticHues (dominantColors , lightMode )
0 commit comments