diff --git a/wpilibc/src/main/native/include/frc/util/Color.h b/wpilibc/src/main/native/include/frc/util/Color.h index 6e4d3ddb27..52be29aa3e 100644 --- a/wpilibc/src/main/native/include/frc/util/Color.h +++ b/wpilibc/src/main/native/include/frc/util/Color.h @@ -784,10 +784,10 @@ class Color { int chroma = (s * v) >> 8; // Beacuse hue is 0-180 rather than 0-360 use 30 not 60 - int region = h / 30; + int region = (h / 30) % 6; - // Remainder converted from 0-30 to roughly 0-255 - int remainder = (h - (region * 30)) * 9; + // Remainder converted from 0-30 to 0-255 + int remainder = static_cast((h % 30) * (255 / 30.0)); // Value of the lowest rgb component int m = v - chroma; diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AddressableLEDBuffer.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AddressableLEDBuffer.java index e02958aaf0..4a1a593c0b 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/AddressableLEDBuffer.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/AddressableLEDBuffer.java @@ -39,7 +39,7 @@ public class AddressableLEDBuffer { * Sets a specific led in the buffer. * * @param index the index to write - * @param h the h value [0-180] + * @param h the h value [0-180) * @param s the s value [0-255] * @param v the v value [0-255] */ @@ -49,31 +49,48 @@ public class AddressableLEDBuffer { return; } - final int region = h / 30; - final int remainder = (h - (region * 30)) * 6; + // The below algorithm is copied from Color.fromHSV and moved here for + // performance reasons. - final int p = (v * (255 - s)) >> 8; - final int q = (v * (255 - ((s * remainder) >> 8))) >> 8; - final int t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8; + // Loosely based on + // https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB + // The hue range is split into 60 degree regions where in each region there + // is one rgb component at a low value (m), one at a high value (v) and one + // that changes (X) from low to high (X+m) or high to low (v-X) + + // Difference between highest and lowest value of any rgb component + final int chroma = (s * v) / 255; + + // Beacuse hue is 0-180 rather than 0-360 use 30 not 60 + final int region = (h / 30) % 6; + + // Remainder converted from 0-30 to 0-255 + final int remainder = (int) Math.round((h % 30) * (255 / 30.0)); + + // Value of the lowest rgb component + final int m = v - chroma; + + // Goes from 0 to chroma as hue increases + final int X = (chroma * remainder) >> 8; switch (region) { case 0: - setRGB(index, v, t, p); + setRGB(index, v, X + m, m); break; case 1: - setRGB(index, q, v, p); + setRGB(index, v - X, v, m); break; case 2: - setRGB(index, p, v, t); + setRGB(index, m, v, X + m); break; case 3: - setRGB(index, p, q, v); + setRGB(index, m, v - X, v); break; case 4: - setRGB(index, t, p, v); + setRGB(index, X + m, m, v); break; default: - setRGB(index, v, p, q); + setRGB(index, v, m, v - X); break; } } diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/util/Color.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/util/Color.java index 48c166cfae..fb4685d238 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/util/Color.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/util/Color.java @@ -85,13 +85,13 @@ public class Color { // that changes (X) from low to high (X+m) or high to low (v-X) // Difference between highest and lowest value of any rgb component - final int chroma = (s * v) >> 8; + final int chroma = (s * v) / 255; // Beacuse hue is 0-180 rather than 0-360 use 30 not 60 - final int region = h / 30; + final int region = (h / 30) % 6; - // Remainder converted from 0-30 to roughly 0-255 - final int remainder = (h - (region * 30)) * 9; + // Remainder converted from 0-30 to 0-255 + final int remainder = (int) Math.round((h % 30) * (255 / 30.0)); // Value of the lowest rgb component final int m = v - chroma; diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/AddressableLEDBufferTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/AddressableLEDBufferTest.java index 6f00ba83a7..9bf5d88aeb 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/AddressableLEDBufferTest.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/AddressableLEDBufferTest.java @@ -35,16 +35,16 @@ class AddressableLEDBufferTest { arguments(0, 255, 255, 255, 0, 0), // Red arguments(60, 255, 255, 0, 255, 0), // Lime arguments(120, 255, 255, 0, 0, 255), // Blue - arguments(30, 255, 255, 254, 255, 0), // Yellow (ish) - arguments(90, 255, 255, 0, 254, 255), // Cyan (ish) - arguments(150, 255, 255, 255, 0, 254), // Magenta (ish) + arguments(30, 255, 255, 255, 255, 0), // Yellow + arguments(90, 255, 255, 0, 255, 255), // Cyan + arguments(150, 255, 255, 255, 0, 255), // Magenta arguments(0, 0, 191, 191, 191, 191), // Silver arguments(0, 0, 128, 128, 128, 128), // Gray arguments(0, 255, 128, 128, 0, 0), // Maroon - arguments(30, 255, 128, 127, 128, 0), // Olive (ish) + arguments(30, 255, 128, 128, 128, 0), // Olive arguments(60, 255, 128, 0, 128, 0), // Green - arguments(150, 255, 128, 128, 0, 127), // Purple (ish) - arguments(90, 255, 128, 0, 127, 128), // Teal (ish) + arguments(150, 255, 128, 128, 0, 128), // Purple + arguments(90, 255, 128, 0, 128, 128), // Teal arguments(120, 255, 128, 0, 0, 128) // Navy ); }