1 /**
2  * @file lv_color.h
3  *
4  */
5 
6 #ifndef LV_COLOR_H
7 #define LV_COLOR_H
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 /*********************
14  *      INCLUDES
15  *********************/
16 #ifdef LV_CONF_INCLUDE_SIMPLE
17 #include "lv_conf.h"
18 #else
19 #include "../../lv_conf.h"
20 #endif
21 
22 /*Error checking*/
23 #if LV_COLOR_DEPTH == 24
24 #error "LV_COLOR_DEPTH  24 is deprecated. Use LV_COLOR_DEPTH  32 instead (lv_conf.h)"
25 #endif
26 
27 #if LV_COLOR_DEPTH != 32 && LV_COLOR_SCREEN_TRANSP != 0
28 #error "LV_COLOR_SCREEN_TRANSP requires LV_COLOR_DEPTH == 32. Set it in lv_conf.h"
29 #endif
30 
31 #if LV_COLOR_DEPTH != 16 && LV_COLOR_16_SWAP != 0
32 #error "LV_COLOR_16_SWAP requires LV_COLOR_DEPTH == 16. Set it in lv_conf.h"
33 #endif
34 
35 #include <stdint.h>
36 
37 /*********************
38  *      DEFINES
39  *********************/
40 #define LV_COLOR_WHITE LV_COLOR_MAKE(0xFF, 0xFF, 0xFF)
41 #define LV_COLOR_SILVER LV_COLOR_MAKE(0xC0, 0xC0, 0xC0)
42 #define LV_COLOR_GRAY LV_COLOR_MAKE(0x80, 0x80, 0x80)
43 #define LV_COLOR_BLACK LV_COLOR_MAKE(0x00, 0x00, 0x00)
44 #define LV_COLOR_RED LV_COLOR_MAKE(0xFF, 0x00, 0x00)
45 #define LV_COLOR_MAROON LV_COLOR_MAKE(0x80, 0x00, 0x00)
46 #define LV_COLOR_YELLOW LV_COLOR_MAKE(0xFF, 0xFF, 0x00)
47 #define LV_COLOR_OLIVE LV_COLOR_MAKE(0x80, 0x80, 0x00)
48 #define LV_COLOR_LIME LV_COLOR_MAKE(0x00, 0xFF, 0x00)
49 #define LV_COLOR_GREEN LV_COLOR_MAKE(0x00, 0x80, 0x00)
50 #define LV_COLOR_CYAN LV_COLOR_MAKE(0x00, 0xFF, 0xFF)
51 #define LV_COLOR_AQUA LV_COLOR_CYAN
52 #define LV_COLOR_TEAL LV_COLOR_MAKE(0x00, 0x80, 0x80)
53 #define LV_COLOR_BLUE LV_COLOR_MAKE(0x00, 0x00, 0xFF)
54 #define LV_COLOR_NAVY LV_COLOR_MAKE(0x00, 0x00, 0x80)
55 #define LV_COLOR_MAGENTA LV_COLOR_MAKE(0xFF, 0x00, 0xFF)
56 #define LV_COLOR_PURPLE LV_COLOR_MAKE(0x80, 0x00, 0x80)
57 #define LV_COLOR_ORANGE LV_COLOR_MAKE(0xFF, 0xA5, 0x00)
58 
59 /**
60  * Opacity percentages.
61  */
62 enum {
63     LV_OPA_TRANSP = 0,
64     LV_OPA_0      = 0,
65     LV_OPA_10     = 25,
66     LV_OPA_20     = 51,
67     LV_OPA_30     = 76,
68     LV_OPA_40     = 102,
69     LV_OPA_50     = 127,
70     LV_OPA_60     = 153,
71     LV_OPA_70     = 178,
72     LV_OPA_80     = 204,
73     LV_OPA_90     = 229,
74     LV_OPA_100    = 255,
75     LV_OPA_COVER  = 255,
76 };
77 
78 #define LV_OPA_MIN 16  /*Opacities below this will be transparent*/
79 #define LV_OPA_MAX 251 /*Opacities above this will fully cover*/
80 
81 #if LV_COLOR_DEPTH == 1
82 #define LV_COLOR_SIZE 8
83 #elif LV_COLOR_DEPTH == 8
84 #define LV_COLOR_SIZE 8
85 #elif LV_COLOR_DEPTH == 16
86 #define LV_COLOR_SIZE 16
87 #elif LV_COLOR_DEPTH == 32
88 #define LV_COLOR_SIZE 32
89 #else
90 #error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
91 #endif
92 
93 /**********************
94  *      TYPEDEFS
95  **********************/
96 
97 typedef union
98 {
99     uint8_t blue : 1;
100     uint8_t green : 1;
101     uint8_t red : 1;
102     uint8_t full : 1;
103 } lv_color1_t;
104 
105 typedef union
106 {
107     struct
108     {
109         uint8_t blue : 2;
110         uint8_t green : 3;
111         uint8_t red : 3;
112     } ch;
113     uint8_t full;
114 } lv_color8_t;
115 
116 typedef union
117 {
118     struct
119     {
120 #if LV_COLOR_16_SWAP == 0
121         uint16_t blue : 5;
122         uint16_t green : 6;
123         uint16_t red : 5;
124 #else
125         uint16_t green_h : 3;
126         uint16_t red : 5;
127         uint16_t blue : 5;
128         uint16_t green_l : 3;
129 #endif
130     } ch;
131     uint16_t full;
132 } lv_color16_t;
133 
134 typedef union
135 {
136     struct
137     {
138         uint8_t blue;
139         uint8_t green;
140         uint8_t red;
141         uint8_t alpha;
142     } ch;
143     uint32_t full;
144 } lv_color32_t;
145 
146 #if LV_COLOR_DEPTH == 1
147 typedef uint8_t lv_color_int_t;
148 typedef lv_color1_t lv_color_t;
149 #elif LV_COLOR_DEPTH == 8
150 typedef uint8_t lv_color_int_t;
151 typedef lv_color8_t lv_color_t;
152 #elif LV_COLOR_DEPTH == 16
153 typedef uint16_t lv_color_int_t;
154 typedef lv_color16_t lv_color_t;
155 #elif LV_COLOR_DEPTH == 32
156 typedef uint32_t lv_color_int_t;
157 typedef lv_color32_t lv_color_t;
158 #else
159 #error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
160 #endif
161 
162 typedef uint8_t lv_opa_t;
163 
164 typedef struct
165 {
166     uint16_t h;
167     uint8_t s;
168     uint8_t v;
169 } lv_color_hsv_t;
170 
171 /**********************
172  * GLOBAL PROTOTYPES
173  **********************/
174 
175 /*In color conversations:
176  * - When converting to bigger color type the LSB weight of 1 LSB is calculated
177  *   E.g. 16 bit Red has 5 bits
178  *         8 bit Red has 2 bits
179  *        ----------------------
180  *        8 bit red LSB = (2^5 - 1) / (2^2 - 1) = 31 / 3 = 10
181  *
182  * - When calculating to smaller color type simply shift out the LSBs
183  *   E.g.  8 bit Red has 2 bits
184  *        16 bit Red has 5 bits
185  *        ----------------------
186  *         Shift right with 5 - 3 = 2
187  */
188 
lv_color_to1(lv_color_t color)189 static inline uint8_t lv_color_to1(lv_color_t color)
190 {
191 #if LV_COLOR_DEPTH == 1
192     return color.full;
193 #elif LV_COLOR_DEPTH == 8
194     if((color.ch.red & 0x4) || (color.ch.green & 0x4) || (color.ch.blue & 0x2)) {
195         return 1;
196     } else {
197         return 0;
198     }
199 #elif LV_COLOR_DEPTH == 16
200 #if LV_COLOR_16_SWAP == 0
201     if((color.ch.red & 0x10) || (color.ch.green & 0x20) || (color.ch.blue & 0x10)) {
202         return 1;
203 #else
204     if((color.ch.red & 0x10) || (color.ch.green_h & 0x20) || (color.ch.blue & 0x10)) {
205         return 1;
206 #endif
207     } else {
208         return 0;
209     }
210 #elif LV_COLOR_DEPTH == 32
211     if((color.ch.red & 0x80) || (color.ch.green & 0x80) || (color.ch.blue & 0x80)) {
212         return 1;
213     } else {
214         return 0;
215     }
216 #endif
217 }
218 
219 static inline uint8_t lv_color_to8(lv_color_t color)
220 {
221 #if LV_COLOR_DEPTH == 1
222     if(color.full == 0)
223         return 0;
224     else
225         return 0xFF;
226 #elif LV_COLOR_DEPTH == 8
227     return color.full;
228 #elif LV_COLOR_DEPTH == 16
229 
230 #if LV_COLOR_16_SWAP == 0
231     lv_color8_t ret;
232     ret.ch.red   = color.ch.red >> 2;   /* 5 - 3  = 2*/
233     ret.ch.green = color.ch.green >> 3; /* 6 - 3  = 3*/
234     ret.ch.blue  = color.ch.blue >> 3;  /* 5 - 2  = 3*/
235     return ret.full;
236 #else
237     lv_color8_t ret;
238     ret.ch.red   = color.ch.red >> 2;  /* 5 - 3  = 2*/
239     ret.ch.green = color.ch.green_h;   /* 6 - 3  = 3*/
240     ret.ch.blue  = color.ch.blue >> 3; /* 5 - 2  = 3*/
241     return ret.full;
242 #endif
243 #elif LV_COLOR_DEPTH == 32
244     lv_color8_t ret;
245     ret.ch.red   = color.ch.red >> 5;   /* 8 - 3  = 5*/
246     ret.ch.green = color.ch.green >> 5; /* 8 - 3  = 5*/
247     ret.ch.blue  = color.ch.blue >> 6;  /* 8 - 2  = 6*/
248     return ret.full;
249 #endif
250 }
251 
252 static inline uint16_t lv_color_to16(lv_color_t color)
253 {
254 #if LV_COLOR_DEPTH == 1
255     if(color.full == 0)
256         return 0;
257     else
258         return 0xFFFF;
259 #elif LV_COLOR_DEPTH == 8
260     lv_color16_t ret;
261 #if LV_COLOR_16_SWAP == 0
262     ret.ch.red = color.ch.red * 4;     /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/
263     ret.ch.green = color.ch.green * 9; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
264     ret.ch.blue = color.ch.blue * 10;  /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/
265 #else
266     ret.red        = color.ch.red * 4;
267     uint8_t g_tmp  = color.ch.green * 9;
268     ret.ch.green_h = (g_tmp & 0x1F) >> 3;
269     ret.ch.green_l = g_tmp & 0x07;
270     ret.ch.blue    = color.ch.blue * 10;
271 #endif
272     return ret.full;
273 #elif LV_COLOR_DEPTH == 16
274     return color.full;
275 #elif LV_COLOR_DEPTH == 32
276     lv_color16_t ret;
277 #if LV_COLOR_16_SWAP == 0
278     ret.ch.red   = color.ch.red >> 3;   /* 8 - 5  = 3*/
279     ret.ch.green = color.ch.green >> 2; /* 8 - 6  = 2*/
280     ret.ch.blue  = color.ch.blue >> 3;  /* 8 - 5  = 3*/
281 #else
282     ret.ch.red     = color.ch.red >> 3;
283     ret.ch.green_h = (color.ch.green & 0xE0) >> 5;
284     ret.ch.green_l = (color.ch.green & 0x1C) >> 2;
285     ret.ch.blue    = color.ch.blue >> 3;
286 #endif
287     return ret.full;
288 #endif
289 }
290 
291 static inline uint32_t lv_color_to32(lv_color_t color)
292 {
293 #if LV_COLOR_DEPTH == 1
294     if(color.full == 0)
295         return 0;
296     else
297         return 0xFFFFFFFF;
298 #elif LV_COLOR_DEPTH == 8
299     lv_color32_t ret;
300     ret.ch.red = color.ch.red * 36;     /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
301     ret.ch.green = color.ch.green * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
302     ret.ch.blue = color.ch.blue * 85;   /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/
303     ret.ch.alpha = 0xFF;
304     return ret.full;
305 #elif LV_COLOR_DEPTH == 16
306 #if LV_COLOR_16_SWAP == 0
307     lv_color32_t ret;
308     ret.ch.red   = color.ch.red * 8;   /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
309     ret.ch.green = color.ch.green * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/
310     ret.ch.blue  = color.ch.blue * 8;  /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
311     ret.ch.alpha = 0xFF;
312     return ret.full;
313 #else
314     lv_color32_t ret;
315     ret.ch.red   = color.ch.red * 8;                                 /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
316     ret.ch.green = ((color.ch.green_h << 3) + color.ch.green_l) * 4; /*(2^8 - 1)/(2^6 - 1) = 255/63 = 4*/
317     ret.ch.blue  = color.ch.blue * 8;                                /*(2^8 - 1)/(2^5 - 1) = 255/31 = 8*/
318     ret.ch.alpha = 0xFF;
319     return ret.full;
320 #endif
321 #elif LV_COLOR_DEPTH == 32
322     return color.full;
323 #endif
324 }
325 
326 static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
327 {
328     lv_color_t ret;
329 #if LV_COLOR_DEPTH != 1
330     /*LV_COLOR_DEPTH == 8, 16 or 32*/
331     ret.ch.red = (uint16_t)((uint16_t)c1.ch.red * mix + (c2.ch.red * (255 - mix))) >> 8;
332 #if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
333     /*If swapped Green is in 2 parts*/
334     uint16_t g_1   = (c1.ch.green_h << 3) + c1.ch.green_l;
335     uint16_t g_2   = (c2.ch.green_h << 3) + c2.ch.green_l;
336     uint16_t g_out = (uint16_t)((uint16_t)g_1 * mix + (g_2 * (255 - mix))) >> 8;
337     ret.ch.green_h = g_out >> 3;
338     ret.ch.green_l = g_out & 0x7;
339 #else
340     ret.ch.green = (uint16_t)((uint16_t)c1.ch.green * mix + (c2.ch.green * (255 - mix))) >> 8;
341 #endif
342     ret.ch.blue = (uint16_t)((uint16_t)c1.ch.blue * mix + (c2.ch.blue * (255 - mix))) >> 8;
343 #if LV_COLOR_DEPTH == 32
344     ret.ch.alpha = 0xFF;
345 #endif
346 #else
347     /*LV_COLOR_DEPTH == 1*/
348     ret.full = mix > LV_OPA_50 ? c1.full : c2.full;
349 #endif
350 
351     return ret;
352 }
353 
354 /**
355  * Get the brightness of a color
356  * @param color a color
357  * @return the brightness [0..255]
358  */
359 static inline uint8_t lv_color_brightness(lv_color_t color)
360 {
361     lv_color32_t c32;
362     c32.full        = lv_color_to32(color);
363     uint16_t bright = 3 * c32.ch.red + c32.ch.blue + 4 * c32.ch.green;
364     return (uint16_t)bright >> 3;
365 }
366 
367 /* The most simple macro to create a color from R,G and B values */
368 #if LV_COLOR_DEPTH == 1
369 #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){(b8 >> 7 | g8 >> 7 | r8 >> 7)})
370 static inline lv_color_t lv_color_make(int r8, int g8, int b8)
371 {
372     lv_color_t color;
373     color.full = (b8 >> 7 | g8 >> 7 | r8 >> 7);
374     return color;
375 }
376 #elif LV_COLOR_DEPTH == 8
377 #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 6, g8 >> 5, r8 >> 5}})
378 static inline lv_color_t lv_color_make(uint8_t r8, int g8, int b8)
379 {
380     lv_color_t color;
381     color.ch.blue = b8 >> 6;
382     color.ch.green = g8 >> 5;
383     color.ch.red = r8 >> 5;
384     return color;
385 }
386 #elif LV_COLOR_DEPTH == 16
387 #if LV_COLOR_16_SWAP == 0
388 #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 3, g8 >> 2, r8 >> 3}})
389 static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
390 {
391     lv_color_t color;
392     color.ch.blue  = (uint16_t)(b8 >> 3);
393     color.ch.green = (uint16_t)(g8 >> 2);
394     color.ch.red   = (uint16_t)(r8 >> 3);
395     return color;
396 }
397 #else
398 #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{g8 >> 5, r8 >> 3, b8 >> 3, (g8 >> 2) & 0x7}})
399 static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
400 {
401     lv_color_t color;
402     color.ch.green_h = (uint16_t)(g8 >> 5);
403     color.ch.red = (uint16_t)(r8 >> 3);
404     color.ch.blue = (uint16_t)(b8 >> 3);
405     color.ch.green_l = (uint16_t)((g8 >> 2) & 0x7);
406     return color;
407 }
408 #endif
409 #elif LV_COLOR_DEPTH == 32
410 #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/
411 static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
412 {
413     lv_color_t color;
414     color.ch.blue  = b8;
415     color.ch.green = g8;
416     color.ch.red   = r8;
417     color.ch.alpha = 0xff;
418     return color;
419 }
420 #endif
421 
422 static inline lv_color_t lv_color_hex(uint32_t c)
423 {
424     return lv_color_make((uint8_t)((c >> 16) & 0xFF), (uint8_t)((c >> 8) & 0xFF), (uint8_t)(c & 0xFF));
425 }
426 
427 static inline lv_color_t lv_color_hex3(uint32_t c)
428 {
429     return lv_color_make((uint8_t)(((c >> 4) & 0xF0) | ((c >> 8) & 0xF)), (uint8_t)((c & 0xF0) | ((c & 0xF0) >> 4)),
430                          (uint8_t)((c & 0xF) | ((c & 0xF) << 4)));
431 }
432 
433 /**
434  * Convert a HSV color to RGB
435  * @param h hue [0..359]
436  * @param s saturation [0..100]
437  * @param v value [0..100]
438  * @return the given RGB color in RGB (with LV_COLOR_DEPTH depth)
439  */
440 lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v);
441 
442 /**
443  * Convert an RGB color to HSV
444  * @param r red
445  * @param g green
446  * @param b blue
447  * @return the given RGB color n HSV
448  */
449 lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b);
450 
451 /**********************
452  *      MACROS
453  **********************/
454 
455 #ifdef __cplusplus
456 } /* extern "C" */
457 #endif
458 
459 #endif /*USE_COLOR*/
460