Move History

Fork Selected
  • Code
    const RGB_MAX: f64 = 255.;
    
    fn rgb_to_hsv(rgb: (u8, u8, u8)) -> (u16, u8, u8) {
        let (r, g, b) = rgb;
        let v = r.max(g).max(b) as f64 / RGB_MAX;
        if v == 0. {
            return (0, 0, 0);
        }
        let r = r as f64 / v;
        let g = g as f64 / v;
        let b = b as f64 / v;
        let s = 1. - r.min(g).min(b) as f64 / RGB_MAX;
        if s == 0. {
            return (0, 0, (v * 100.) as u8);
        }
        let hue_offset = |color| 60. * (1. - (1. - color / RGB_MAX) / s);
        let r = hue_offset(r);
        let g = hue_offset(g);
        let b = hue_offset(b);
        let peak = r.max(g).max(b);
        let h = if r == peak { // mostly red
            if g < b { 360. - b } else { 000. + g }
        } else if g == peak { // mostly green
            if b < r { 120. - r } else { 120. + b }
        } else { // mostly blue
            if r < g { 240. - g } else { 240. + r }
        };
        let h = h.round() as u16;
        let s = (s * 100.).round() as u8;
        let v = (v * 100.).round() as u8;
        let hsv = (h, s, v);
        hsv
    }
    Test Cases
    #[cfg(test)]
    mod tests {
        use super::rgb_to_hsv;
        
        #[test]
        fn rainbow() {
            assert_eq!(rgb_to_hsv((255, 000, 000)), (000, 100, 100)); // red
            assert_eq!(rgb_to_hsv((255, 128, 000)), (030, 100, 100)); // orange
            assert_eq!(rgb_to_hsv((255, 255, 000)), (060, 100, 100)); // yellow
            assert_eq!(rgb_to_hsv((000, 255, 000)), (120, 100, 100)); // green
            assert_eq!(rgb_to_hsv((000, 255, 255)), (180, 100, 100)); // cyan
            assert_eq!(rgb_to_hsv((000, 000, 255)), (240, 100, 100)); // blue
            assert_eq!(rgb_to_hsv((128, 000, 255)), (270, 100, 100)); // purple
            assert_eq!(rgb_to_hsv((255, 000, 255)), (300, 100, 100)); // magenta
        }
        
        #[test]
        fn grey() {
            assert_eq!(rgb_to_hsv((000, 000, 000)), (0, 0, 000)); // black
            assert_eq!(rgb_to_hsv((051, 051, 051)), (0, 0, 020)); // off-black
            assert_eq!(rgb_to_hsv((102, 102, 102)), (0, 0, 040)); // dark grey
            assert_eq!(rgb_to_hsv((153, 153, 153)), (0, 0, 060)); // light grey
            assert_eq!(rgb_to_hsv((204, 204, 204)), (0, 0, 080)); // off-white
            assert_eq!(rgb_to_hsv((255, 255, 255)), (0, 0, 100)); // white
        }
        
        #[test]
        fn grey_rainbow() {
            assert_eq!(rgb_to_hsv((204, 102, 102)), (000, 50, 80)); // red
            assert_eq!(rgb_to_hsv((204, 153, 102)), (030, 50, 80)); // orange
            assert_eq!(rgb_to_hsv((204, 204, 102)), (060, 50, 80)); // yellow
            assert_eq!(rgb_to_hsv((102, 204, 102)), (120, 50, 80)); // green
            assert_eq!(rgb_to_hsv((102, 204, 204)), (180, 50, 80)); // cyan
            assert_eq!(rgb_to_hsv((102, 102, 204)), (240, 50, 80)); // blue
            assert_eq!(rgb_to_hsv((153, 102, 204)), (270, 50, 80)); // purple
            assert_eq!(rgb_to_hsv((204, 102, 204)), (300, 50, 80)); // magenta
        }
    }
  • Code
    • function rgbToHsv(rgb) {
    • let r = rgb[0], g = rgb[1], b = rgb[2];
    • const v = Math.max(r, g, b) / 255;
    • if (v == 0) return Array.of(0, 0, 0);
    • r /= v;
    • g /= v;
    • b /= v;
    • const s = 1 - Math.min(r, g, b) / 255;
    • if (s == 0) return Array.of(0, 0, v * 100);
    • r = 255 - (255 - r) / s;
    • g = 255 - (255 - g) / s;
    • b = 255 - (255 - b) / s;
    • const peak = Math.max(r, g, b);
    • let h = 0;
    • if (r == peak) h = g < b ? 360 - b * 60 / 255 : g * 60 / 255;
    • else if (g == peak) h = r > b ? 120 - r * 60 / 255 : 120 + b * 60 / 255;
    • else h = r > g ? 240 + r * 60 / 255 : 240 - g * 60 / 255;
    • return Array.of(Math.round(h), Math.round(s * 100), Math.round(v * 100));
    • const RGB_MAX: f64 = 255.;
    • fn rgb_to_hsv(rgb: (u8, u8, u8)) -> (u16, u8, u8) {
    • let (r, g, b) = rgb;
    • let v = r.max(g).max(b) as f64 / RGB_MAX;
    • if v == 0. {
    • return (0, 0, 0);
    • }
    • let r = r as f64 / v;
    • let g = g as f64 / v;
    • let b = b as f64 / v;
    • let s = 1. - r.min(g).min(b) as f64 / RGB_MAX;
    • if s == 0. {
    • return (0, 0, (v * 100.) as u8);
    • }
    • let hue_offset = |color| 60. * (1. - (1. - color / RGB_MAX) / s);
    • let r = hue_offset(r);
    • let g = hue_offset(g);
    • let b = hue_offset(b);
    • let peak = r.max(g).max(b);
    • let h = if r == peak { // mostly red
    • if g < b { 360. - b } else { 000. + g }
    • } else if g == peak { // mostly green
    • if b < r { 120. - r } else { 120. + b }
    • } else { // mostly blue
    • if r < g { 240. - g } else { 240. + r }
    • };
    • let h = h.round() as u16;
    • let s = (s * 100.).round() as u8;
    • let v = (v * 100.).round() as u8;
    • let hsv = (h, s, v);
    • hsv
    • }
    Test Cases
    • const assert = require("chai").assert;
    • function arraysEqual(a, b) {
    • assert.strictEqual((a == null), (b == null));
    • assert.strictEqual(a.length, b.length);
    • for (let i = 0; i < a.length; ++i) assert.strictEqual(a[i], b[i]);
    • }
    • describe("Solution", function() {
    • it("Rainbow", function() {
    • arraysEqual(rgbToHsv(Array.of(255, 0, 0)), Array.of(0, 100, 100));
    • arraysEqual(rgbToHsv(Array.of(255, 128, 0)), Array.of(30, 100, 100));
    • arraysEqual(rgbToHsv(Array.of(255, 255, 0)), Array.of(60, 100, 100));
    • arraysEqual(rgbToHsv(Array.of(0, 255, 0)), Array.of(120, 100, 100));
    • arraysEqual(rgbToHsv(Array.of(0, 255, 255)), Array.of(180, 100, 100));
    • arraysEqual(rgbToHsv(Array.of(0, 0, 255)), Array.of(240, 100, 100));
    • arraysEqual(rgbToHsv(Array.of(128, 0, 255)), Array.of(270, 100, 100));
    • });
    • it("Grey", function() {
    • arraysEqual(rgbToHsv(Array.of(0, 0, 0)), Array.of(0, 0, 0));
    • arraysEqual(rgbToHsv(Array.of(51, 51, 51)), Array.of(0, 0, 20));
    • arraysEqual(rgbToHsv(Array.of(102, 102, 102)), Array.of(0, 0, 40));
    • arraysEqual(rgbToHsv(Array.of(153, 153, 153)), Array.of(0, 0, 60));
    • arraysEqual(rgbToHsv(Array.of(204, 204, 204)), Array.of(0, 0, 80));
    • arraysEqual(rgbToHsv(Array.of(255, 255, 255)), Array.of(0, 0, 100));
    • });
    • it("Grey_Rainbow", function() {
    • arraysEqual(rgbToHsv(Array.of(204, 102, 102)), Array.of(0, 50, 80));
    • arraysEqual(rgbToHsv(Array.of(204, 153, 102)), Array.of(30, 50, 80));
    • arraysEqual(rgbToHsv(Array.of(204, 204, 102)), Array.of(60, 50, 80));
    • arraysEqual(rgbToHsv(Array.of(102, 204, 102)), Array.of(120, 50, 80));
    • arraysEqual(rgbToHsv(Array.of(102, 204, 204)), Array.of(180, 50, 80));
    • arraysEqual(rgbToHsv(Array.of(102, 102, 204)), Array.of(240, 50, 80));
    • arraysEqual(rgbToHsv(Array.of(153, 102, 204)), Array.of(270, 50, 80));
    • });
    • });
    • #[cfg(test)]
    • mod tests {
    • use super::rgb_to_hsv;
    • #[test]
    • fn rainbow() {
    • assert_eq!(rgb_to_hsv((255, 000, 000)), (000, 100, 100)); // red
    • assert_eq!(rgb_to_hsv((255, 128, 000)), (030, 100, 100)); // orange
    • assert_eq!(rgb_to_hsv((255, 255, 000)), (060, 100, 100)); // yellow
    • assert_eq!(rgb_to_hsv((000, 255, 000)), (120, 100, 100)); // green
    • assert_eq!(rgb_to_hsv((000, 255, 255)), (180, 100, 100)); // cyan
    • assert_eq!(rgb_to_hsv((000, 000, 255)), (240, 100, 100)); // blue
    • assert_eq!(rgb_to_hsv((128, 000, 255)), (270, 100, 100)); // purple
    • assert_eq!(rgb_to_hsv((255, 000, 255)), (300, 100, 100)); // magenta
    • }
    • #[test]
    • fn grey() {
    • assert_eq!(rgb_to_hsv((000, 000, 000)), (0, 0, 000)); // black
    • assert_eq!(rgb_to_hsv((051, 051, 051)), (0, 0, 020)); // off-black
    • assert_eq!(rgb_to_hsv((102, 102, 102)), (0, 0, 040)); // dark grey
    • assert_eq!(rgb_to_hsv((153, 153, 153)), (0, 0, 060)); // light grey
    • assert_eq!(rgb_to_hsv((204, 204, 204)), (0, 0, 080)); // off-white
    • assert_eq!(rgb_to_hsv((255, 255, 255)), (0, 0, 100)); // white
    • }
    • #[test]
    • fn grey_rainbow() {
    • assert_eq!(rgb_to_hsv((204, 102, 102)), (000, 50, 80)); // red
    • assert_eq!(rgb_to_hsv((204, 153, 102)), (030, 50, 80)); // orange
    • assert_eq!(rgb_to_hsv((204, 204, 102)), (060, 50, 80)); // yellow
    • assert_eq!(rgb_to_hsv((102, 204, 102)), (120, 50, 80)); // green
    • assert_eq!(rgb_to_hsv((102, 204, 204)), (180, 50, 80)); // cyan
    • assert_eq!(rgb_to_hsv((102, 102, 204)), (240, 50, 80)); // blue
    • assert_eq!(rgb_to_hsv((153, 102, 204)), (270, 50, 80)); // purple
    • assert_eq!(rgb_to_hsv((204, 102, 204)), (300, 50, 80)); // magenta
    • }
    • }