mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
codes for OKLab colour space
This commit is contained in:
81
src/net/torvald/colourutil/OKLabUtil.kt
Normal file
81
src/net/torvald/colourutil/OKLabUtil.kt
Normal file
@@ -0,0 +1,81 @@
|
||||
package net.torvald.colourutil
|
||||
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.pow
|
||||
|
||||
/**
|
||||
* OKLab is a colour space devised by Björn Ottosson. https://bottosson.github.io/posts/oklab/
|
||||
*
|
||||
* Created by minjaesong on 2022-12-02.
|
||||
*/
|
||||
object OKLabUtil {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param L Luminosity. Scale depends on the scale of the conversion (if source Lab had 0..100, this value will also be 0..100).
|
||||
* @param C Chrominance. Scale depends on the scale of the conversion.
|
||||
* @param h Hue in RADIANS (-pi..pi).
|
||||
*/
|
||||
data class OKLCh(var L: Float = 0f, val C: Float = 0f, val h: Float = 0f, val alpha: Float = 1f)
|
||||
|
||||
data class OKLab(var L: Float = 0f, val a: Float = 0f, val b: Float = 0f, val alpha: Float = 1f) {
|
||||
fun toOKLCh(): OKLCh {
|
||||
val c = (a*a + b*b).pow(0.5f)
|
||||
val h = atan2(a, b)
|
||||
|
||||
return OKLCh(L, c, h, alpha)
|
||||
}
|
||||
|
||||
fun toSRGB(): RGB {
|
||||
val l_ = L + 0.3963377774f * a + 0.2158037573f * b
|
||||
val m_ = L - 0.1055613458f * a - 0.0638541728f * b
|
||||
val s_ = L - 0.0894841775f * a - 1.2914855480f * b
|
||||
|
||||
val l = l_ * l_ * l_
|
||||
val m = m_ * m_ * m_
|
||||
val s = s_ * s_ * s_
|
||||
|
||||
val lrgb = RGB(
|
||||
+4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s
|
||||
-1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s
|
||||
-0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s,
|
||||
alpha
|
||||
)
|
||||
|
||||
return lrgb.unLinearise()
|
||||
}
|
||||
}
|
||||
|
||||
fun CIEXYZ.toOKLab(): OKLab {
|
||||
val l = (0.8189330101f * this.X + 0.3618667424f * this.Y - 0.1288597137f * this.Z).pow(0.333333333333f)
|
||||
val m = (0.0329845436f * this.X + 0.9293118715f * this.Y + 0.0361456387f * this.Z).pow(0.333333333333f)
|
||||
val s = (0.0482003018f * this.X + 0.2643662691f * this.Y + 0.6338517070f * this.Z).pow(0.333333333333f)
|
||||
|
||||
val L = 0.2104542553f*l + 0.7936177850f*m - 0.0040720468f*s
|
||||
val a = 1.9779984951f*l - 2.4285922050f*m + 0.4505937099f*s
|
||||
val b = 0.0259040371f*l + 0.7827717662f*m - 0.8086757660f*s
|
||||
|
||||
return OKLab(L, a, b, alpha)
|
||||
}
|
||||
|
||||
fun RGB.toOKLab(): OKLab {
|
||||
val c = this.linearise()
|
||||
|
||||
val l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b
|
||||
val m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b
|
||||
val s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b
|
||||
|
||||
val l_ = l.pow(0.3333333333333f)
|
||||
val m_ = m.pow(0.3333333333333f)
|
||||
val s_ = s.pow(0.3333333333333f)
|
||||
|
||||
|
||||
val L = 0.2104542553f * l_ + 0.7936177850f * m_ - 0.0040720468f * s_
|
||||
val a = 1.9779984951f * l_ - 2.4285922050f * m_ + 0.4505937099f * s_
|
||||
val b = 0.0259040371f * l_ + 0.7827717662f * m_ - 0.8086757660f * s_
|
||||
|
||||
return OKLab(L, a, b, c.alpha)
|
||||
}
|
||||
Reference in New Issue
Block a user