mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
168 lines
3.5 KiB
Go
168 lines
3.5 KiB
Go
package wayland
|
|
|
|
import (
|
|
"math"
|
|
)
|
|
|
|
type GammaRamp struct {
|
|
Red []uint16
|
|
Green []uint16
|
|
Blue []uint16
|
|
}
|
|
|
|
type rgb struct {
|
|
r, g, b float64
|
|
}
|
|
|
|
type xyz struct {
|
|
x, y, z float64
|
|
}
|
|
|
|
func illuminantD(temp int) (float64, float64, bool) {
|
|
var x float64
|
|
switch {
|
|
case temp >= 2500 && temp <= 7000:
|
|
t := float64(temp)
|
|
x = 0.244063 + 0.09911e3/t + 2.9678e6/(t*t) - 4.6070e9/(t*t*t)
|
|
case temp > 7000 && temp <= 25000:
|
|
t := float64(temp)
|
|
x = 0.237040 + 0.24748e3/t + 1.9018e6/(t*t) - 2.0064e9/(t*t*t)
|
|
default:
|
|
return 0, 0, false
|
|
}
|
|
y := -3*(x*x) + 2.870*x - 0.275
|
|
return x, y, true
|
|
}
|
|
|
|
func planckianLocus(temp int) (float64, float64, bool) {
|
|
var x, y float64
|
|
switch {
|
|
case temp >= 1667 && temp <= 4000:
|
|
t := float64(temp)
|
|
x = -0.2661239e9/(t*t*t) - 0.2343589e6/(t*t) + 0.8776956e3/t + 0.179910
|
|
if temp <= 2222 {
|
|
y = -1.1064814*(x*x*x) - 1.34811020*(x*x) + 2.18555832*x - 0.20219683
|
|
} else {
|
|
y = -0.9549476*(x*x*x) - 1.37418593*(x*x) + 2.09137015*x - 0.16748867
|
|
}
|
|
case temp > 4000 && temp < 25000:
|
|
t := float64(temp)
|
|
x = -3.0258469e9/(t*t*t) + 2.1070379e6/(t*t) + 0.2226347e3/t + 0.240390
|
|
y = 3.0817580*(x*x*x) - 5.87338670*(x*x) + 3.75112997*x - 0.37001483
|
|
default:
|
|
return 0, 0, false
|
|
}
|
|
return x, y, true
|
|
}
|
|
|
|
func srgbGamma(value, gamma float64) float64 {
|
|
if value <= 0.0031308 {
|
|
return 12.92 * value
|
|
}
|
|
return math.Pow(1.055*value, 1.0/gamma) - 0.055
|
|
}
|
|
|
|
func clamp01(v float64) float64 {
|
|
switch {
|
|
case v > 1.0:
|
|
return 1.0
|
|
case v < 0.0:
|
|
return 0.0
|
|
default:
|
|
return v
|
|
}
|
|
}
|
|
|
|
func xyzToSRGB(c xyz) rgb {
|
|
return rgb{
|
|
r: srgbGamma(clamp01(3.2404542*c.x-1.5371385*c.y-0.4985314*c.z), 2.2),
|
|
g: srgbGamma(clamp01(-0.9692660*c.x+1.8760108*c.y+0.0415560*c.z), 2.2),
|
|
b: srgbGamma(clamp01(0.0556434*c.x-0.2040259*c.y+1.0572252*c.z), 2.2),
|
|
}
|
|
}
|
|
|
|
func normalizeRGB(c *rgb) {
|
|
maxw := math.Max(c.r, math.Max(c.g, c.b))
|
|
if maxw > 0 {
|
|
c.r /= maxw
|
|
c.g /= maxw
|
|
c.b /= maxw
|
|
}
|
|
}
|
|
|
|
func calcWhitepoint(temp int) rgb {
|
|
if temp == 6500 {
|
|
return rgb{r: 1.0, g: 1.0, b: 1.0}
|
|
}
|
|
|
|
var wp xyz
|
|
|
|
switch {
|
|
case temp >= 25000:
|
|
x, y, _ := illuminantD(25000)
|
|
wp.x = x
|
|
wp.y = y
|
|
case temp >= 4000:
|
|
x, y, _ := illuminantD(temp)
|
|
wp.x = x
|
|
wp.y = y
|
|
case temp >= 2500:
|
|
x1, y1, _ := illuminantD(temp)
|
|
x2, y2, _ := planckianLocus(temp)
|
|
factor := float64(4000-temp) / 1500.0
|
|
sineFactor := (math.Cos(math.Pi*factor) + 1.0) / 2.0
|
|
wp.x = x1*sineFactor + x2*(1.0-sineFactor)
|
|
wp.y = y1*sineFactor + y2*(1.0-sineFactor)
|
|
default:
|
|
t := temp
|
|
if t < 1667 {
|
|
t = 1667
|
|
}
|
|
x, y, _ := planckianLocus(t)
|
|
wp.x = x
|
|
wp.y = y
|
|
}
|
|
|
|
wp.z = 1.0 - wp.x - wp.y
|
|
|
|
wpRGB := xyzToSRGB(wp)
|
|
normalizeRGB(&wpRGB)
|
|
return wpRGB
|
|
}
|
|
|
|
func GenerateGammaRamp(size uint32, temp int, gamma float64) GammaRamp {
|
|
ramp := GammaRamp{
|
|
Red: make([]uint16, size),
|
|
Green: make([]uint16, size),
|
|
Blue: make([]uint16, size),
|
|
}
|
|
|
|
wp := calcWhitepoint(temp)
|
|
|
|
for i := uint32(0); i < size; i++ {
|
|
val := float64(i) / float64(size-1)
|
|
ramp.Red[i] = uint16(clamp01(math.Pow(val*wp.r, 1.0/gamma)) * 65535.0)
|
|
ramp.Green[i] = uint16(clamp01(math.Pow(val*wp.g, 1.0/gamma)) * 65535.0)
|
|
ramp.Blue[i] = uint16(clamp01(math.Pow(val*wp.b, 1.0/gamma)) * 65535.0)
|
|
}
|
|
|
|
return ramp
|
|
}
|
|
|
|
func GenerateIdentityRamp(size uint32) GammaRamp {
|
|
ramp := GammaRamp{
|
|
Red: make([]uint16, size),
|
|
Green: make([]uint16, size),
|
|
Blue: make([]uint16, size),
|
|
}
|
|
|
|
for i := uint32(0); i < size; i++ {
|
|
val := uint16((float64(i) / float64(size-1)) * 65535.0)
|
|
ramp.Red[i] = val
|
|
ramp.Green[i] = val
|
|
ramp.Blue[i] = val
|
|
}
|
|
|
|
return ramp
|
|
}
|