[orx-color] Match new HueShiftableColor / SaturatableColor interfaces
This commit is contained in:
@@ -26,11 +26,15 @@ data class ColorHPLUVa(val h: Double, val s: Double, val l: Double, override val
|
|||||||
return ColorLCHUVa(l100, c100, h)
|
return ColorLCHUVa(l100, c100, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shiftHue(shiftInDegrees: Double): ColorHPLUVa = copy(h = h + (shiftInDegrees))
|
override val hue: Double = h
|
||||||
|
override fun withHue(hue: Double) = copy(h = hue)
|
||||||
|
|
||||||
|
|
||||||
override fun shade(factor: Double): ColorHPLUVa = copy(l = l * factor)
|
override fun shade(factor: Double): ColorHPLUVa = copy(l = l * factor)
|
||||||
|
|
||||||
override fun saturate(factor: Double): ColorHPLUVa = copy(s = s * factor)
|
override val saturation: Double = s
|
||||||
|
|
||||||
|
override fun withSaturation(saturation: Double): ColorHPLUVa = copy(s = saturation)
|
||||||
|
|
||||||
override fun toRGBa(): ColorRGBa = toLCHUVa().toRGBa()
|
override fun toRGBa(): ColorRGBa = toLCHUVa().toRGBa()
|
||||||
|
|
||||||
|
|||||||
@@ -114,11 +114,12 @@ data class ColorHSLUVa(val h: Double, val s: Double, val l: Double, override val
|
|||||||
return ColorXSLUVa(hueToX(h), s, l, alpha)
|
return ColorXSLUVa(hueToX(h), s, l, alpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shiftHue(shiftInDegrees: Double) = copy(h = h + (shiftInDegrees))
|
override val hue: Double =h
|
||||||
|
|
||||||
|
override fun withHue(hue: Double): ColorHSLUVa = copy(h = hue)
|
||||||
override fun shade(factor: Double) = copy(l = l * factor)
|
override fun shade(factor: Double) = copy(l = l * factor)
|
||||||
|
override val saturation: Double = s
|
||||||
override fun saturate(factor: Double) = copy(s = s * factor)
|
override fun withSaturation(saturation: Double): ColorHSLUVa = copy(s = saturation)
|
||||||
|
|
||||||
override fun toRGBa(): ColorRGBa {
|
override fun toRGBa(): ColorRGBa {
|
||||||
return toLCHUVa().toRGBa()
|
return toLCHUVa().toRGBa()
|
||||||
|
|||||||
@@ -95,11 +95,14 @@ data class ColorOKHSLa(val h: Double, val s: Double, val l: Double, override val
|
|||||||
).toRGBa().toSRGB()
|
).toRGBa().toSRGB()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shiftHue(shiftInDegrees: Double): ColorOKHSLa = copy(h = h + shiftInDegrees)
|
override val hue: Double = h
|
||||||
|
|
||||||
|
override fun withHue(hue: Double): ColorOKHSLa = copy(h = hue)
|
||||||
|
|
||||||
override fun opacify(factor: Double): ColorOKHSLa = copy(alpha = alpha * factor)
|
override fun opacify(factor: Double): ColorOKHSLa = copy(alpha = alpha * factor)
|
||||||
|
override val saturation: Double = s
|
||||||
|
|
||||||
override fun saturate(factor: Double): ColorOKHSLa = copy(s = s * factor)
|
override fun withSaturation(saturation: Double): ColorOKHSLa = copy(s = saturation)
|
||||||
|
|
||||||
override fun shade(factor: Double): ColorOKHSLa = copy(l = l * factor)
|
override fun shade(factor: Double): ColorOKHSLa = copy(l = l * factor)
|
||||||
|
|
||||||
|
|||||||
@@ -102,9 +102,14 @@ data class ColorOKHSVa(val h: Double, val s: Double, val v: Double, override val
|
|||||||
).toRGBa().toSRGB()
|
).toRGBa().toSRGB()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shiftHue(shiftInDegrees: Double): ColorOKHSVa = copy(h = h + shiftInDegrees)
|
override val hue: Double = h
|
||||||
|
|
||||||
|
override fun withHue(hue: Double): ColorOKHSVa = copy(h = hue)
|
||||||
|
|
||||||
override fun opacify(factor: Double): ColorOKHSVa = copy(alpha = alpha * factor)
|
override fun opacify(factor: Double): ColorOKHSVa = copy(alpha = alpha * factor)
|
||||||
override fun saturate(factor: Double): ColorOKHSVa = copy(s = s * factor)
|
override val saturation: Double = s
|
||||||
|
override fun withSaturation(saturation: Double): ColorOKHSVa = copy(s = saturation)
|
||||||
|
|
||||||
override fun shade(factor: Double): ColorOKHSVa = copy(v = v * factor)
|
override fun shade(factor: Double): ColorOKHSVa = copy(v = v * factor)
|
||||||
override fun minus(right: ColorOKHSVa) =
|
override fun minus(right: ColorOKHSVa) =
|
||||||
copy(h = h - right.h, s = s - right.s, v = v - right.v, alpha = alpha - right.alpha)
|
copy(h = h - right.h, s = s - right.s, v = v - right.v, alpha = alpha - right.alpha)
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import kotlin.math.*
|
|||||||
data class ColorOKLCHa(val l: Double, val c: Double, val h: Double, override val alpha: Double = 1.0) :
|
data class ColorOKLCHa(val l: Double, val c: Double, val h: Double, override val alpha: Double = 1.0) :
|
||||||
ColorModel<ColorOKLCHa>,
|
ColorModel<ColorOKLCHa>,
|
||||||
ShadableColor<ColorOKLCHa>,
|
ShadableColor<ColorOKLCHa>,
|
||||||
|
ChromaColor<ColorOKLCHa>,
|
||||||
HueShiftableColor<ColorOKLCHa>,
|
HueShiftableColor<ColorOKLCHa>,
|
||||||
SaturatableColor<ColorOKLCHa>,
|
|
||||||
AlgebraicColor<ColorOKLCHa> {
|
AlgebraicColor<ColorOKLCHa> {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -35,8 +35,6 @@ data class ColorOKLCHa(val l: Double, val c: Double, val h: Double, override val
|
|||||||
|
|
||||||
override fun opacify(factor: Double) = copy(alpha = alpha * factor)
|
override fun opacify(factor: Double) = copy(alpha = alpha * factor)
|
||||||
override fun shade(factor: Double) = copy(l = l * factor)
|
override fun shade(factor: Double) = copy(l = l * factor)
|
||||||
override fun shiftHue(shiftInDegrees: Double) = copy(h = h + shiftInDegrees)
|
|
||||||
override fun saturate(factor: Double) = copy(c = c * factor)
|
|
||||||
|
|
||||||
override fun plus(right: ColorOKLCHa) = copy(l = l + right.l, c = c + right.c, h = h + right.h, alpha = alpha + right.alpha)
|
override fun plus(right: ColorOKLCHa) = copy(l = l + right.l, c = c + right.c, h = h + right.h, alpha = alpha + right.alpha)
|
||||||
override fun minus(right: ColorOKLCHa) = copy(l = l - right.l, c = c - right.c, h = h - right.h, alpha = alpha - right.alpha)
|
override fun minus(right: ColorOKLCHa) = copy(l = l - right.l, c = c - right.c, h = h - right.h, alpha = alpha - right.alpha)
|
||||||
@@ -51,6 +49,11 @@ data class ColorOKLCHa(val l: Double, val c: Double, val h: Double, override val
|
|||||||
|
|
||||||
override fun toRGBa(): ColorRGBa = toOKLABa().toRGBa()
|
override fun toRGBa(): ColorRGBa = toOKLABa().toRGBa()
|
||||||
override fun toVector4(): Vector4 = Vector4(l, c, h, alpha)
|
override fun toVector4(): Vector4 = Vector4(l, c, h, alpha)
|
||||||
|
override val chroma: Double = c
|
||||||
|
override fun withChroma(chroma: Double): ColorOKLCHa = copy(c = chroma)
|
||||||
|
override val hue: Double = h
|
||||||
|
|
||||||
|
override fun withHue(hue: Double): ColorOKLCHa = copy(h = hue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mix(left: ColorOKLCHa, right: ColorOKLCHa, x: Double): ColorOKLCHa {
|
fun mix(left: ColorOKLCHa, right: ColorOKLCHa, x: Double): ColorOKLCHa {
|
||||||
|
|||||||
@@ -16,12 +16,13 @@ data class ColorXSLUVa(val x: Double, val s: Double, val l: Double, override val
|
|||||||
|
|
||||||
@Deprecated("Legacy alpha parameter name", ReplaceWith("alpha"))
|
@Deprecated("Legacy alpha parameter name", ReplaceWith("alpha"))
|
||||||
val a = alpha
|
val a = alpha
|
||||||
|
override val hue: Double = x
|
||||||
override fun shiftHue(shiftInDegrees: Double) = copy(x = x + (shiftInDegrees))
|
override fun withHue(hue: Double): ColorXSLUVa = copy(x = hue)
|
||||||
|
|
||||||
override fun shade(factor: Double) = copy(l = l * factor)
|
override fun shade(factor: Double) = copy(l = l * factor)
|
||||||
|
override val saturation: Double = s
|
||||||
|
|
||||||
override fun saturate(factor: Double) = copy(s = s * factor)
|
override fun withSaturation(saturation: Double): ColorXSLUVa = copy(s = saturation)
|
||||||
|
|
||||||
override fun toRGBa(): ColorRGBa = toHSLUVa().toRGBa()
|
override fun toRGBa(): ColorRGBa = toHSLUVa().toRGBa()
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,27 @@ package org.openrndr.extra.color.tools
|
|||||||
import org.openrndr.color.*
|
import org.openrndr.color.*
|
||||||
import org.openrndr.extra.color.spaces.*
|
import org.openrndr.extra.color.spaces.*
|
||||||
|
|
||||||
|
fun ColorRGBa.matchLinearity(other: ColorRGBa): ColorRGBa {
|
||||||
|
return if (other.linearity.isEquivalent(linearity)) {
|
||||||
|
this
|
||||||
|
} else {
|
||||||
|
if (other.linearity.isEquivalent(Linearity.LINEAR)) {
|
||||||
|
toLinear()
|
||||||
|
} else if (other.linearity.isEquivalent(Linearity.SRGB)) {
|
||||||
|
toSRGB()
|
||||||
|
} else {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> ColorRGBa.hue(): Double
|
||||||
|
where T : HueShiftableColor<T>,
|
||||||
|
T : ColorModel<T> = convertTo<T>().hue
|
||||||
|
|
||||||
inline fun <reified T> ColorRGBa.blendWith(other: ColorRGBa, steps: Int): Sequence<ColorRGBa>
|
inline fun <reified T> ColorRGBa.blendWith(other: ColorRGBa, steps: Int): Sequence<ColorRGBa>
|
||||||
where T : AlgebraicColor<T>,
|
where T : AlgebraicColor<T>,
|
||||||
T: ColorModel<T> {
|
T : ColorModel<T> {
|
||||||
return sequence {
|
return sequence {
|
||||||
for (step in 0 until steps) {
|
for (step in 0 until steps) {
|
||||||
yield(mixedWith<T>(other, step / (steps - 1.0)))
|
yield(mixedWith<T>(other, step / (steps - 1.0)))
|
||||||
@@ -13,6 +31,7 @@ inline fun <reified T> ColorRGBa.blendWith(other: ColorRGBa, steps: Int): Sequen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline fun <reified T : ColorModel<T>> ColorRGBa.convertTo(): T {
|
inline fun <reified T : ColorModel<T>> ColorRGBa.convertTo(): T {
|
||||||
val converted = when (T::class) {
|
val converted = when (T::class) {
|
||||||
ColorHSLa::class -> this.toHSLa()
|
ColorHSLa::class -> this.toHSLa()
|
||||||
@@ -38,61 +57,37 @@ inline fun <reified T : ColorModel<T>> ColorRGBa.convertTo(): T {
|
|||||||
return converted as T
|
return converted as T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> ColorRGBa.mixHue(hue: Double, factor: Double): ColorRGBa
|
||||||
|
where T : HueShiftableColor<T>,
|
||||||
|
T : ColorModel<T>,
|
||||||
|
T : ConvertibleToColorRGBa = convertTo<T>().mixHue(hue, factor).toRGBa().matchLinearity(this)
|
||||||
|
|
||||||
|
inline fun <reified T> ColorRGBa.withHue(hue: Double): ColorRGBa
|
||||||
|
where T : HueShiftableColor<T>,
|
||||||
|
T : ColorModel<T>,
|
||||||
|
T : ConvertibleToColorRGBa = convertTo<T>().withHue(hue).toRGBa().matchLinearity(this)
|
||||||
|
|
||||||
|
inline fun <reified T> ColorRGBa.mixSaturation(saturation: Double, factor: Double): ColorRGBa
|
||||||
|
where T : SaturatableColor<T>,
|
||||||
|
T : ColorModel<T>,
|
||||||
|
T : ConvertibleToColorRGBa =
|
||||||
|
convertTo<T>().mixSaturation(saturation, factor).toRGBa().matchLinearity(this)
|
||||||
|
|
||||||
|
|
||||||
inline fun <reified T> ColorRGBa.mixedWith(other: ColorRGBa, factor: Double): ColorRGBa
|
inline fun <reified T> ColorRGBa.mixedWith(other: ColorRGBa, factor: Double): ColorRGBa
|
||||||
where T : AlgebraicColor<T>, T : ColorModel<T> {
|
where T : AlgebraicColor<T>, T : ColorModel<T> {
|
||||||
|
|
||||||
val source = convertTo<T>()
|
val source = convertTo<T>()
|
||||||
val target = other.convertTo<T>()
|
val target = other.convertTo<T>()
|
||||||
val mixed = source.mix(target, factor).toRGBa()
|
return source.mix(target, factor).toRGBa().matchLinearity(this)
|
||||||
|
|
||||||
return if (mixed.linearity.isEquivalent(linearity)) {
|
|
||||||
mixed
|
|
||||||
} else {
|
|
||||||
if (linearity.isEquivalent(Linearity.LINEAR)) {
|
|
||||||
mixed.toLinear()
|
|
||||||
} else if (linearity.isEquivalent(Linearity.SRGB)) {
|
|
||||||
mixed.toSRGB()
|
|
||||||
} else {
|
|
||||||
mixed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T> ColorRGBa.saturate(factor: Double): ColorRGBa
|
inline fun <reified T> ColorRGBa.saturate(factor: Double): ColorRGBa
|
||||||
where T : SaturatableColor<T>,
|
where T : SaturatableColor<T>,
|
||||||
T : ColorModel<T>,
|
T : ColorModel<T>,
|
||||||
T : ConvertibleToColorRGBa {
|
T : ConvertibleToColorRGBa = convertTo<T>().saturate(factor).toRGBa().matchLinearity(this)
|
||||||
|
|
||||||
val saturated = convertTo<T>().saturate(factor).toRGBa()
|
|
||||||
return if (saturated.linearity.isEquivalent(linearity)) {
|
|
||||||
saturated
|
|
||||||
} else {
|
|
||||||
if (linearity.isEquivalent(Linearity.LINEAR)) {
|
|
||||||
saturated.toLinear()
|
|
||||||
} else if (linearity.isEquivalent(Linearity.SRGB)) {
|
|
||||||
saturated.toSRGB()
|
|
||||||
} else {
|
|
||||||
saturated
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T> ColorRGBa.shiftHue(degrees: Double): ColorRGBa where
|
inline fun <reified T> ColorRGBa.shiftHue(degrees: Double): ColorRGBa where
|
||||||
T : HueShiftableColor<T>,
|
T : HueShiftableColor<T>,
|
||||||
T : ColorModel<T>,
|
T : ColorModel<T>,
|
||||||
T : ConvertibleToColorRGBa {
|
T : ConvertibleToColorRGBa = convertTo<T>().shiftHue(degrees).toRGBa().matchLinearity(this)
|
||||||
val converted = convertTo<T>()
|
|
||||||
val shifted = (converted.shiftHue(degrees) as ConvertibleToColorRGBa).toRGBa()
|
|
||||||
return if (shifted.linearity.isEquivalent(linearity)) {
|
|
||||||
shifted
|
|
||||||
} else {
|
|
||||||
if (linearity.isEquivalent(Linearity.LINEAR)) {
|
|
||||||
shifted.toLinear()
|
|
||||||
} else if (linearity.isEquivalent(Linearity.SRGB)) {
|
|
||||||
shifted.toSRGB()
|
|
||||||
} else {
|
|
||||||
shifted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ fun main() {
|
|||||||
configure {
|
configure {
|
||||||
width = 800
|
width = 800
|
||||||
height = 800
|
height = 800
|
||||||
|
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
val mesh = sphereMesh(8, 8, radius = 0.1)
|
val mesh = sphereMesh(8, 8, radius = 0.1)
|
||||||
|
|||||||
44
orx-color/src/jvmDemo/kotlin/DemoHueTools01.kt
Normal file
44
orx-color/src/jvmDemo/kotlin/DemoHueTools01.kt
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.draw.isolated
|
||||||
|
import org.openrndr.extra.color.presets.NAVY
|
||||||
|
import org.openrndr.extra.color.spaces.OKHSV
|
||||||
|
import org.openrndr.extra.color.tools.hue
|
||||||
|
import org.openrndr.extra.color.tools.mixHue
|
||||||
|
import org.openrndr.extra.color.tools.withHue
|
||||||
|
import kotlin.math.cos
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
application {
|
||||||
|
configure {
|
||||||
|
width = 800
|
||||||
|
height = 800
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
extend {
|
||||||
|
val seedColor = ColorRGBa.PINK
|
||||||
|
val targetHue = seconds*100.0
|
||||||
|
|
||||||
|
val rows = 10
|
||||||
|
val columns = 12
|
||||||
|
|
||||||
|
val cellWidth = width / columns.toDouble()
|
||||||
|
val cellHeight = height / rows.toDouble()
|
||||||
|
|
||||||
|
drawer.stroke = null
|
||||||
|
for (j in 0 until 10) {
|
||||||
|
drawer.isolated {
|
||||||
|
for (i in 0 until columns) {
|
||||||
|
drawer.fill = seedColor
|
||||||
|
.withHue<OKHSV>(i * 360.0 / columns)
|
||||||
|
.mixHue<OKHSV>(targetHue, j / (rows.toDouble()-1.0))
|
||||||
|
drawer.rectangle(0.0, 0.0, cellWidth, cellHeight)
|
||||||
|
drawer.translate(cellWidth, 0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawer.translate(0.0, cellHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user