package net.torvald.colourutil import com.jme3.math.FastMath import net.torvald.colourutil.CIELChabUtil.toLCh import net.torvald.colourutil.CIELChabUtil.toLab import net.torvald.colourutil.CIELabUtil.toLab import net.torvald.colourutil.CIEXYZUtil.toXYZ import net.torvald.colourutil.CIEXYZUtil.toColor import net.torvald.colourutil.CIELabUtil.toXYZ import com.badlogic.gdx.graphics.Color /** * Cylindrical modification of CIELab colour space * * reference: http://www.brucelindbloom.com/index.html?Equations.html * * Created by minjaesong on 2016-09-01. */ object CIELChabUtil { /** Sweet LCh_ab linear gradient */ fun getGradient(scale: Float, fromCol: Color, toCol: Color): Color { val from = fromCol.toLCh() val to = toCol.toLCh() val newL = FastMath.interpolateLinear(scale, from.L, to.L) val newC = FastMath.interpolateLinear(scale, from.C, to.C) val newAlpha = FastMath.interpolateLinear(scale, from.alpha, to.alpha) val newH: Float if ((from.h - to.h).abs() == FastMath.PI) // exact opposite colour return CIELabUtil.getGradient(scale, fromCol, toCol) else if ((from.h - to.h).abs() > FastMath.PI) // reflex angle newH = FastMath.interpolateLinear(scale, from.h, to.h + FastMath.TWO_PI) else newH = FastMath.interpolateLinear(scale, from.h, to.h) return CIELCh(newL, newC, newH, newAlpha).toColor() } fun CIELab.toLCh(): CIELCh { val c = (a.sqr() + b.sqr()).sqrt() val h = FastMath.atan2(b, a) return CIELCh(L, c, h, alpha) } fun CIELCh.toLab(): CIELab { val a = C * FastMath.cos(h) val b = C * FastMath.sin(h) return CIELab(L, a, b, alpha) } private fun Float.sqr() = this * this private fun Float.sqrt() = Math.sqrt(this.toDouble()).toFloat() private fun Float.abs() = FastMath.abs(this) } fun Color.toLCh() = this.toXYZ().toLab().toLCh() fun CIELCh.toColor() = this.toLab().toXYZ().toColor() /** * @param L : Luminosity in 0.0 - 1.0 * @param C : Chroma (saturation) in 0.0 - 1.0 * @param h : Hue in radian (-pi to pi) */ data class CIELCh(var L: Float = 0f, var C: Float = 0f, var h: Float = 0f, var alpha: Float = 1f)