InvertColor inverts the color's lightness in Oklch space while preserving chroma (saturation). For chromatic colors, L is adjusted toward 0.5 only as needed to preserve a fraction of the original chroma (set by chromaPreserveFactor), since the sRGB gamut has less room for chroma at extreme lightness
()
| 143 | // extreme lightness values. |
| 144 | // Special colors (default, transparent) are returned unchanged. |
| 145 | func (c Color) InvertColor() Color { |
| 146 | if c == DefaultColor || c == TransparentColor || c == "" { |
| 147 | return c |
| 148 | } |
| 149 | |
| 150 | tc := c.Color() |
| 151 | if tc == tcell.ColorDefault { |
| 152 | return c |
| 153 | } |
| 154 | |
| 155 | hex := tc.TrueColor().Hex() |
| 156 | if hex < 0 { |
| 157 | return c |
| 158 | } |
| 159 | |
| 160 | col, err := colorful.Hex(fmt.Sprintf("#%06x", hex)) |
| 161 | if err != nil { |
| 162 | return c |
| 163 | } |
| 164 | |
| 165 | L, C, h := col.OkLch() |
| 166 | |
| 167 | // For achromatic colors, simply invert L |
| 168 | if C < 0.01 { |
| 169 | return NewColor(colorful.OkLch(1.0-L, 0, h).Clamped().Hex()) |
| 170 | } |
| 171 | |
| 172 | // For chromatic colors, find L closest to inverted that preserves |
| 173 | // at least chromaPreserveFactor of the original chroma |
| 174 | targetL := 1.0 - L |
| 175 | minC := C * chromaPreserveFactor |
| 176 | actualL := closestLForChroma(targetL, minC, h) |
| 177 | |
| 178 | // Use as much of the original chroma as the gamut allows at actualL |
| 179 | maxC := maxChromaForLH(actualL, h) |
| 180 | actualC := C |
| 181 | if maxC < C { |
| 182 | actualC = maxC |
| 183 | } |
| 184 | |
| 185 | inverted := colorful.OkLch(actualL, actualC, h).Clamped() |
| 186 | |
| 187 | return NewColor(inverted.Hex()) |
| 188 | } |