aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/Color.java
blob: 49a66184d0e4eba9e4cf7cb41e3803466eb34b0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/**
 * @author Pacien TRAN-GIRARD
 * @author Timothée FLOURE
 */
public final class Color {

    public static final int BYTE_MASK = 0b11111111;
    public static final float DECIMAL_NORMALIZER = 255.0f;

    public static final int RED_SHIFT = 16;
    public static final int GREEN_SHIFT = 8;
    public static final int BLUE_SHIFT = 0;

    /**
     * Returns shifted component from given packed color.
     *
     * @param rgb   32-bits RGB color
     * @param shift binary shift
     * @return a float between 0.0 and 1.0
     * @see #getRGBValue
     */
    private static float getNormalizedRGBComponent(int rgb, int shift) {
        return ((float) (rgb >> shift & BYTE_MASK)) / DECIMAL_NORMALIZER;
    }

    /**
     * Returns RGB binary value from given component and color shift.
     *
     * @param component a float between 0.0 and 1.0
     * @param shift     binary shift
     * @return 32-bits RGB color
     * @see #getNormalizedRGBComponent
     */
    private static int getRGBValue(float component, int shift) {
        if (component < 0.0f) component = 0.0f;
        if (component > 1.0f) component = 1.0f;

        return ((int) (component * DECIMAL_NORMALIZER) & BYTE_MASK) << shift;
    }

    /**
     * Returns red component from given packed color.
     *
     * @param rgb 32-bits RGB color
     * @return a float between 0.0 and 1.0
     * @see #getGreen
     * @see #getBlue
     * @see #getRGB(float, float, float)
     */
    public static float getRed(int rgb) {
        return Color.getNormalizedRGBComponent(rgb, RED_SHIFT);
    }

    /**
     * Returns green component from given packed color.
     *
     * @param rgb 32-bits RGB color
     * @return a float between 0.0 and 1.0
     * @see #getRed
     * @see #getBlue
     * @see #getRGB(float, float, float)
     */
    public static float getGreen(int rgb) {
        return Color.getNormalizedRGBComponent(rgb, GREEN_SHIFT);
    }

    /**
     * Returns blue component from given packed color.
     *
     * @param rgb 32-bits RGB color
     * @return a float between 0.0 and 1.0
     * @see #getRed
     * @see #getGreen
     * @see #getRGB(float, float, float)
     */
    public static float getBlue(int rgb) {
        return Color.getNormalizedRGBComponent(rgb, BLUE_SHIFT);
    }

    /**
     * Returns the average of red, green and blue components from given packed color.
     *
     * @param rgb 32-bits RGB color
     * @return a float between 0.0 and 1.0
     * @see #getRed
     * @see #getGreen
     * @see #getBlue
     * @see #getRGB(float)
     */
    public static float getGray(int rgb) {
        return (Color.getRed(rgb) + Color.getGreen(rgb) + Color.getBlue(rgb)) / 3.0f;
    }

    /**
     * Returns packed RGB components from given red, green and blue components.
     *
     * @param red   a float between 0.0 and 1.0
     * @param green a float between 0.0 and 1.0
     * @param blue  a float between 0.0 and 1.0
     * @return 32-bits RGB color
     * @see #getRed
     * @see #getGreen
     * @see #getBlue
     */
    public static int getRGB(float red, float green, float blue) {
        int rgbValue = 0b0;
        rgbValue |= Color.getRGBValue(red, RED_SHIFT);
        rgbValue |= Color.getRGBValue(green, GREEN_SHIFT);
        rgbValue |= Color.getRGBValue(blue, BLUE_SHIFT);
        return rgbValue;
    }

    /**
     * Returns packed RGB components from given grayscale value.
     *
     * @param gray a float between 0.0 and 1.0
     * @return 32-bits RGB color
     * @see #getGray
     */
    public static int getRGB(float gray) {
        return Color.getRGB(gray, gray, gray);
    }

    /**
     * Converts packed RGB image to grayscale float image.
     *
     * @param image a HxW int array
     * @return a HxW float array
     * @see #toRGB
     * @see #getGray
     */
    public static float[][] toGray(int[][] image) {
        int width = image[0].length;
        int height = image.length;

        float[][] floatImage = new float[height][width];

        for (int row = 0; row < height; ++row)
            for (int col = 0; col < width; ++col)
                floatImage[row][col] = Color.getGray(image[row][col]);

        return floatImage;
    }

    /**
     * Converts grayscale float image to packed RGB image.
     *
     * @param gray a HxW float array
     * @return a HxW int array
     * @see #toGray
     * @see #getRGB(float)
     */
    public static int[][] toRGB(float[][] gray) {
        int width = gray[0].length;
        int height = gray.length;

        int[][] rgbImage = new int[height][width];

        for (int row = 0; row < height; ++row)
            for (int col = 0; col < width; ++col)
                rgbImage[row][col] = Color.getRGB(gray[row][col]);

        return rgbImage;
    }

}