1 /**
2  * @file lv_color.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_color.h"
10 #include "lv_log.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 
lv_color_fill(lv_color_t * buf,lv_color_t color,uint32_t px_num)36 void LV_ATTRIBUTE_FAST_MEM lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num)
37 {
38 #if LV_COLOR_DEPTH == 16
39     uintptr_t buf_int = (uintptr_t)buf;
40     if(buf_int & 0x3) {
41         *buf = color;
42         buf++;
43         px_num--;
44     }
45 
46     uint32_t c32 = (uint32_t)color.full + ((uint32_t)color.full << 16);
47     uint32_t * buf32 = (uint32_t *)buf;
48 
49     while(px_num > 16) {
50         *buf32 = c32;
51         buf32++;
52         *buf32 = c32;
53         buf32++;
54         *buf32 = c32;
55         buf32++;
56         *buf32 = c32;
57         buf32++;
58 
59         *buf32 = c32;
60         buf32++;
61         *buf32 = c32;
62         buf32++;
63         *buf32 = c32;
64         buf32++;
65         *buf32 = c32;
66         buf32++;
67 
68         px_num -= 16;
69     }
70 
71     buf = (lv_color_t *)buf32;
72 
73     while(px_num) {
74         *buf = color;
75         buf++;
76         px_num--;
77     }
78 #else
79     while(px_num > 16) {
80         *buf = color;
81         buf++;
82         *buf = color;
83         buf++;
84         *buf = color;
85         buf++;
86         *buf = color;
87         buf++;
88 
89         *buf = color;
90         buf++;
91         *buf = color;
92         buf++;
93         *buf = color;
94         buf++;
95         *buf = color;
96         buf++;
97 
98         *buf = color;
99         buf++;
100         *buf = color;
101         buf++;
102         *buf = color;
103         buf++;
104         *buf = color;
105         buf++;
106 
107         *buf = color;
108         buf++;
109         *buf = color;
110         buf++;
111         *buf = color;
112         buf++;
113         *buf = color;
114         buf++;
115 
116         px_num -= 16;
117     }
118     while(px_num) {
119         *buf = color;
120         buf++;
121         px_num--;
122     }
123 #endif
124 }
125 
lv_color_lighten(lv_color_t c,lv_opa_t lvl)126 lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl)
127 {
128     return lv_color_mix(lv_color_white(), c, lvl);
129 }
130 
lv_color_darken(lv_color_t c,lv_opa_t lvl)131 lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl)
132 {
133     return lv_color_mix(lv_color_black(), c, lvl);
134 }
135 
lv_color_change_lightness(lv_color_t c,lv_opa_t lvl)136 lv_color_t lv_color_change_lightness(lv_color_t c, lv_opa_t lvl)
137 {
138     /*It'd be better to convert the color to HSL, change L and convert back to RGB.*/
139     if(lvl == LV_OPA_50) return c;
140     else if(lvl < LV_OPA_50) return lv_color_darken(c, (LV_OPA_50 - lvl) * 2);
141     else return lv_color_lighten(c, (lvl - LV_OPA_50) * 2);
142 }
143 
144 /**
145  * Convert a HSV color to RGB
146  * @param h hue [0..359]
147  * @param s saturation [0..100]
148  * @param v value [0..100]
149  * @return the given RGB color in RGB (with LV_COLOR_DEPTH depth)
150  */
lv_color_hsv_to_rgb(uint16_t h,uint8_t s,uint8_t v)151 lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v)
152 {
153     h = (uint32_t)((uint32_t)h * 255) / 360;
154     s = (uint16_t)((uint16_t)s * 255) / 100;
155     v = (uint16_t)((uint16_t)v * 255) / 100;
156 
157     uint8_t r, g, b;
158 
159     uint8_t region, remainder, p, q, t;
160 
161     if(s == 0) {
162         return lv_color_make(v, v, v);
163     }
164 
165     region    = h / 43;
166     remainder = (h - (region * 43)) * 6;
167 
168     p = (v * (255 - s)) >> 8;
169     q = (v * (255 - ((s * remainder) >> 8))) >> 8;
170     t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
171 
172     switch(region) {
173         case 0:
174             r = v;
175             g = t;
176             b = p;
177             break;
178         case 1:
179             r = q;
180             g = v;
181             b = p;
182             break;
183         case 2:
184             r = p;
185             g = v;
186             b = t;
187             break;
188         case 3:
189             r = p;
190             g = q;
191             b = v;
192             break;
193         case 4:
194             r = t;
195             g = p;
196             b = v;
197             break;
198         default:
199             r = v;
200             g = p;
201             b = q;
202             break;
203     }
204 
205     lv_color_t result = lv_color_make(r, g, b);
206     return result;
207 }
208 
209 /**
210  * Convert a 32-bit RGB color to HSV
211  * @param r8 8-bit red
212  * @param g8 8-bit green
213  * @param b8 8-bit blue
214  * @return the given RGB color in HSV
215  */
lv_color_rgb_to_hsv(uint8_t r8,uint8_t g8,uint8_t b8)216 lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8)
217 {
218     uint16_t r = ((uint32_t)r8 << 10) / 255;
219     uint16_t g = ((uint32_t)g8 << 10) / 255;
220     uint16_t b = ((uint32_t)b8 << 10) / 255;
221 
222     uint16_t rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b);
223     uint16_t rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b);
224 
225     lv_color_hsv_t hsv;
226 
227     // https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
228     hsv.v = (100 * rgbMax) >> 10;
229 
230     int32_t delta = rgbMax - rgbMin;
231     if(delta < 3) {
232         hsv.h = 0;
233         hsv.s = 0;
234         return hsv;
235     }
236 
237     // https://en.wikipedia.org/wiki/HSL_and_HSV#Saturation
238     hsv.s = 100 * delta / rgbMax;
239     if(hsv.s < 3) {
240         hsv.h = 0;
241         return hsv;
242     }
243 
244     // https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma
245     int32_t h;
246     if(rgbMax == r)
247         h = (((g - b) << 10) / delta) + (g < b ? (6 << 10) : 0); // between yellow & magenta
248     else if(rgbMax == g)
249         h = (((b - r) << 10) / delta) + (2 << 10); // between cyan & yellow
250     else if(rgbMax == b)
251         h = (((r - g) << 10) / delta) + (4 << 10); // between magenta & cyan
252     else
253         h = 0;
254     h *= 60;
255     h >>= 10;
256     if(h < 0) h += 360;
257 
258     hsv.h = h;
259     return hsv;
260 }
261 
262 /**
263  * Convert a color to HSV
264  * @param color color
265  * @return the given color in HSV
266  */
lv_color_to_hsv(lv_color_t color)267 lv_color_hsv_t lv_color_to_hsv(lv_color_t color)
268 {
269     lv_color32_t color32;
270     color32.full = lv_color_to32(color);
271     return lv_color_rgb_to_hsv(color32.ch.red, color32.ch.green, color32.ch.blue);
272 }
273 
lv_palette_main(lv_palette_t p)274 lv_color_t lv_palette_main(lv_palette_t p)
275 {
276     static const lv_color_t colors[] = {
277         LV_COLOR_MAKE(0xF4, 0x43, 0x36), LV_COLOR_MAKE(0xE9, 0x1E, 0x63), LV_COLOR_MAKE(0x9C, 0x27, 0xB0), LV_COLOR_MAKE(0x67, 0x3A, 0xB7),
278         LV_COLOR_MAKE(0x3F, 0x51, 0xB5), LV_COLOR_MAKE(0x21, 0x96, 0xF3), LV_COLOR_MAKE(0x03, 0xA9, 0xF4), LV_COLOR_MAKE(0x00, 0xBC, 0xD4),
279         LV_COLOR_MAKE(0x00, 0x96, 0x88), LV_COLOR_MAKE(0x4C, 0xAF, 0x50), LV_COLOR_MAKE(0x8B, 0xC3, 0x4A), LV_COLOR_MAKE(0xCD, 0xDC, 0x39),
280         LV_COLOR_MAKE(0xFF, 0xEB, 0x3B), LV_COLOR_MAKE(0xFF, 0xC1, 0x07), LV_COLOR_MAKE(0xFF, 0x98, 0x00), LV_COLOR_MAKE(0xFF, 0x57, 0x22),
281         LV_COLOR_MAKE(0x79, 0x55, 0x48), LV_COLOR_MAKE(0x60, 0x7D, 0x8B), LV_COLOR_MAKE(0x9E, 0x9E, 0x9E)
282     };
283 
284     if(p >= _LV_PALETTE_LAST) {
285         LV_LOG_WARN("Invalid palette: %d", p);
286         return lv_color_black();
287     }
288 
289     return colors[p];
290 
291 }
292 
lv_palette_lighten(lv_palette_t p,uint8_t lvl)293 lv_color_t lv_palette_lighten(lv_palette_t p, uint8_t lvl)
294 {
295     static const lv_color_t colors[][5] = {
296         {LV_COLOR_MAKE(0xEF, 0x53, 0x50), LV_COLOR_MAKE(0xE5, 0x73, 0x73), LV_COLOR_MAKE(0xEF, 0x9A, 0x9A), LV_COLOR_MAKE(0xFF, 0xCD, 0xD2), LV_COLOR_MAKE(0xFF, 0xEB, 0xEE)},
297         {LV_COLOR_MAKE(0xEC, 0x40, 0x7A), LV_COLOR_MAKE(0xF0, 0x62, 0x92), LV_COLOR_MAKE(0xF4, 0x8F, 0xB1), LV_COLOR_MAKE(0xF8, 0xBB, 0xD0), LV_COLOR_MAKE(0xFC, 0xE4, 0xEC)},
298         {LV_COLOR_MAKE(0xAB, 0x47, 0xBC), LV_COLOR_MAKE(0xBA, 0x68, 0xC8), LV_COLOR_MAKE(0xCE, 0x93, 0xD8), LV_COLOR_MAKE(0xE1, 0xBE, 0xE7), LV_COLOR_MAKE(0xF3, 0xE5, 0xF5)},
299         {LV_COLOR_MAKE(0x7E, 0x57, 0xC2), LV_COLOR_MAKE(0x95, 0x75, 0xCD), LV_COLOR_MAKE(0xB3, 0x9D, 0xDB), LV_COLOR_MAKE(0xD1, 0xC4, 0xE9), LV_COLOR_MAKE(0xED, 0xE7, 0xF6)},
300         {LV_COLOR_MAKE(0x5C, 0x6B, 0xC0), LV_COLOR_MAKE(0x79, 0x86, 0xCB), LV_COLOR_MAKE(0x9F, 0xA8, 0xDA), LV_COLOR_MAKE(0xC5, 0xCA, 0xE9), LV_COLOR_MAKE(0xE8, 0xEA, 0xF6)},
301         {LV_COLOR_MAKE(0x42, 0xA5, 0xF5), LV_COLOR_MAKE(0x64, 0xB5, 0xF6), LV_COLOR_MAKE(0x90, 0xCA, 0xF9), LV_COLOR_MAKE(0xBB, 0xDE, 0xFB), LV_COLOR_MAKE(0xE3, 0xF2, 0xFD)},
302         {LV_COLOR_MAKE(0x29, 0xB6, 0xF6), LV_COLOR_MAKE(0x4F, 0xC3, 0xF7), LV_COLOR_MAKE(0x81, 0xD4, 0xFA), LV_COLOR_MAKE(0xB3, 0xE5, 0xFC), LV_COLOR_MAKE(0xE1, 0xF5, 0xFE)},
303         {LV_COLOR_MAKE(0x26, 0xC6, 0xDA), LV_COLOR_MAKE(0x4D, 0xD0, 0xE1), LV_COLOR_MAKE(0x80, 0xDE, 0xEA), LV_COLOR_MAKE(0xB2, 0xEB, 0xF2), LV_COLOR_MAKE(0xE0, 0xF7, 0xFA)},
304         {LV_COLOR_MAKE(0x26, 0xA6, 0x9A), LV_COLOR_MAKE(0x4D, 0xB6, 0xAC), LV_COLOR_MAKE(0x80, 0xCB, 0xC4), LV_COLOR_MAKE(0xB2, 0xDF, 0xDB), LV_COLOR_MAKE(0xE0, 0xF2, 0xF1)},
305         {LV_COLOR_MAKE(0x66, 0xBB, 0x6A), LV_COLOR_MAKE(0x81, 0xC7, 0x84), LV_COLOR_MAKE(0xA5, 0xD6, 0xA7), LV_COLOR_MAKE(0xC8, 0xE6, 0xC9), LV_COLOR_MAKE(0xE8, 0xF5, 0xE9)},
306         {LV_COLOR_MAKE(0x9C, 0xCC, 0x65), LV_COLOR_MAKE(0xAE, 0xD5, 0x81), LV_COLOR_MAKE(0xC5, 0xE1, 0xA5), LV_COLOR_MAKE(0xDC, 0xED, 0xC8), LV_COLOR_MAKE(0xF1, 0xF8, 0xE9)},
307         {LV_COLOR_MAKE(0xD4, 0xE1, 0x57), LV_COLOR_MAKE(0xDC, 0xE7, 0x75), LV_COLOR_MAKE(0xE6, 0xEE, 0x9C), LV_COLOR_MAKE(0xF0, 0xF4, 0xC3), LV_COLOR_MAKE(0xF9, 0xFB, 0xE7)},
308         {LV_COLOR_MAKE(0xFF, 0xEE, 0x58), LV_COLOR_MAKE(0xFF, 0xF1, 0x76), LV_COLOR_MAKE(0xFF, 0xF5, 0x9D), LV_COLOR_MAKE(0xFF, 0xF9, 0xC4), LV_COLOR_MAKE(0xFF, 0xFD, 0xE7)},
309         {LV_COLOR_MAKE(0xFF, 0xCA, 0x28), LV_COLOR_MAKE(0xFF, 0xD5, 0x4F), LV_COLOR_MAKE(0xFF, 0xE0, 0x82), LV_COLOR_MAKE(0xFF, 0xEC, 0xB3), LV_COLOR_MAKE(0xFF, 0xF8, 0xE1)},
310         {LV_COLOR_MAKE(0xFF, 0xA7, 0x26), LV_COLOR_MAKE(0xFF, 0xB7, 0x4D), LV_COLOR_MAKE(0xFF, 0xCC, 0x80), LV_COLOR_MAKE(0xFF, 0xE0, 0xB2), LV_COLOR_MAKE(0xFF, 0xF3, 0xE0)},
311         {LV_COLOR_MAKE(0xFF, 0x70, 0x43), LV_COLOR_MAKE(0xFF, 0x8A, 0x65), LV_COLOR_MAKE(0xFF, 0xAB, 0x91), LV_COLOR_MAKE(0xFF, 0xCC, 0xBC), LV_COLOR_MAKE(0xFB, 0xE9, 0xE7)},
312         {LV_COLOR_MAKE(0x8D, 0x6E, 0x63), LV_COLOR_MAKE(0xA1, 0x88, 0x7F), LV_COLOR_MAKE(0xBC, 0xAA, 0xA4), LV_COLOR_MAKE(0xD7, 0xCC, 0xC8), LV_COLOR_MAKE(0xEF, 0xEB, 0xE9)},
313         {LV_COLOR_MAKE(0x78, 0x90, 0x9C), LV_COLOR_MAKE(0x90, 0xA4, 0xAE), LV_COLOR_MAKE(0xB0, 0xBE, 0xC5), LV_COLOR_MAKE(0xCF, 0xD8, 0xDC), LV_COLOR_MAKE(0xEC, 0xEF, 0xF1)},
314         {LV_COLOR_MAKE(0xBD, 0xBD, 0xBD), LV_COLOR_MAKE(0xE0, 0xE0, 0xE0), LV_COLOR_MAKE(0xEE, 0xEE, 0xEE), LV_COLOR_MAKE(0xF5, 0xF5, 0xF5), LV_COLOR_MAKE(0xFA, 0xFA, 0xFA)},
315     };
316 
317     if(p >= _LV_PALETTE_LAST) {
318         LV_LOG_WARN("Invalid palette: %d", p);
319         return lv_color_black();
320     }
321 
322     if(lvl == 0 || lvl > 5) {
323         LV_LOG_WARN("Invalid level: %d. Must be 1..5", lvl);
324         return lv_color_black();
325     }
326 
327     lvl--;
328 
329     return colors[p][lvl];
330 }
331 
lv_palette_darken(lv_palette_t p,uint8_t lvl)332 lv_color_t lv_palette_darken(lv_palette_t p, uint8_t lvl)
333 {
334     static const lv_color_t colors[][4] = {
335         {LV_COLOR_MAKE(0xE5, 0x39, 0x35), LV_COLOR_MAKE(0xD3, 0x2F, 0x2F), LV_COLOR_MAKE(0xC6, 0x28, 0x28), LV_COLOR_MAKE(0xB7, 0x1C, 0x1C)},
336         {LV_COLOR_MAKE(0xD8, 0x1B, 0x60), LV_COLOR_MAKE(0xC2, 0x18, 0x5B), LV_COLOR_MAKE(0xAD, 0x14, 0x57), LV_COLOR_MAKE(0x88, 0x0E, 0x4F)},
337         {LV_COLOR_MAKE(0x8E, 0x24, 0xAA), LV_COLOR_MAKE(0x7B, 0x1F, 0xA2), LV_COLOR_MAKE(0x6A, 0x1B, 0x9A), LV_COLOR_MAKE(0x4A, 0x14, 0x8C)},
338         {LV_COLOR_MAKE(0x5E, 0x35, 0xB1), LV_COLOR_MAKE(0x51, 0x2D, 0xA8), LV_COLOR_MAKE(0x45, 0x27, 0xA0), LV_COLOR_MAKE(0x31, 0x1B, 0x92)},
339         {LV_COLOR_MAKE(0x39, 0x49, 0xAB), LV_COLOR_MAKE(0x30, 0x3F, 0x9F), LV_COLOR_MAKE(0x28, 0x35, 0x93), LV_COLOR_MAKE(0x1A, 0x23, 0x7E)},
340         {LV_COLOR_MAKE(0x1E, 0x88, 0xE5), LV_COLOR_MAKE(0x19, 0x76, 0xD2), LV_COLOR_MAKE(0x15, 0x65, 0xC0), LV_COLOR_MAKE(0x0D, 0x47, 0xA1)},
341         {LV_COLOR_MAKE(0x03, 0x9B, 0xE5), LV_COLOR_MAKE(0x02, 0x88, 0xD1), LV_COLOR_MAKE(0x02, 0x77, 0xBD), LV_COLOR_MAKE(0x01, 0x57, 0x9B)},
342         {LV_COLOR_MAKE(0x00, 0xAC, 0xC1), LV_COLOR_MAKE(0x00, 0x97, 0xA7), LV_COLOR_MAKE(0x00, 0x83, 0x8F), LV_COLOR_MAKE(0x00, 0x60, 0x64)},
343         {LV_COLOR_MAKE(0x00, 0x89, 0x7B), LV_COLOR_MAKE(0x00, 0x79, 0x6B), LV_COLOR_MAKE(0x00, 0x69, 0x5C), LV_COLOR_MAKE(0x00, 0x4D, 0x40)},
344         {LV_COLOR_MAKE(0x43, 0xA0, 0x47), LV_COLOR_MAKE(0x38, 0x8E, 0x3C), LV_COLOR_MAKE(0x2E, 0x7D, 0x32), LV_COLOR_MAKE(0x1B, 0x5E, 0x20)},
345         {LV_COLOR_MAKE(0x7C, 0xB3, 0x42), LV_COLOR_MAKE(0x68, 0x9F, 0x38), LV_COLOR_MAKE(0x55, 0x8B, 0x2F), LV_COLOR_MAKE(0x33, 0x69, 0x1E)},
346         {LV_COLOR_MAKE(0xC0, 0xCA, 0x33), LV_COLOR_MAKE(0xAF, 0xB4, 0x2B), LV_COLOR_MAKE(0x9E, 0x9D, 0x24), LV_COLOR_MAKE(0x82, 0x77, 0x17)},
347         {LV_COLOR_MAKE(0xFD, 0xD8, 0x35), LV_COLOR_MAKE(0xFB, 0xC0, 0x2D), LV_COLOR_MAKE(0xF9, 0xA8, 0x25), LV_COLOR_MAKE(0xF5, 0x7F, 0x17)},
348         {LV_COLOR_MAKE(0xFF, 0xB3, 0x00), LV_COLOR_MAKE(0xFF, 0xA0, 0x00), LV_COLOR_MAKE(0xFF, 0x8F, 0x00), LV_COLOR_MAKE(0xFF, 0x6F, 0x00)},
349         {LV_COLOR_MAKE(0xFB, 0x8C, 0x00), LV_COLOR_MAKE(0xF5, 0x7C, 0x00), LV_COLOR_MAKE(0xEF, 0x6C, 0x00), LV_COLOR_MAKE(0xE6, 0x51, 0x00)},
350         {LV_COLOR_MAKE(0xF4, 0x51, 0x1E), LV_COLOR_MAKE(0xE6, 0x4A, 0x19), LV_COLOR_MAKE(0xD8, 0x43, 0x15), LV_COLOR_MAKE(0xBF, 0x36, 0x0C)},
351         {LV_COLOR_MAKE(0x6D, 0x4C, 0x41), LV_COLOR_MAKE(0x5D, 0x40, 0x37), LV_COLOR_MAKE(0x4E, 0x34, 0x2E), LV_COLOR_MAKE(0x3E, 0x27, 0x23)},
352         {LV_COLOR_MAKE(0x54, 0x6E, 0x7A), LV_COLOR_MAKE(0x45, 0x5A, 0x64), LV_COLOR_MAKE(0x37, 0x47, 0x4F), LV_COLOR_MAKE(0x26, 0x32, 0x38)},
353         {LV_COLOR_MAKE(0x75, 0x75, 0x75), LV_COLOR_MAKE(0x61, 0x61, 0x61), LV_COLOR_MAKE(0x42, 0x42, 0x42), LV_COLOR_MAKE(0x21, 0x21, 0x21)},
354     };
355 
356     if(p >= _LV_PALETTE_LAST) {
357         LV_LOG_WARN("Invalid palette: %d", p);
358         return lv_color_black();
359     }
360 
361     if(lvl == 0 || lvl > 4) {
362         LV_LOG_WARN("Invalid level: %d. Must be 1..4", lvl);
363         return lv_color_black();
364     }
365 
366     lvl--;
367 
368     return colors[p][lvl];
369 }
370