1 /**
2  * @file lv_color.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_color.h"
10 #include "lv_math.h"
11 
12 /*********************
13  *      DEFINES
14  *********************/
15 
16 /**********************
17  *      TYPEDEFS
18  **********************/
19 
20 /**********************
21  *  STATIC PROTOTYPES
22  **********************/
23 
24 /**********************
25  *  STATIC VARIABLES
26  **********************/
27 
28 /**********************
29  *      MACROS
30  **********************/
31 
32 /**********************
33  *   GLOBAL FUNCTIONS
34  **********************/
35 
36 /**********************
37  *   STATIC FUNCTIONS
38  **********************/
39 
lv_color_fill(lv_color_t * buf,lv_color_t color,uint32_t px_num)40 LV_ATTRIBUTE_FAST_MEM void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num)
41 {
42 #if LV_COLOR_DEPTH == 16
43     uintptr_t buf_int = (uintptr_t) buf;
44     if(buf_int & 0x3) {
45         *buf = color;
46         buf++;
47         px_num--;
48     }
49 
50     uint32_t c32 = color.full + (color.full << 16);
51     uint32_t * buf32 = (uint32_t *)buf;
52 
53     while(px_num > 16) {
54         *buf32 = c32;
55         buf32++;
56         *buf32 = c32;
57         buf32++;
58         *buf32 = c32;
59         buf32++;
60         *buf32 = c32;
61         buf32++;
62 
63         *buf32 = c32;
64         buf32++;
65         *buf32 = c32;
66         buf32++;
67         *buf32 = c32;
68         buf32++;
69         *buf32 = c32;
70         buf32++;
71 
72         px_num -= 16;
73     }
74 
75     buf = (lv_color_t *)buf32;
76 
77     while(px_num) {
78         *buf = color;
79         buf++;
80         px_num --;
81     }
82 #else
83     while(px_num > 16) {
84         *buf = color;
85         buf++;
86         *buf = color;
87         buf++;
88         *buf = color;
89         buf++;
90         *buf = color;
91         buf++;
92 
93         *buf = color;
94         buf++;
95         *buf = color;
96         buf++;
97         *buf = color;
98         buf++;
99         *buf = color;
100         buf++;
101 
102         *buf = color;
103         buf++;
104         *buf = color;
105         buf++;
106         *buf = color;
107         buf++;
108         *buf = color;
109         buf++;
110 
111         *buf = color;
112         buf++;
113         *buf = color;
114         buf++;
115         *buf = color;
116         buf++;
117         *buf = color;
118         buf++;
119 
120         px_num -= 16;
121     }
122     while(px_num) {
123         *buf = color;
124         buf++;
125         px_num --;
126     }
127 #endif
128 }
129 
130 
lv_color_lighten(lv_color_t c,lv_opa_t lvl)131 lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl)
132 {
133     return lv_color_mix(LV_COLOR_WHITE, c, lvl);
134 }
135 
136 
lv_color_darken(lv_color_t c,lv_opa_t lvl)137 lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl)
138 {
139     return lv_color_mix(LV_COLOR_BLACK, c, lvl);
140 }
141 
142 /**
143  * Convert a HSV color to RGB
144  * @param h hue [0..359]
145  * @param s saturation [0..100]
146  * @param v value [0..100]
147  * @return the given RGB color in RGB (with LV_COLOR_DEPTH depth)
148  */
lv_color_hsv_to_rgb(uint16_t h,uint8_t s,uint8_t v)149 lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v)
150 {
151     h = (uint32_t)((uint32_t)h * 255) / 360;
152     s = (uint16_t)((uint16_t)s * 255) / 100;
153     v = (uint16_t)((uint16_t)v * 255) / 100;
154 
155     uint8_t r, g, b;
156 
157     uint8_t region, remainder, p, q, t;
158 
159     if(s == 0) {
160         return lv_color_make(v, v, v);
161     }
162 
163     region    = h / 43;
164     remainder = (h - (region * 43)) * 6;
165 
166     p = (v * (255 - s)) >> 8;
167     q = (v * (255 - ((s * remainder) >> 8))) >> 8;
168     t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
169 
170     switch(region) {
171         case 0:
172             r = v;
173             g = t;
174             b = p;
175             break;
176         case 1:
177             r = q;
178             g = v;
179             b = p;
180             break;
181         case 2:
182             r = p;
183             g = v;
184             b = t;
185             break;
186         case 3:
187             r = p;
188             g = q;
189             b = v;
190             break;
191         case 4:
192             r = t;
193             g = p;
194             b = v;
195             break;
196         default:
197             r = v;
198             g = p;
199             b = q;
200             break;
201     }
202 
203     lv_color_t result = lv_color_make(r, g, b);
204     return result;
205 }
206 
207 /**
208  * Convert a 32-bit RGB color to HSV
209  * @param r8 8-bit red
210  * @param g8 8-bit green
211  * @param b8 8-bit blue
212  * @return the given RGB color in HSV
213  */
lv_color_rgb_to_hsv(uint8_t r8,uint8_t g8,uint8_t b8)214 lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8)
215 {
216     uint16_t r = ((uint32_t)r8 << 10) / 255;
217     uint16_t g = ((uint32_t)g8 << 10) / 255;
218     uint16_t b = ((uint32_t)b8 << 10) / 255;
219 
220     uint16_t rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b);
221     uint16_t rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b);
222 
223     lv_color_hsv_t hsv;
224 
225     // https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
226     hsv.v = (100 * rgbMax) >> 10;
227 
228     int32_t delta = rgbMax - rgbMin;
229     if(LV_MATH_ABS(delta) < 3) {
230         hsv.h = 0;
231         hsv.s = 0;
232         return hsv;
233     }
234 
235     // https://en.wikipedia.org/wiki/HSL_and_HSV#Saturation
236     hsv.s = 100 * delta / rgbMax;
237     if(hsv.s < 3) {
238         hsv.h = 0;
239         return hsv;
240     }
241 
242     // https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma
243     int32_t h;
244     if(rgbMax == r)
245         h = (((g - b) << 10) / delta) + (g < b ? (6 << 10) : 0); // between yellow & magenta
246     else if(rgbMax == g)
247         h = (((b - r) << 10) / delta) + (2 << 10); // between cyan & yellow
248     else if(rgbMax == b)
249         h = (((r - g) << 10) / delta) + (4 << 10); // between magenta & cyan
250     else
251         h = 0;
252     h *= 60;
253     h >>= 10;
254     if(h < 0) h += 360;
255 
256     hsv.h = h;
257     return hsv;
258 }
259 
260 /**
261  * Convert a color to HSV
262  * @param color color
263  * @return the given color in HSV
264  */
lv_color_to_hsv(lv_color_t color)265 lv_color_hsv_t lv_color_to_hsv(lv_color_t color)
266 {
267     lv_color32_t color32;
268     color32.full = lv_color_to32(color);
269     return lv_color_rgb_to_hsv(color32.ch.red, color32.ch.green, color32.ch.blue);
270 }
271