Add single color mode
[kaka/cakelight.git] / src / kaka / cakelight / Color.java
1 package kaka.cakelight;
2
3 public class Color {
4     public static final Color BLACK = Color.rgb(0, 0, 0);
5
6     private static int[] gammaCorrection = new int[256];
7
8     public static void calculateGammaCorrection(double gamma) {
9         for (int i = 0, max = 255; i <= max; i++) {
10             gammaCorrection[i] = (int)(Math.pow((double)i / max, gamma) * max);
11         }
12     }
13
14     private int r, g, b;
15
16     public static Color rgb(double r, double g, double b) {
17         return rgb((int)(255 * r), (int)(255 * g), (int)(255 * b));
18     }
19
20     public static Color rgb(int r, int g, int b) {
21         Color c = new Color();
22         c.r = r;
23         c.g = g;
24         c.b = b;
25         return c;
26     }
27
28     /**
29      * @param hue 0.0 - 1.0
30      * @param saturation 0.0 - 1.0
31      * @param value 0.0 - 1.0
32      */
33     public static Color hsv(double hue, double saturation, double value) {
34         double normalizedHue = hue - Math.floor(hue);
35         int h = (int)(normalizedHue * 6);
36         double f = normalizedHue * 6 - h;
37         double p = value * (1 - saturation);
38         double q = value * (1 - f * saturation);
39         double t = value * (1 - (1 - f) * saturation);
40
41         switch (h) {
42             case 0: return rgb(value, t, p);
43             case 1: return rgb(q, value, p);
44             case 2: return rgb(p, value, t);
45             case 3: return rgb(p, q, value);
46             case 4: return rgb(t, p, value);
47             case 5: return rgb(value, p, q);
48             default: throw new RuntimeException("Something went wrong when converting from HSV to RGB. Input was " + hue + ", " + saturation + ", " + value);
49         }
50     }
51
52     public double[] toHSV() {
53         return toHSV(r / 255.0, g / 255.0, b / 255.0);
54     }
55
56     /**
57      * @return an array with hsv values ranging from 0.0 to 1.0
58      */
59     public static double[] toHSV(double r, double g, double b) {
60         double h, s, v;
61         double min = Math.min(Math.min(r, g), b);
62         double max = Math.max(Math.max(r, g), b);
63
64         if (max == 0) {
65             return new double[] {0, 0, 0};
66         }
67
68         // Value
69         v = max;
70
71         // Saturation
72         double delta = max - min;
73         s = delta / max;
74
75         // Hue
76         if (r == max) {
77             h = (g - b) / delta; // between yellow & magenta
78         } else if (g == max) {
79             h = 2 + (b - r) / delta; // between cyan & yellow
80         } else {
81             h = 4 + (r - g) / delta; // between magenta & cyan
82         }
83
84         h /= 6.0;
85         if (h < 0)
86             h += 1;
87
88         return new double[] {h, s, v};
89     }
90
91     public int r() {
92         return gammaCorrection[r];
93     }
94
95     public int g() {
96         return gammaCorrection[g];
97     }
98
99     public int b() {
100         return gammaCorrection[b];
101     }
102
103     public Color interpolate(Color other, double value) {
104         double invertedValue = 1 - value;
105         return Color.rgb(
106                 (int)(r * invertedValue + other.r * value),
107                 (int)(g * invertedValue + other.g * value),
108                 (int)(b * invertedValue + other.b * value)
109         );
110     }
111
112     @Override
113     public String toString() {
114         return "Color{r=" + r + ", g=" + g + ", b=" + b + "}";
115     }
116 }