Xinyuan-LilyGO / TTGO_TWatch_Library

MIT License
903 stars 290 forks source link

Why colors are encoded on 6 bit in Hex instead of classic 3x256 ? #181

Closed ZZ0R0 closed 1 year ago

ZZ0R0 commented 1 year ago

Please help me with colors, I'm trying to make a color shifter program but i can't shift colors because the format is not (255,255,255) but 0xFFFF. Why is this ? How can I shift colors from red to purple to blue with a nice hue ? Is it even possible ? I tried to convert RGB to uint32_t but i get a format of 0xFFFFFF instead of 0xFFFF ! And 0xFFFFFF format is not working with the draw functions, why ? Can i modify the library you did in depth to change this ? Can I simply use a classic (R,G,B) format in the draw function ?

lewisxhe commented 1 year ago

see there https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library/blob/40e9c9a6190d7ac5998b9e6350aa102529569eef/src/libraries/TFT_eSPI/TFT_eSPI.h#L1008

codefaux commented 1 year ago

the format is not (255,255,255) but 0xFFFF. Why is this ?

The TFT itself uses what's known as 565 color format, as a limitation of the display and/or display driver using a total of 16 bits for all color channel data. For more detail, see here; https://stackoverflow.com/questions/25467682/rgb-565-why-6-bits-for-green-color

For interacting with this, there are several routes;

Here are two examples from a dead-simple debug display I'm working on.

tft->setTextColor( (axp->getBattPercentage()>25) ? TFT_LIGHTGREY : TFT_RED ); The inline conditional may be confusing, but note the use of TFT_ defines for predefined colors. These colors are defined in TFT_eSPI.h

// Default color definitions
#define TFT_BLACK       0x0000      /*   0,   0,   0 */
#define TFT_NAVY        0x000F      /*   0,   0, 128 */
#define TFT_DARKGREEN   0x03E0      /*   0, 128,   0 */
#define TFT_DARKCYAN    0x03EF      /*   0, 128, 128 */
#define TFT_MAROON      0x7800      /* 128,   0,   0 */
#define TFT_PURPLE      0x780F      /* 128,   0, 128 */
#define TFT_OLIVE       0x7BE0      /* 128, 128,   0 */
#define TFT_LIGHTGREY   0xD69A      /* 211, 211, 211 */
#define TFT_DARKGREY    0x7BEF      /* 128, 128, 128 */
#define TFT_BLUE        0x001F      /*   0,   0, 255 */
#define TFT_GREEN       0x07E0      /*   0, 255,   0 */
#define TFT_CYAN        0x07FF      /*   0, 255, 255 */
#define TFT_RED         0xF800      /* 255,   0,   0 */
#define TFT_MAGENTA     0xF81F      /* 255,   0, 255 */
#define TFT_YELLOW      0xFFE0      /* 255, 255,   0 */
#define TFT_WHITE       0xFFFF      /* 255, 255, 255 */
#define TFT_ORANGE      0xFDA0      /* 255, 180,   0 */
#define TFT_GREENYELLOW 0xB7E0      /* 180, 255,   0 */
#define TFT_PINK        0xFE19      /* 255, 192, 203 */ //Lighter pink, was 0xFC9F      
#define TFT_BROWN       0x9A60      /* 150,  75,   0 */
#define TFT_GOLD        0xFEA0      /* 255, 215,   0 */
#define TFT_SILVER      0xC618      /* 192, 192, 192 */
#define TFT_SKYBLUE     0x867D      /* 135, 206, 235 */
#define TFT_VIOLET      0x915C      /* 180,  46, 226 */

tft->setTextColor( (tm_info.tm_hour>12) ? tft->color565(128, 128, 204) : tft->color565(204, 204, 128) ); Again, inline conditionals, but note the use of tft->color565(128, 128, 204) to convert from 8-bit RGB triplet (0-255, 0-255, 0-255) to 16-bit color565 format.

If you have an 8-bit color code, you can use tft->color8to16()

If you have a 24-bit color code (16744255 aka 0xFF7F3F aka orange) you can use tft->color24to16(16744255) or tft->color24to16(0xFF7F3F)

How can I shift colors from red to purple to blue with a nice hue ?

Use alphaBlend(alpha, foreground565, background565) to blend (fade) between two color565 codes, or AlphaBlend24(a, f, b) to fade between two 24-bit color codes. For your example, tft->alphaBlend(fade_amount, TFT_RED, TFT_BLUE) would potentially work, but may not be "pretty" enough for some purposes. A function to convert HSV to 565 would be optimal -- example here, but you would have to rewrite it as a function; https://stackoverflow.com/questions/56735379/how-to-convert-rgb565-to-hsl-color-in-c

codefaux commented 1 year ago

I should also note that the more often you use native (aka 565) colors, the less "work" your software will need to do. It's only a few cycles, but in deep optimization that can begin to matter. Best Practice is to use native formats when possible, but there's nothing wrong with ignoring that in favor of getting it working.