From 9608946d358c8c6fab64aa61c8eeb92ac0477486 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Thu, 21 Oct 2021 23:03:07 +0200 Subject: [PATCH] [orx-color] Add OKHSLa, OKHSVa --- .../commonMain/kotlin/palettes/Palettes.kt | 2 +- .../commonMain/kotlin/spaces/ColorHSLUVa.kt | 2 +- .../commonMain/kotlin/spaces/ColorOKHSL.kt | 124 ++++++++ .../commonMain/kotlin/spaces/ColorOKHSV.kt | 114 ++++++++ .../commonMain/kotlin/spaces/ColorOKLABa.kt | 2 +- .../commonMain/kotlin/spaces/ColorOKLCHa.kt | 2 +- .../src/commonMain/kotlin/spaces/OKHelpers.kt | 264 ++++++++++++++++++ orx-color/src/demo/kotlin/DemoColorPlane01.kt | 2 +- orx-color/src/demo/kotlin/DemoColorPlane02.kt | 2 +- orx-color/src/demo/kotlin/DemoColorRange01.kt | 2 +- orx-color/src/demo/kotlin/DemoColorRange02.kt | 2 +- orx-color/src/demo/kotlin/DemoColorRange03.kt | 8 +- orx-color/src/demo/kotlin/DemoColorRange04.kt | 8 +- orx-color/src/demo/kotlin/DemoHSLUV01.kt | 2 +- orx-color/src/demo/kotlin/DemoHSLUV02.kt | 2 +- orx-color/src/demo/kotlin/DemoOKHSV01.kt | 29 ++ orx-color/src/demo/kotlin/DemoXSLUV01.kt | 4 +- 17 files changed, 551 insertions(+), 20 deletions(-) create mode 100644 orx-color/src/commonMain/kotlin/spaces/ColorOKHSL.kt create mode 100644 orx-color/src/commonMain/kotlin/spaces/ColorOKHSV.kt create mode 100644 orx-color/src/commonMain/kotlin/spaces/OKHelpers.kt create mode 100644 orx-color/src/demo/kotlin/DemoOKHSV01.kt diff --git a/orx-color/src/commonMain/kotlin/palettes/Palettes.kt b/orx-color/src/commonMain/kotlin/palettes/Palettes.kt index c8d3126a..14219894 100644 --- a/orx-color/src/commonMain/kotlin/palettes/Palettes.kt +++ b/orx-color/src/commonMain/kotlin/palettes/Palettes.kt @@ -1,7 +1,7 @@ package org.openrndr.extras.color.palettes import org.openrndr.color.* -import org.openrndr.extras.color.spaces.* +import org.openrndr.extra.color.spaces.* fun colorSequence(vararg offsets: Pair): ColorSequence diff --git a/orx-color/src/commonMain/kotlin/spaces/ColorHSLUVa.kt b/orx-color/src/commonMain/kotlin/spaces/ColorHSLUVa.kt index 0e17e70d..82d0041b 100644 --- a/orx-color/src/commonMain/kotlin/spaces/ColorHSLUVa.kt +++ b/orx-color/src/commonMain/kotlin/spaces/ColorHSLUVa.kt @@ -1,4 +1,4 @@ -package org.openrndr.extras.color.spaces +package org.openrndr.extra.color.spaces import org.openrndr.color.* import org.openrndr.math.mixAngle diff --git a/orx-color/src/commonMain/kotlin/spaces/ColorOKHSL.kt b/orx-color/src/commonMain/kotlin/spaces/ColorOKHSL.kt new file mode 100644 index 00000000..75710fcc --- /dev/null +++ b/orx-color/src/commonMain/kotlin/spaces/ColorOKHSL.kt @@ -0,0 +1,124 @@ +package org.openrndr.extra.color.spaces + +import org.openrndr.color.* +import kotlin.math.* + +data class ColorOKHSLa(val h: Double, val s: Double, val l: Double, val a: Double = 1.0) : + HueShiftableColor, + OpacifiableColor, + SaturatableColor, + ShadableColor, + ConvertibleToColorRGBa { + + companion object { + fun fromColorRGBa(c: ColorRGBa): ColorOKHSLa { + val lab = c.toOKLABa() + val C = sqrt(lab.a * lab.a + lab.b * lab.b); + val a_ = lab.a / C; + val b_ = lab.b / C; + + val L = lab.l + val h = 0.5 + 0.5 * atan2(-lab.b, -lab.a) / PI; + + val Cs = get_Cs(L, a_, b_) + val C_0 = Cs[0]; + val C_mid = Cs[1]; + val C_max = Cs[2]; + + + val s = if (C < C_mid) { + val k_0 = 0; + val k_1 = 0.8 * C_0; + val k_2 = (1 - k_1 / C_mid); + + val t = (C - k_0) / (k_1 + k_2 * (C - k_0)); + t * 0.8; + } else { + val k_0 = C_mid; + val k_1 = 0.2 * C_mid * C_mid * 1.25 * 1.25 / C_0; + val k_2 = (1 - (k_1) / (C_max - C_mid)); + + val t = (C - k_0) / (k_1 + k_2 * (C - k_0)); + 0.8 + 0.2 * t; + } + val l = toe(L); + return ColorOKHSLa(h, s, l, c.a) + } + } + + override fun toRGBa(): ColorRGBa { + if (l == 1.0) + { + ColorRGBa(1.0, 1.0, 1.0, a) + } + + else if (l == 0.0) + { + ColorRGBa(0.0, 0.0, 0.0, a) + } + val a_ = cos(2*PI*h); + val b_ = sin(2*PI*h); + val L = toe_inv(l); + + val Cs = get_Cs(L, a_, b_); + val C_0 = Cs[0]; + val C_mid = Cs[1]; + val C_max = Cs[2]; + + //let C, t, k_0, k_1, k_2; + val C: Double + val t: Double + val k_0: Double + val k_1: Double + val k_2: Double + if (s < 0.8) + { + t = 1.25*s; + k_0 = 0.0 + k_1 = 0.8*C_0; + k_2 = (1-k_1/C_mid); + } + else + { + t = 5*(s-0.8); + k_0 = C_mid; + k_1 = 0.2*C_mid*C_mid*1.25*1.25/C_0; + k_2 = (1 - (k_1)/(C_max - C_mid)); + } + + C = k_0 + t*k_1/(1-k_2*t); + + // If we would only use one of the Cs: + //C = s*C_0; + //C = s*1.25*C_mid; + //C = s*C_max; + +// let rgb = oklab_to_linear_srgb(L, C*a_, C*b_); +// return [ +// 255*srgb_transfer_function(rgb[0]), +// 255*srgb_transfer_function(rgb[1]), +// 255*srgb_transfer_function(rgb[2]), +// ] + return ColorOKLABa(L, C * a_, C * b_).toRGBa().toSRGB() + } + + override fun shiftHue(shiftInDegrees: Double): ColorOKHSLa { + val normalizedShift = shiftInDegrees / 360.0 + return copy(h = h + normalizedShift) + } + + override fun opacify(factor: Double): ColorOKHSLa { + return copy(a = a * factor) + } + + override fun saturate(factor: Double): ColorOKHSLa { + return copy(s = s * factor) + } + + override fun shade(factor: Double): ColorOKHSLa { + return copy(l = l * factor) + } + +} + +fun ColorRGBa.toOKHSLa() : ColorOKHSLa = ColorOKHSLa.fromColorRGBa(this) \ No newline at end of file diff --git a/orx-color/src/commonMain/kotlin/spaces/ColorOKHSV.kt b/orx-color/src/commonMain/kotlin/spaces/ColorOKHSV.kt new file mode 100644 index 00000000..b8950d81 --- /dev/null +++ b/orx-color/src/commonMain/kotlin/spaces/ColorOKHSV.kt @@ -0,0 +1,114 @@ +package org.openrndr.extra.color.spaces + +import org.openrndr.color.* +import kotlin.math.* + + +data class ColorOKHSVa(val h: Double, val s: Double, val v: Double, val a: Double = 1.0) : + HueShiftableColor, + OpacifiableColor, + SaturatableColor, + ShadableColor, + ConvertibleToColorRGBa { + + companion object { + fun fromColorRGBa(c: ColorRGBa): ColorOKHSVa { + val lab = c.toOKLABa() + var C = sqrt(lab.a * lab.a + lab.b * lab.b); + val a_ = lab.a / C; + val b_ = lab.b / C; + + var L = lab.l + val h = 0.5 + 0.5 * atan2(-lab.b, -lab.a) / PI; + + val ST_max = get_ST_max(a_, b_); + val S_max = ST_max[0]; + val S_0 = 0.5; + val T = ST_max[1]; + val k = 1 - S_0 / S_max; + + val t = T / (C + L * T); + val L_v = t * L; + val C_v = t * C; + + val L_vt = toe_inv(L_v); + val C_vt = C_v * L_vt / L_v; + + val rgb_scale = ColorOKLABa(L_vt, a_ * C_vt, b_ * C_vt, c.a).toRGBa().toLinear() + val scale_L = (1.0 / (max(rgb_scale.r, rgb_scale.g, rgb_scale.b, 0.0))).pow(1.0 / 3.0) + + L = L / scale_L; + C = C / scale_L; + + C = C * toe(L) / L; + L = toe(L); + + val v = L / L_v; + val s = (S_0 + T) * C_v / ((T * S_0) + T * k * C_v) + + return ColorOKHSVa(h, s, v, c.a) + } + } + + override fun toRGBa(): ColorRGBa { + val a_ = cos(2 * PI * h) + val b_ = sin(2 * PI * h) + + val ST_max = get_ST_max(a_, b_) + val S_max = ST_max[0]; + val S_0 = 0.5; + val T = ST_max[1]; + val k = 1 - S_0 / S_max; + + val L_v = 1 - s * S_0 / (S_0 + T - T * k * s) + val C_v = s * T * S_0 / (S_0 + T - T * k * s) + + var L = v * L_v; + var C = v * C_v; + + // to present steps along the way + //L = v; + //C = v*s*S_max; + //L = v*(1 - s*S_max/(S_max+T)); + //C = v*s*S_max*T/(S_max+T); + + val L_vt = toe_inv(L_v); + val C_vt = C_v * L_vt / L_v; + + val L_new = toe_inv(L); // * L_v/L_vt; + C = C * L_new / L; + L = L_new; + + val rgb_scale = + ColorOKLABa(L_vt, a_ * C_vt, b_ * C_vt, a).toRGBa().toLinear()// oklab_to_linear_srgb(L_vt,a_*C_vt,b_*C_vt); + val scale_L = (1.0 / (max(rgb_scale.r, rgb_scale.g, rgb_scale.b, 0.0))).pow(1.0 / 3.0) + + // remove to see effect without rescaling + L *= scale_L; + C *= scale_L; + + return ColorOKLABa(L, C * a_, C * b_).toRGBa().toSRGB() + + + } + + override fun shiftHue(shiftInDegrees: Double): ColorOKHSVa { + val normalizedShift = shiftInDegrees/360.0 + return copy(h = h + normalizedShift) + } + + override fun opacify(factor: Double): ColorOKHSVa { + return copy(a = a * factor) + } + + override fun saturate(factor: Double): ColorOKHSVa { + return copy(s = s * factor) + } + + override fun shade(factor: Double): ColorOKHSVa { + return copy(v = v * factor) + } + +} + +fun ColorRGBa.toOKHSVa() : ColorOKHSVa = ColorOKHSVa.fromColorRGBa(this) \ No newline at end of file diff --git a/orx-color/src/commonMain/kotlin/spaces/ColorOKLABa.kt b/orx-color/src/commonMain/kotlin/spaces/ColorOKLABa.kt index acac1269..b036af2e 100644 --- a/orx-color/src/commonMain/kotlin/spaces/ColorOKLABa.kt +++ b/orx-color/src/commonMain/kotlin/spaces/ColorOKLABa.kt @@ -1,4 +1,4 @@ -package org.openrndr.extras.color.spaces +package org.openrndr.extra.color.spaces import org.openrndr.color.* import org.openrndr.math.CastableToVector4 diff --git a/orx-color/src/commonMain/kotlin/spaces/ColorOKLCHa.kt b/orx-color/src/commonMain/kotlin/spaces/ColorOKLCHa.kt index 10b7928b..ae72796a 100644 --- a/orx-color/src/commonMain/kotlin/spaces/ColorOKLCHa.kt +++ b/orx-color/src/commonMain/kotlin/spaces/ColorOKLCHa.kt @@ -1,4 +1,4 @@ -package org.openrndr.extras.color.spaces +package org.openrndr.extra.color.spaces import org.openrndr.color.* import org.openrndr.math.asDegrees diff --git a/orx-color/src/commonMain/kotlin/spaces/OKHelpers.kt b/orx-color/src/commonMain/kotlin/spaces/OKHelpers.kt new file mode 100644 index 00000000..93d6cbff --- /dev/null +++ b/orx-color/src/commonMain/kotlin/spaces/OKHelpers.kt @@ -0,0 +1,264 @@ +package org.openrndr.extra.color.spaces + + +import kotlin.math.max +import kotlin.math.min +import kotlin.math.pow +import kotlin.math.sqrt + +// verbatim copies of https://github.com/bottosson/bottosson.github.io/blob/master/misc/colorpicker/colorconversion.js + +internal fun max(a: Double, b: Double, c: Double, d: Double): Double { + return max(max(a, b), max(c, d)) +} + + +fun toe(x: Double): Double { + val k_1 = 0.206 + val k_2 = 0.03 + val k_3 = (1 + k_1) / (1 + k_2) + + return 0.5 * (k_3 * x - k_1 + sqrt((k_3 * x - k_1) * (k_3 * x - k_1) + 4 * k_2 * k_3 * x)) +} + +fun toe_inv(x: Double): Double { + val k_1 = 0.206 + val k_2 = 0.03 + val k_3 = (1 + k_1) / (1 + k_2) + return (x * x + k_1 * x) / (k_3 * (x + k_2)) +} + +internal fun compute_max_saturation(a: Double, b: Double): Double { + // Max saturation will be when one of r, g or b goes below zero. + + // Select different coefficients depending on which component goes below zero first + val k0: Double + val k1: Double + val k2: Double + val k3: Double + val k4: Double + val wl: Double + val wm: Double + val ws: Double + + if (-1.88170328 * a - 0.80936493 * b > 1) { + // Red component + k0 = +1.19086277; k1 = +1.76576728; k2 = +0.59662641; k3 = +0.75515197; k4 = +0.56771245 + wl = +4.0767416621; wm = -3.3077115913; ws = +0.2309699292 + } else if (1.81444104 * a - 1.19445276 * b > 1) { + // Green component + k0 = +0.73956515; k1 = -0.45954404; k2 = +0.08285427; k3 = +0.12541070; k4 = +0.14503204 + wl = -1.2684380046; wm = +2.6097574011; ws = -0.3413193965 + } else { + // Blue component + k0 = +1.35733652; k1 = -0.00915799; k2 = -1.15130210; k3 = -0.50559606; k4 = +0.00692167 + wl = -0.0041960863; wm = -0.7034186147; ws = +1.7076147010 + } + + // Approximate max saturation using a polynomial: + val S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b + + // Do one step Halley's method to get closer + // this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite + // this should be sufficient for most applications, otherwise do two/three steps + + val k_l = +0.3963377774 * a + 0.2158037573 * b + val k_m = -0.1055613458 * a - 0.0638541728 * b + val k_s = -0.0894841775 * a - 1.2914855480 * b + + return run { + val l_ = 1 + S * k_l + val m_ = 1 + S * k_m + val s_ = 1 + S * k_s + + val l = l_ * l_ * l_ + val m = m_ * m_ * m_ + val s = s_ * s_ * s_ + + val l_dS = 3 * k_l * l_ * l_ + val m_dS = 3 * k_m * m_ * m_ + val s_dS = 3 * k_s * s_ * s_ + + val l_dS2 = 6 * k_l * k_l * l_ + val m_dS2 = 6 * k_m * k_m * m_ + val s_dS2 = 6 * k_s * k_s * s_ + + val f = wl * l + wm * m + ws * s + val f1 = wl * l_dS + wm * m_dS + ws * s_dS + val f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2 + + S - f * f1 / (f1 * f1 - 0.5 * f * f2) + } +} + +internal fun find_cusp(a: Double, b: Double): DoubleArray { + // First, find the maximum saturation (saturation S = C/L) + val S_cusp = compute_max_saturation(a, b) + val rgb_at_max = ColorOKLABa(1.0, S_cusp * a, S_cusp * b).toRGBa().toLinear() + val L_cusp = (1.0 / max(max(rgb_at_max.r, rgb_at_max.g), rgb_at_max.b)).pow(1.0 / 3.0) + val C_cusp = L_cusp * S_cusp + + return doubleArrayOf(L_cusp, C_cusp) +} + +internal fun get_ST_max(a: Double, b: Double, cusp: DoubleArray? = null): DoubleArray { + val cusp = cusp ?: find_cusp(a, b) + + val L = cusp[0] + val C = cusp[1] + return doubleArrayOf(C / L, C / (1.0 - L)) +} + +fun get_ST_mid(a_: Double, b_: Double): DoubleArray { + val S = 0.11516993 + 1 / ( + +7.44778970 + 4.15901240 * b_ + + a_ * (-2.19557347 + 1.75198401 * b_ + + a_ * (-2.13704948 - 10.02301043 * b_ + + a_ * (-4.24894561 + 5.38770819 * b_ + 4.69891013 * a_ + ))) + ) + + val T = 0.11239642 + 1 / ( + +1.61320320 - 0.68124379 * b_ + + a_ * (+0.40370612 + 0.90148123 * b_ + + a_ * (-0.27087943 + 0.61223990 * b_ + + a_ * (+0.00299215 - 0.45399568 * b_ - 0.14661872 * a_ + ))) + ) + + return doubleArrayOf(S, T) +} + +fun get_Cs(L: Double, a_: Double, b_: Double): DoubleArray { + val cusp = find_cusp(a_, b_) + + val C_max = find_gamut_intersection(a_, b_, L, 1.0, L, cusp) + val ST_max = get_ST_max(a_, b_, cusp) + + val S_mid = 0.11516993 + 1 / ( + +7.44778970 + 4.15901240 * b_ + + a_ * (-2.19557347 + 1.75198401 * b_ + + a_ * (-2.13704948 - 10.02301043 * b_ + + a_ * (-4.24894561 + 5.38770819 * b_ + 4.69891013 * a_ + ))) + ) + + val T_mid = 0.11239642 + 1 / ( + +1.61320320 - 0.68124379 * b_ + + a_ * (+0.40370612 + 0.90148123 * b_ + + a_ * (-0.27087943 + 0.61223990 * b_ + + a_ * (+0.00299215 - 0.45399568 * b_ - 0.14661872 * a_ + ))) + ) + + val k: Double = C_max / min((L * ST_max[0]), (1 - L) * ST_max[1]) + + val C_mid: Double + run { + val C_a = L * S_mid + val C_b = (1 - L) * T_mid + + C_mid = (0.9 * k) * sqrt(sqrt(1 / (1 / (C_a * C_a * C_a * C_a) + 1 / (C_b * C_b * C_b * C_b)))) + } + + val C_0: Double + run { + val C_a = L * 0.4 + val C_b = (1 - L) * 0.8 + + C_0 = sqrt(1 / (1 / (C_a * C_a) + 1 / (C_b * C_b))) + } + + return doubleArrayOf(C_0, C_mid, C_max) +} + +fun find_gamut_intersection( + a: Double, + b: Double, + L1: Double, + C1: Double, + L0: Double, + cusp: DoubleArray? = null +): Double { + val cusp = cusp ?: find_cusp(a, b) + + + // Find the intersection for upper and lower half seprately + var t: Double + if (((L1 - L0) * cusp[1] - (cusp[0] - L0) * C1) <= 0) { + // Lower half + + t = cusp[1] * L0 / (C1 * cusp[0] + cusp[1] * (L0 - L1)) + } else { + // Upper half + + // First intersect with triangle + t = cusp[1] * (L0 - 1) / (C1 * (cusp[0] - 1) + cusp[1] * (L0 - L1)) + + // Then one step Halley's method + run { + val dL = L1 - L0 + val dC = C1 + + val k_l = +0.3963377774 * a + 0.2158037573 * b + val k_m = -0.1055613458 * a - 0.0638541728 * b + val k_s = -0.0894841775 * a - 1.2914855480 * b + + val l_dt = dL + dC * k_l + val m_dt = dL + dC * k_m + val s_dt = dL + dC * k_s; + + + // If higher accuracy is required, 2 or 3 iterations of the following block can be used: + { + val L = L0 * (1 - t) + t * L1 + val C = t * C1 + + val l_ = L + C * k_l + val m_ = L + C * k_m + val s_ = L + C * k_s + + val l = l_ * l_ * l_ + val m = m_ * m_ * m_ + val s = s_ * s_ * s_ + + val ldt = 3 * l_dt * l_ * l_ + val mdt = 3 * m_dt * m_ * m_ + val sdt = 3 * s_dt * s_ * s_ + + val ldt2 = 6 * l_dt * l_dt * l_ + val mdt2 = 6 * m_dt * m_dt * m_ + val sdt2 = 6 * s_dt * s_dt * s_ + + val r = 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s - 1 + val r1 = 4.0767416621 * ldt - 3.3077115913 * mdt + 0.2309699292 * sdt + val r2 = 4.0767416621 * ldt2 - 3.3077115913 * mdt2 + 0.2309699292 * sdt2 + + val u_r = r1 / (r1 * r1 - 0.5 * r * r2) + var t_r = -r * u_r + + val g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s - 1 + val g1 = -1.2684380046 * ldt + 2.6097574011 * mdt - 0.3413193965 * sdt + val g2 = -1.2684380046 * ldt2 + 2.6097574011 * mdt2 - 0.3413193965 * sdt2 + + val u_g = g1 / (g1 * g1 - 0.5 * g * g2) + var t_g = -g * u_g + + val b = -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s - 1 + val b1 = -0.0041960863 * ldt - 0.7034186147 * mdt + 1.7076147010 * sdt + val b2 = -0.0041960863 * ldt2 - 0.7034186147 * mdt2 + 1.7076147010 * sdt2 + + val u_b = b1 / (b1 * b1 - 0.5 * b * b2) + var t_b = -b * u_b + + t_r = if (u_r >= 0) t_r else 10e5 + t_g = if (u_g >= 0) t_g else 10e5 + t_b = if (u_b >= 0) t_b else 10e5 + + t += min(t_r, min(t_g, t_b)) + } + } + } + + return t +} diff --git a/orx-color/src/demo/kotlin/DemoColorPlane01.kt b/orx-color/src/demo/kotlin/DemoColorPlane01.kt index d64f3815..f0842656 100644 --- a/orx-color/src/demo/kotlin/DemoColorPlane01.kt +++ b/orx-color/src/demo/kotlin/DemoColorPlane01.kt @@ -3,7 +3,7 @@ import org.openrndr.color.ColorRGBa import org.openrndr.draw.* import org.openrndr.extensions.SingleScreenshot import org.openrndr.extras.camera.Orbital -import org.openrndr.extras.color.spaces.ColorOKLCHa +import org.openrndr.extra.color.spaces.ColorOKLCHa import org.openrndr.extras.meshgenerators.sphereMesh import org.openrndr.math.Vector3 import kotlin.math.cos diff --git a/orx-color/src/demo/kotlin/DemoColorPlane02.kt b/orx-color/src/demo/kotlin/DemoColorPlane02.kt index 1f8cbe48..a22c5bcb 100644 --- a/orx-color/src/demo/kotlin/DemoColorPlane02.kt +++ b/orx-color/src/demo/kotlin/DemoColorPlane02.kt @@ -3,7 +3,7 @@ import org.openrndr.color.ColorRGBa import org.openrndr.draw.* import org.openrndr.extensions.SingleScreenshot import org.openrndr.extras.camera.Orbital -import org.openrndr.extras.color.spaces.ColorOKLCHa +import org.openrndr.extra.color.spaces.ColorOKLCHa import org.openrndr.extras.meshgenerators.sphereMesh import org.openrndr.math.Vector3 import kotlin.math.cos diff --git a/orx-color/src/demo/kotlin/DemoColorRange01.kt b/orx-color/src/demo/kotlin/DemoColorRange01.kt index 25005837..8950f61c 100644 --- a/orx-color/src/demo/kotlin/DemoColorRange01.kt +++ b/orx-color/src/demo/kotlin/DemoColorRange01.kt @@ -5,7 +5,7 @@ import org.openrndr.application import org.openrndr.color.ColorRGBa import org.openrndr.extensions.SingleScreenshot import org.openrndr.extras.color.palettes.rangeTo -import org.openrndr.extras.color.spaces.toHSLUVa +import org.openrndr.extra.color.spaces.toHSLUVa import org.openrndr.math.Vector2 import org.openrndr.math.map import org.openrndr.shape.Rectangle diff --git a/orx-color/src/demo/kotlin/DemoColorRange02.kt b/orx-color/src/demo/kotlin/DemoColorRange02.kt index 8483a0be..86a0d233 100644 --- a/orx-color/src/demo/kotlin/DemoColorRange02.kt +++ b/orx-color/src/demo/kotlin/DemoColorRange02.kt @@ -7,7 +7,7 @@ import org.openrndr.extensions.SingleScreenshot import org.openrndr.extras.color.palettes.colorSequence import org.openrndr.extras.color.palettes.rangeTo import org.openrndr.extras.color.presets.CORAL -import org.openrndr.extras.color.spaces.toHSLUVa +import org.openrndr.extra.color.spaces.toHSLUVa fun main() = application { program { diff --git a/orx-color/src/demo/kotlin/DemoColorRange03.kt b/orx-color/src/demo/kotlin/DemoColorRange03.kt index f56fddca..f4b85a18 100644 --- a/orx-color/src/demo/kotlin/DemoColorRange03.kt +++ b/orx-color/src/demo/kotlin/DemoColorRange03.kt @@ -3,10 +3,10 @@ import org.openrndr.color.ColorRGBa import org.openrndr.draw.loadFont import org.openrndr.extensions.SingleScreenshot import org.openrndr.extras.color.palettes.rangeTo -import org.openrndr.extras.color.spaces.toHSLUVa -import org.openrndr.extras.color.spaces.toOKLABa -import org.openrndr.extras.color.spaces.toOKLCHa -import org.openrndr.extras.color.spaces.toXSLUVa +import org.openrndr.extra.color.spaces.toHSLUVa +import org.openrndr.extra.color.spaces.toOKLABa +import org.openrndr.extra.color.spaces.toOKLCHa +import org.openrndr.extra.color.spaces.toXSLUVa fun main() { application { diff --git a/orx-color/src/demo/kotlin/DemoColorRange04.kt b/orx-color/src/demo/kotlin/DemoColorRange04.kt index 27d6e9ec..bb4c315b 100644 --- a/orx-color/src/demo/kotlin/DemoColorRange04.kt +++ b/orx-color/src/demo/kotlin/DemoColorRange04.kt @@ -6,10 +6,10 @@ import org.openrndr.draw.loadFont import org.openrndr.extensions.SingleScreenshot import org.openrndr.extras.camera.Orbital import org.openrndr.extras.color.palettes.rangeTo -import org.openrndr.extras.color.spaces.toHSLUVa -import org.openrndr.extras.color.spaces.toOKLABa -import org.openrndr.extras.color.spaces.toOKLCHa -import org.openrndr.extras.color.spaces.toXSLUVa +import org.openrndr.extra.color.spaces.toHSLUVa +import org.openrndr.extra.color.spaces.toOKLABa +import org.openrndr.extra.color.spaces.toOKLCHa +import org.openrndr.extra.color.spaces.toXSLUVa import org.openrndr.extras.meshgenerators.sphereMesh import org.openrndr.math.Vector3 diff --git a/orx-color/src/demo/kotlin/DemoHSLUV01.kt b/orx-color/src/demo/kotlin/DemoHSLUV01.kt index da39de35..16d9296e 100644 --- a/orx-color/src/demo/kotlin/DemoHSLUV01.kt +++ b/orx-color/src/demo/kotlin/DemoHSLUV01.kt @@ -7,7 +7,7 @@ import org.openrndr.color.rgb import org.openrndr.draw.isolated import org.openrndr.draw.loadFont import org.openrndr.extensions.SingleScreenshot -import org.openrndr.extras.color.spaces.ColorHSLUVa +import org.openrndr.extra.color.spaces.ColorHSLUVa import org.openrndr.math.Vector2 import org.openrndr.shape.Rectangle diff --git a/orx-color/src/demo/kotlin/DemoHSLUV02.kt b/orx-color/src/demo/kotlin/DemoHSLUV02.kt index 22435be3..12404e30 100644 --- a/orx-color/src/demo/kotlin/DemoHSLUV02.kt +++ b/orx-color/src/demo/kotlin/DemoHSLUV02.kt @@ -3,7 +3,7 @@ import org.openrndr.application import org.openrndr.color.ColorRGBa import org.openrndr.extensions.SingleScreenshot -import org.openrndr.extras.color.spaces.toHSLUVa +import org.openrndr.extra.color.spaces.toHSLUVa import org.openrndr.math.Polar import org.openrndr.math.Vector2 import kotlin.math.sqrt diff --git a/orx-color/src/demo/kotlin/DemoOKHSV01.kt b/orx-color/src/demo/kotlin/DemoOKHSV01.kt new file mode 100644 index 00000000..685c6b95 --- /dev/null +++ b/orx-color/src/demo/kotlin/DemoOKHSV01.kt @@ -0,0 +1,29 @@ +import org.openrndr.application +import org.openrndr.color.ColorRGBa +import org.openrndr.extra.color.spaces.ColorOKHSLa +import org.openrndr.extra.color.spaces.ColorOKHSVa + +fun main() = application { + program { + extend { + val c = ColorRGBa.GREEN + val okhsv = ColorOKHSVa.fromColorRGBa(c) + val hsv = c.toHSVa() + val hsl = c.toHSLa() + val okhsl = ColorOKHSLa.fromColorRGBa(c) + + for (i in 0 until 36) { + drawer.fill = okhsv.shiftHue(i * 10.0).saturate(1.0).toRGBa() + drawer.rectangle(i * 10.0, 40.0, 10.0, 10.0) + drawer.fill = hsv.shiftHue(i * 10.0).saturate(1.0).toRGBa() + drawer.rectangle(i * 10.0, 60.0, 10.0, 10.0) + + drawer.fill = okhsl.shiftHue(i * 10.0).saturate(1.0).toRGBa() + drawer.rectangle(i * 10.0, 80.0, 10.0, 10.0) + drawer.fill = hsl.shiftHue(i * 10.0).saturate(1.0).toRGBa() + drawer.rectangle(i * 10.0, 100.0, 10.0, 10.0) + + } + } + } +} \ No newline at end of file diff --git a/orx-color/src/demo/kotlin/DemoXSLUV01.kt b/orx-color/src/demo/kotlin/DemoXSLUV01.kt index bc4a25e5..6a6c48c4 100644 --- a/orx-color/src/demo/kotlin/DemoXSLUV01.kt +++ b/orx-color/src/demo/kotlin/DemoXSLUV01.kt @@ -3,8 +3,8 @@ import org.openrndr.application import org.openrndr.color.ColorRGBa import org.openrndr.extensions.SingleScreenshot -import org.openrndr.extras.color.spaces.ColorXSLUVa -import org.openrndr.extras.color.spaces.toHSLUVa +import org.openrndr.extra.color.spaces.ColorXSLUVa +import org.openrndr.extra.color.spaces.toHSLUVa import org.openrndr.math.Polar import org.openrndr.shape.contour