Around a decade ago I was building a custom version of i3blocks (read: a version that just works for me) and wanted to display my battery percentage status, color-coded to the percentage: progression from green for 100%, and red for 0%. As the battery status shifts up and down, I wanted the color to also change towards yellow (for 50%), and then towards red/green depending on the value. This isn’t technologically interesting and it’s just a 5-minute C program that I wanted to save the documentation somewhere for the future. Anyways, yay for additive RGB and bitshifts!
Consider red, green, and yellow in RGB
FF0000 -- Red - 0%
00FF00 -- Green - 100%
FFFF00 -- Yellow - 50%
From kindergarten we know that to get yellow, we mix green and red. Therefore from 0% to 50%:
FF0000
FF0100
FF0200
...
FFFE00
FFFF00
Effectively, for percentages 1-50, we need to add more green until fully saturated. Per percentage (1-50), we need to scale the progression of the green-ness by 1/50: 0xFF/50=5.1
so for every percentage of battery from 1 to 50, we add 5.1 of “green-ness”.
if(battery <= 50){
double green_ratio = battery/50.0; // Ratio of battery out of 50
int green = 0x0000FF; // A full color in the RGB model, shift 8 to move it to G.
int red = 0xFF0000; // Red
green *= green_ratio; // Multiply by the "green-ness" ratio
green = green << 8; // Push into the G of RGB
sprintf(rgb, "#%06x\n", red + green);
}
There’s some truncation that happens related to the green-ness (can’t add the .1 of green) but whatever.
For 51-100%, the formula is pretty much the same, but given yellow (FFFF00), we slowly decrease red. i.e:
if(battery > 50) {
double red_ratio = (battery-50.0)/50;
int red = 0x0000FF; // A full color in the RGB model, shift 16 to move it to R.
int yellow = 0xFFFF00; // Yellow
red *= red_ratio; // Multiple by the 'red-ness' ratio
red = red << 16; // Push into the R of RGB
sprintf(rgb, "#%06x\n", yellow - red);
}
I used the same algorithm for monitoring some kernel state in freebsd related to memory, namely vm.stats.vm
and page_size, free_count, cache_count, inactive_count, and page_count.