How can I represent 3 Bytes of RGB as 1 Byte?

Good day, everyone.

I have this project. A helmet for my DJ gigs with addressable LEDS. There are roughly 700 LEDS on this helmet, all individually addressable and controlled by an ESP32 with an Ethernet shield.

I've managed to get it send a full frame of data at around 24 frames per second. That's 3 bytes per color X 700 LEDs. Any faster and I end up hitting buffering limits. Now I have been advised that I can look into compression or only updating the LEDs that need to be updated but I figured personally it would make more sense to just reduce the resolution of color palette. Instead of 3 Bytes, only send the 1 byte and limit the color palette to 256 colors. I mean we're talking about average LED strips which aren't exactly epitome of sRGB color accuracy so reducing the range of colors to 256 I think would be just fine.

The question is, if I'm sending 1 byte of data, how can I then map that 1 byte to a particular RBG color value on the receiving end?

My current possible vector of attack is to use a table like this: 256 Colors - Cheat Sheet - Xterm, HEX, RGB, HSL
and literally scrape the data off it, format it into a 256 entry array, each index containing a 3 bytes RGB value, and use it as a lookup table on the receiving end. Then, create a color palette within my animation software where I create the animations, to limit the color choice to only these colors and make a corresponding encoding dictionary Red is the top values, within which there's a number of Green values, within which there's a number of Blue values, thus creating basically a 3 level deep lookup table for encoding an RGB color into a single decimal to be sent over the network.

The part I'm iffy about is the creation of the two lookup tables. Perhaps there's a way to use some other Principe for translating the 3 bytes of rgb data into a single byte. Maybe some sort of a known algorithm that is present within both the application sending the data and the MCU receiving the data. To get the sinle color byte, the 3 RGB bytes are fed into the algorythm and on the receiving end, the same algorithmic is performed in reverse, spitting out an RGB value?

Ultimately I want to find a way to reduce the 3 bytes of color data to 1 byte. This would triple my frame data traffic, allowing me to send more frames and achieve smoother animation.

a 'simple' way of compressing 3 bytes into one would be to change the base use ie from base 2 (binary) to some other value that would suit the range of value you expect to use as described in this thread I found.

hope that helps...

The human eye is most sensitive in the green region - which is why RGB565 gives the most bits to green

so it would make most sense for green to be one that gets 3 bits;
then decide if you want red or blue to only have "coarse" control (only 2 bits)...

What do you mean by "buffering limits"?

What are the "transmitting" and "receiving" ends? Over what channel is the data transferred between them?

There are very many such, but one byte codes for 256 different colors, no matter whether you choose an algorithm, or a lookup table.

1 Like

Perhaps it would be easier in HSV Color Space?

If the 700 LEDs are all in one string then even if only one is updated then data needs to be sent to all of them

3 Likes

Is 00-ff R, 00-ff G and 00-ff B necessary. How many shades of green are enough? Consider limiting your colors.

Maybe I understand and you like this.

3x8 but is 24 bits of possible combinations, over 16 million.

But suppose that you only need 256 combos at least for this frame? Then you define a struct of 3 bytes and made a 256 element array of those and name it palette. You can change the palette or sections of it very quickly, 256 is a soft limit.

Do you need more?

PS, are you storing tables and images in PROGMEM?

By Buffering I mean that ESP32 can't process this much traffic to keep up updating the LED's

Transmitter being the Computer sending frame data over Ethernet and Receiver being ESP32 with an Ethernet shield

HSV would still be 3 bytes, each for Hue, Saturation and Value. I was contemplating on splitting into just Hue and Value tho and the Hue would chose from a series of saturated and desaturated Hues so the saturation would be implied.

It's more talking about sending the data only for updated LEDs but you'd still have to supply the LED addresses so it doesn't really help. And yes, ALL leds have to be updated.

Maybe. Would having only 4 brigtness states for each color [00, 01, 10, 11] be as flexible as making a lookup table of 255 colors?

Yeah so a lookup table.

I am hoping there's perhaps some sort of existing algorythm I could lean on before I go down this route.

No storage, just receive the data and feed straight into the LEDs.

From what I figured, the buffering limit is on the Ethernet shield, not the LED strips. So by somehow reducing each color from 3 bytes to 1 byte, I can theoretically triple the throughput (if I don't hit some other bottleneck).

Right now I can top at around 16fps without lag or delay. Anything faster and I can see the helmet fail to keep up. I can stop the animation and see the helmet still playing back buffered frame data.

Start with that idea, but use the last two bits as an intensity for all three. That gives you colour mix, plus intensity control, all in one byte per LED. Unpacking to three bytes, though, will be fiddly. Start with the intensity setting the high two bits of all three bytes, then map in each bit pair as you see fit.
But, a LUT will be much, much faster.

The image pixels would be 1 byte palette color. The color# is the index in the palette array of 3 byte structs. You send those 3 bytes to the leds.

No: because 2 bits per colour is a total of just 6 bits; so just 64 colours - you are "wasting" 2 bits in each byte.

With a lookup table, you don't have to allocate specific numbers of bits to each colour, or have any algorithmic relation between the byte value and the colour - you could just have a "palette" of 256 random colours.

Yeah it's starting to seems like a look up table might be the best option after all.

Before I commit to that, I don't suppose there might exist an algorithmic method of creating a color table? Also someone said that a look up table would be faster? I've seen some doom and quake dev videos where devs always talk about some calculation being too costly and they in turn rely on a lookup table for pre-calculated values.

How can a look up table be faster than calculating on the spot?

2 bits each R G B is 64 colors that you can change almost any time.