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