mandala/palette.go
2025-06-01 19:25:40 +03:00

372 lines
11 KiB
Go

package main
import (
"image/color"
"math/rand/v2"
)
type Palette []color.RGBA
var textColors = []color.RGBA{
// basic bright colors
{255, 100, 100, 255}, // red
{100, 255, 100, 255}, // green
{100, 100, 255, 255}, // blue
{255, 255, 100, 255}, // yellow
{255, 100, 255, 255}, // magenta
{100, 255, 255, 255}, // cyan
{255, 255, 255, 255}, // white
{255, 150, 50, 255}, // orange
{150, 255, 50, 255}, // lime
{255, 50, 150, 255}, // pink
{50, 150, 255, 255}, // sky blue
{200, 200, 255, 255}, // light blue
// extended primary variations
{255, 50, 50, 255}, // bright red
{255, 150, 150, 255}, // light red
{50, 255, 50, 255}, // bright green
{150, 255, 150, 255}, // light green
{50, 50, 255, 255}, // bright blue
{150, 150, 255, 255}, // light blue variant
// warm colors
{255, 200, 50, 255}, // golden yellow
{255, 175, 0, 255}, // amber
{255, 69, 0, 255}, // red orange
{255, 20, 147, 255}, // deep pink
{255, 105, 180, 255}, // hot pink
{255, 182, 193, 255}, // light pink
{255, 160, 122, 255}, // light salmon
{255, 99, 71, 255}, // tomato
{255, 127, 80, 255}, // coral
// cool colors
{0, 255, 127, 255}, // spring green
{0, 250, 154, 255}, // medium spring green
{64, 224, 208, 255}, // turquoise
{72, 209, 204, 255}, // medium turquoise
{135, 206, 250, 255}, // light sky blue
{70, 130, 180, 255}, // steel blue
{100, 149, 237, 255}, // cornflower blue
{123, 104, 238, 255}, // medium slate blue
{138, 43, 226, 255}, // blue violet
// purple spectrum
{147, 112, 219, 255}, // medium purple
{186, 85, 211, 255}, // medium orchid
{218, 112, 214, 255}, // orchid
{221, 160, 221, 255}, // plum
{238, 130, 238, 255}, // violet
{255, 0, 255, 255}, // pure magenta
{199, 21, 133, 255}, // medium violet red
{219, 112, 147, 255}, // pale violet red
// neon/electric colors
{57, 255, 20, 255}, // electric green
{255, 20, 147, 255}, // electric pink
{0, 255, 255, 255}, // electric cyan
{255, 255, 0, 255}, // electric yellow
{255, 0, 127, 255}, // electric rose
{127, 255, 0, 255}, // electric lime
{255, 127, 0, 255}, // electric orange
{0, 127, 255, 255}, // electric blue
// pastel variants
{255, 218, 185, 255}, // peach puff
{255, 228, 196, 255}, // bisque
{255, 239, 213, 255}, // papaya whip
{240, 248, 255, 255}, // alice blue
{230, 230, 250, 255}, // lavender
{255, 240, 245, 255}, // lavender blush
{255, 228, 225, 255}, // misty rose
{245, 255, 250, 255}, // mint cream
// earth tones (brighter versions)
{210, 180, 140, 255}, // tan
{222, 184, 135, 255}, // burlywood
{238, 203, 173, 255}, // navajo white
{255, 218, 185, 255}, // peach
{255, 165, 79, 255}, // sandy brown
{205, 133, 63, 255}, // peru
{160, 82, 45, 255}, // saddle brown (lighter)
{210, 105, 30, 255}, // chocolate (lighter)
// jewel tones
{50, 205, 50, 255}, // lime green
{220, 20, 60, 255}, // crimson
{75, 0, 130, 255}, // indigo (brightened)
{128, 0, 128, 255}, // purple (brightened)
{165, 42, 42, 255}, // brown (brightened)
{128, 128, 0, 255}, // olive (brightened)
{0, 128, 128, 255}, // teal (brightened)
{128, 0, 0, 255}, // maroon (brightened)
// unique/exotic colors
{255, 215, 0, 255}, // gold
{192, 192, 192, 255}, // silver
{255, 20, 147, 255}, // deep pink
{0, 191, 255, 255}, // deep sky blue
{30, 144, 255, 255}, // dodger blue
{255, 69, 0, 255}, // orange red
{154, 205, 50, 255}, // yellow green
{32, 178, 170, 255}, // light sea green
{60, 179, 113, 255}, // medium sea green
// vibrant spectrum
{127, 255, 212, 255}, // aquamarine
{240, 230, 140, 255}, // khaki
{238, 232, 170, 255}, // pale goldenrod
{250, 240, 230, 255}, // linen
{253, 245, 230, 255}, // old lace
{255, 250, 240, 255}, // floral white
{248, 248, 255, 255}, // ghost white
{245, 245, 220, 255}, // beige
}
var themePalettes = map[string]Palette{
"vibrant": {
{255, 0, 150, 255}, // hot pink
{255, 100, 0, 255}, // orange
{255, 255, 0, 255}, // yellow
{0, 255, 100, 255}, // lime
{0, 150, 255, 255}, // sky blue
{150, 0, 255, 255}, // purple
},
"sunset": {
{255, 94, 77, 255}, // coral
{255, 154, 0, 255}, // orange
{255, 206, 84, 255}, // yellow
{255, 118, 117, 255}, // light coral
{240, 147, 43, 255}, // dark orange
{235, 77, 75, 255}, // red
},
"ocean": {
{0, 123, 255, 255}, // blue
{0, 200, 255, 255}, // light blue
{0, 255, 200, 255}, // cyan
{100, 200, 255, 255}, // sky blue
{0, 150, 200, 255}, // dark blue
{50, 255, 150, 255}, // aqua
},
"neon": {
{255, 0, 255, 255}, // magenta
{0, 255, 255, 255}, // cyan
{255, 255, 0, 255}, // yellow
{255, 0, 100, 255}, // hot pink
{100, 255, 0, 255}, // lime
{150, 0, 255, 255}, // purple
},
"cosmic": {
{138, 43, 226, 255}, // blue violet
{75, 0, 130, 255}, // indigo
{148, 0, 211, 255}, // dark violet
{255, 20, 147, 255}, // deep pink
{255, 0, 255, 255}, // magenta
{72, 61, 139, 255}, // dark slate blue
},
"midnight": {
{25, 25, 112, 255}, // midnight blue
{72, 61, 139, 255}, // dark slate blue
{123, 104, 238, 255}, // medium slate blue
{147, 112, 219, 255}, // medium purple
{138, 43, 226, 255}, // blue violet
{75, 0, 130, 255}, // indigo
{0, 0, 139, 255}, // dark blue
{30, 144, 255, 255}, // dodger blue
},
"fire": {
{139, 0, 0, 255}, // dark red
{178, 34, 34, 255}, // firebrick
{220, 20, 60, 255}, // crimson
{255, 69, 0, 255}, // red orange
{255, 140, 0, 255}, // dark orange
{255, 165, 0, 255}, // orange
{255, 215, 0, 255}, // gold
{255, 255, 224, 255}, // light yellow
},
"pastel": {
{255, 182, 193, 255}, // light pink
{255, 218, 185, 255}, // peach puff
{255, 255, 224, 255}, // light yellow
{240, 255, 240, 255}, // honeydew
{224, 255, 255, 255}, // light cyan
{230, 230, 250, 255}, // lavender
{255, 228, 225, 255}, // misty rose
{245, 255, 250, 255}, // mint cream
},
"earth": {
{139, 69, 19, 255}, // saddle brown
{160, 82, 45, 255}, // saddle brown
{205, 133, 63, 255}, // peru
{222, 184, 135, 255}, // burlywood
{210, 180, 140, 255}, // tan
{188, 143, 143, 255}, // rosy brown
{218, 165, 32, 255}, // goldenrod
{128, 128, 0, 255}, // olive
},
"ice": {
{240, 248, 255, 255}, // alice blue
{230, 230, 250, 255}, // lavender
{176, 196, 222, 255}, // light steel blue
{173, 216, 230, 255}, // light blue
{135, 206, 250, 255}, // light sky blue
{135, 206, 235, 255}, // sky blue
{70, 130, 180, 255}, // steel blue
{100, 149, 237, 255}, // cornflower blue
},
"autumn": {
{139, 69, 19, 255}, // saddle brown
{165, 42, 42, 255}, // brown
{178, 34, 34, 255}, // firebrick
{205, 92, 92, 255}, // indian red
{233, 150, 122, 255}, // dark salmon
{255, 160, 122, 255}, // light salmon
{255, 215, 0, 255}, // gold
{255, 140, 0, 255}, // dark orange
},
"cyberpunk": {
{255, 0, 150, 255}, // hot pink
{0, 255, 255, 255}, // cyan
{255, 0, 255, 255}, // magenta
{148, 0, 211, 255}, // dark violet
{75, 0, 130, 255}, // indigo
{0, 0, 139, 255}, // dark blue
{255, 20, 147, 255}, // deep pink
{138, 43, 226, 255}, // blue violet
},
"retro": {
{255, 105, 180, 255}, // hot pink
{255, 20, 147, 255}, // deep pink
{255, 69, 0, 255}, // red orange
{255, 215, 0, 255}, // gold
{50, 205, 50, 255}, // lime green
{0, 191, 255, 255}, // deep sky blue
{138, 43, 226, 255}, // blue violet
{255, 140, 0, 255}, // dark orange
},
"monochrome": {
{0, 0, 0, 255}, // black
{105, 105, 105, 255}, // dim gray
{128, 128, 128, 255}, // gray
{169, 169, 169, 255}, // dark gray
{192, 192, 192, 255}, // silver
{211, 211, 211, 255}, // light gray
{220, 220, 220, 255}, // gainsboro
{255, 255, 255, 255}, // white
},
"tropical": {
{255, 99, 71, 255}, // tomato
{255, 165, 0, 255}, // orange
{255, 215, 0, 255}, // gold
{154, 205, 50, 255}, // yellow green
{0, 255, 127, 255}, // spring green
{64, 224, 208, 255}, // turquoise
{0, 206, 209, 255}, // dark turquoise
{72, 209, 204, 255}, // medium turquoise
},
"volcanic": {
{128, 0, 0, 255}, // maroon
{139, 0, 0, 255}, // dark red
{165, 42, 42, 255}, // brown
{178, 34, 34, 255}, // firebrick
{205, 92, 92, 255}, // indian red
{220, 20, 60, 255}, // crimson
{255, 69, 0, 255}, // red orange
{255, 99, 71, 255}, // tomato
},
"aurora": {
{0, 255, 127, 255}, // spring green
{50, 205, 50, 255}, // lime green
{0, 255, 255, 255}, // cyan
{135, 206, 250, 255}, // light sky blue
{138, 43, 226, 255}, // blue violet
{148, 0, 211, 255}, // dark violet
{255, 20, 147, 255}, // deep pink
{255, 105, 180, 255}, // hot pink
},
"desert": {
{244, 164, 96, 255}, // sandy brown
{210, 180, 140, 255}, // tan
{222, 184, 135, 255}, // burlywood
{238, 203, 173, 255}, // navajo white
{255, 228, 181, 255}, // moccasin
{255, 218, 185, 255}, // peach puff
{255, 160, 122, 255}, // light salmon
{205, 133, 63, 255}, // peru
},
"matrix": {
{0, 100, 0, 255}, // dark green
{0, 128, 0, 255}, // green
{34, 139, 34, 255}, // forest green
{50, 205, 50, 255}, // lime green
{124, 252, 0, 255}, // lawn green
{127, 255, 0, 255}, // chartreuse
{0, 255, 0, 255}, // lime
{173, 255, 47, 255}, // green yellow
},
}
func getRandomTextColors() (color.RGBA, color.RGBA) {
textColor := textColors[rand.IntN(len(textColors))]
// calculate perceived brightness using luminance formula
// std. weights for human eye sensitivity: 0.299*R + 0.587*G + 0.114*B
brightness := 0.299*float64(textColor.R) + 0.587*float64(textColor.G) + 0.114*float64(textColor.B)
var outlineColor color.RGBA
if brightness < 128 { // Dark text - use white outline
outlineColor = color.RGBA{255, 255, 255, 255}
} else { // Bright text - use black outline
outlineColor = color.RGBA{0, 0, 0, 255}
}
return textColor, outlineColor
}
func getThemePalette(name string) Palette {
if palette, exists := themePalettes[name]; exists {
return palette
}
return themePalettes["vibrant"] // default
}
func getRandomThemePalette() (Palette, string) {
name := config.ColorThemes[rand.IntN(len(config.ColorThemes))]
return getThemePalette(name), name
}
func (p Palette) interpolate(t float64) color.RGBA {
if len(p) == 0 {
return color.RGBA{128, 128, 128, 255}
}
// clamp to to [0, 1]
if t < 0 {
t = 0
}
if t > 1 {
t = 1
}
// calculate which colors to interpolate between
scaledT := t * float64(len(p)-1)
index := int(scaledT)
localT := scaledT - float64(index)
if index >= len(p)-1 {
return p[len(p)-1]
}
c1 := p[index]
c2 := p[index+1]
// linear interpolation between the two colors
r := uint8(float64(c1.R)*(1-localT) + float64(c2.R)*localT)
g := uint8(float64(c1.G)*(1-localT) + float64(c2.G)*localT)
b := uint8(float64(c1.B)*(1-localT) + float64(c2.B)*localT)
a := uint8(float64(c1.A)*(1-localT) + float64(c2.A)*localT)
return color.RGBA{r, g, b, a}
}