Posts: 145
Joined: Mon Jul 30, 2018 3:44 pm

Bitwise Math

Fri Oct 26, 2018 11:33 am

Not long ago a forum member converted what I was doing in converting a single "level" value to level of target RGB value using bitwise operations vs readable math.

This has worked out great, however during my initial development I was rendering text on either black or very dark background. So when the background is of a light color... black edging in various spots around characters is very noticeable because currently the resulting pixel is from 0 | Target

So question is... for those who understand bitwise "math" if you will.... I would like to create another function similar to the existing convert func that would use a base RGB and work out the level of target color to the base which should result in the edge pixels appearing to slowly blend from target color to base color (aka background / surrounding)

I may be wrong, but I think its a bit tricky when the target may be 0 (black) and the base is green for example... perhaps reverse switching where 255+1 represents 0 and 0 represents 255+1 .... humm...

Code: Select all

uint32_t lfb_convert_color(unsigned int color, unsigned int bc)
    bc += 1;

    unsigned int r = color & 0x00ff0000;
    unsigned int g = color & 0x0000ff00;
    unsigned int b = color & 0x000000ff;

    r = (r * bc) & 0xff000000;
    g = (g * bc) & 0x00ff0000;
    b = (b * bc) & 0x0000ff00;

    unsigned int dst = (color & 0x00000000) | ((r | g | b) >> 8);

    return dst;

Posts: 5791
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Bitwise Math

Fri Oct 26, 2018 12:37 pm

One way to visualise your problem is as a 'single pixel' RGB LED you wish to take from one colour to another.

What you are trying to do is have two points within an 'RGB cube' and traverse from one to another. That's not particularly easy as a simple straight line between the two doesn't necessarily give sensible colour transitions along the way.

It works much better using HVL/HVS rather than RGB so the trick is probably to convert RGB to HVL/HVS then translate the transition line back to RGB.

User avatar
Posts: 35814
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website Twitter

Re: Bitwise Math

Fri Oct 26, 2018 3:09 pm

Go and take a look at that's an Arduino library that does the colour stuff you're asking about.
Note: Having anything humorous in your signature is completely banned on this forum. Wear a tin-foil hat and you'll get a ban.

Any DMs sent on Twitter will be answered next month.

This is a doctor free zone.

Posts: 145
Joined: Mon Jul 30, 2018 3:44 pm

Re: Bitwise Math

Fri Oct 26, 2018 3:30 pm

Ahhh...... I'll try and sniff thru that lib and absorb what I can... I was able to quickly find small examples of converting to and from RGB / HSV but what to do with the H value on percentage from Point A to B is still murky...

I think I'll go ahead and apply (color2 - color1) * fraction + color1 for the time being on RGB until I can better understand what to do... I am not performing a gradient so the edge pixels of a font character shouldn't land in an odd place within the spectrum between points... but I could be wrong.... in either case it will look better than black outlining ... maybe ... we shall see....

Posts: 145
Joined: Mon Jul 30, 2018 3:44 pm

Re: Bitwise Math

Fri Oct 26, 2018 8:51 pm

I sorta compiled some ideas from a couple of stackoverflow threads etc... and came up with the following which is rendering the text nicely... no edging thus far with the various color combos I have tested and especially black on white, green etc.. where previously the edges where causing a visual "blocking" ...

I understand based on some other threads etc... that using a double/float is not optimal... but until I understand enough about bitwise operations etc... I'll have to use this ...

Code: Select all

typedef struct RGB_S {
	int R;
	int G;
	int B;
} RGB_T;

static RGB_T get_rgb(unsigned int color)
	RGB_T rgb;
	rgb.R = (color & 0x00ff0000) >> 16;
	rgb.G = (color & 0x0000ff00) >> 8;
	rgb.B = (color & 0x000000ff);

	return rgb;

static int interpolate(int svalue, int evalue, double fraction)
	return (evalue - svalue) * fraction + svalue;

static unsigned int convert_bc_pixel(unsigned int tcolor, unsigned int bcolor, unsigned int bc)
	double fraction = bc / 255.0f;

	RGB_T target = get_rgb(tcolor);
	RGB_T background = get_rgb(bcolor);
	RGB_T new;

	new.R = interpolate( background.R, target.R, fraction );
	new.G = interpolate( background.G, target.G, fraction );
	new.B = interpolate( background.B, target.B, fraction );

	return ((new.R << 16) | (new.G << 8) | new.B);

Return to “C/C++”