grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

[Solved] Framebuffer and Freetype2 Font Color Control

Thu Oct 11, 2018 1:49 am

In the spirit of trying to learn C... I picked up where I last got discouraged in creating a basic 800x480 (max res of 5" display) Menu which works like my current python curses program.... but I want to have background image etc...

So I got as far as rendering an image successfully to the framebuffer and now have ttf font text rendering on top with no issue... except I can't figure out the color control aspect.

So I figured out color by adding a flag when I call FT_Load_Char which defaults to 0x000000FF color range...

Code: Select all

FT_Load_Char( face, text[n], FT_LOAD_RENDER | FT_LOAD_COLOR );
Reviewing some code I was able to find from a github framebuffer freetype2 example.... the text is now shifted to green via shifting the uint32_t created by the buffer->bitmap 8 bits

Code: Select all

 color = ((color & 0x000000FF) << 8) + 0xFF000000; 
But what I want, is for the max value to be 0xFF00832C and maintain the anti aliasing color values from the buffer->bitmap result.... I think I understand complete shifting.... which is happening from the example above..

But how do I shift it from the default "Blue" spectrum to a "Shade" of desired color?
Last edited by grininmonkey on Thu Oct 11, 2018 4:52 pm, edited 1 time in total.

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: Framebuffer and Freetype2 Font Color Control

Thu Oct 11, 2018 1:46 pm

Ok.... I might be thinking on the right track.. maybe??

I realize now that the set pixel colors from the get bitmap are in 0xFF so the anti lasing effect is adjusting a percentage of blue.. 00 to FF or 0 to 255..

I can't simply take my target color value and adjust the percentage directly.... will have to be done with some math magic per R,G and B..

Code: Select all

 void
 show_image( void )
 {   
     int  i, j;
     uint32_t color;
     for ( i = 0; i < HEIGHT; i++ ) {
         for ( j = 0; j < WIDTH; j++ ) {
             color = image[i][j];
             if(color) {
                 printf("%g\n",(double)color/255);
                 //printf("0x%08x\n",(uint32_t)ceil(((double)color/255)*33580));
                 color = ((color & 0x000000FF) << 8) + 0xFF000000; // map the blue to green and set alpha to 0xFF
                 //color = (uint32_t)ceil(((double)color/255)*33580);
                 lfb.putpixel(j,i, color);
             } 
         }
     }
 }


So... am I on the right track? As in I know the percentage of "brightness" per pixel now based on level of blue assigned.... my printf %g showed me this percentage, however I am not clearly understanding how I can now take a target color (for example 0x0000832C) and adjust the level of "brightness" against that using the percentage of the initial (double)color/255.

I'll have to get percentage of each channel (R,G,B) from "target" and then multiple the base percentage (initial color) against each "target" channel.... as in % of % Target R, G and B independently..... ??

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: Framebuffer and Freetype2 Font Color Control

Thu Oct 11, 2018 4:52 pm

Yep.... figured out I need to determine percentage of percent per channel...

In case someone reads this down the road, I did the following to manipulate the variation of color due to anti-lasing.

Created a function to take "Target" color and blue amount (0-255) which is returned from freetype image mapping.

Code: Select all

uint32_t color_level(int tc, int lvl)
{
	int a,r,g,b;
	double p = lvl / 255.0f;
	uint32_t nc;

	a = (tc >> 24) & 255;
	r = ceil(p * (255 * ((((tc) & 0xFF0000) >> 16) / 255.0f)));
	g = ceil(p * (255 * ((((tc) & 0xFF00) >> 8) / 255.0f)));
	b = ceil(p * (255 * (((tc) & 0xFF)  / 255.0f)));

	nc |= (a & 255) << 24;
	nc |= (r & 255) << 16;
	nc |= (g & 255) << 8;
	nc |= (b & 255);

	return (nc);
}
So now the pixel putter function looks like so.... to put the "text" pixels...

Code: Select all

void
show_image( void )
{
    int  i, j;
    uint32_t color,nc;
    for ( i = 0; i < HEIGHT; i++ ) {
        for ( j = 0; j < WIDTH; j++ ) {
		color = image[i][j];
        	if(color) {
				nc = color_level(0xFF00832C,color & 255);
				//printf("0x%08x\n",nc);
				lfb.putpixel(j,i, nc);
			} 
      	}
    }
}
So making some progress now.... which is exciting ;-)

I like my current/original thermostat interface which is nothing but curses on tty1...
Image

But now with this exercise in poking to the framebuffer using C... it's going to have a little more spice and effects... I am playing around with animated scan lines!!! I now have the beginnings of rendering any ttf font on top of a background image...

Startup frame..
Image

Current work in progress (main screen) frame after figuring out the text color above...
Image

User avatar
Paeryn
Posts: 2170
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: Framebuffer and Freetype2 Font Color Control

Thu Oct 11, 2018 9:47 pm

grininmonkey wrote:
Thu Oct 11, 2018 4:52 pm

Code: Select all

uint32_t color_level(int tc, int lvl)
{
	int a,r,g,b;
	double p = lvl / 255.0f;
	uint32_t nc;

	a = (tc >> 24) & 255;
	r = ceil(p * (255 * ((((tc) & 0xFF0000) >> 16) / 255.0f)));
	g = ceil(p * (255 * ((((tc) & 0xFF00) >> 8) / 255.0f)));
	b = ceil(p * (255 * (((tc) & 0xFF)  / 255.0f)));

	nc |= (a & 255) << 24;
	nc |= (r & 255) << 16;
	nc |= (g & 255) << 8;
	nc |= (b & 255);

	return (nc);
}
You want to either alter that first nc |= (a & 255) << 24 to just a plain assignment rather than orring or explicitly initialise nc = 0. As it is nc could have any random value at the start of the function (either whatever was last stored in the memory address on the stack that nc is being stored at or, if the compiler decides that nc can be kept in a register, whatever value that register previously had) which would mess up your returned colour. If it happens to be zero then that is by sheer luck, whatever you do don't rely on automatic variables having any particular value initially.
Last edited by Paeryn on Thu Oct 11, 2018 10:15 pm, edited 1 time in total.
She who travels light — forgot something.

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: [Solved] Framebuffer and Freetype2 Font Color Control

Thu Oct 11, 2018 10:05 pm

I've set nc=0.... thanks for the heads up!

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: [Solved] Framebuffer and Freetype2 Font Color Control

Thu Oct 11, 2018 11:15 pm

Using the bitwise vs + as in a<<24 + r<<16 + g<<8 + b to stack or I guess pack into the unsigned 32 bit nc is correct?

I tried both ways, but stuck with bitwise approach... seemed to be more appropriate based on my "very" limited understanding of what I am doing in C....

User avatar
Paeryn
Posts: 2170
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: [Solved] Framebuffer and Freetype2 Font Color Control

Fri Oct 12, 2018 1:06 am

As you know the bits from each quarter aren't overlapping, orring unsigned ints is the same as adding. I prefer to write it with orring since that is logically what you are doing.

Depending on usage, that is a lot of floating point operations per pixel. I'd be tempted to keep it in integers. Quick knock up :-

Code: Select all

unsigned int colour_value(unsigned int src, unsigned int value)
{
    // These three lines fudge the value so input range 0->255
    // becomes 1->256 (having maximum value a power of 2 is better
    // for the quick maths, a value of 1 has the same result as 0 would).
    val += 1;

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

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

    unsigned int dst = (src & 0xff000000) | ((r | g | b) >> 8);

    return dst;
}
She who travels light — forgot something.

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: [Solved] Framebuffer and Freetype2 Font Color Control

Fri Oct 12, 2018 2:47 am

I wish I understood enough right now to come up with better ways of doing stuff like that.... I changed my function per your example ;)

User avatar
Paeryn
Posts: 2170
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: [Solved] Framebuffer and Freetype2 Font Color Control

Fri Oct 12, 2018 9:41 am

grininmonkey wrote:
Fri Oct 12, 2018 2:47 am
I wish I understood enough right now to come up with better ways of doing stuff like that.... I changed my function per your example ;)
It does the same as yours but takes advantage of fixed-point rather than floating-point arithmetic and avoids shifts where possible. I added the 1 to the level because that means we can do the divide 256 by shifting right 8 which is a lot quicker. Expanding it,

Code: Select all

r = (src & 0x00ff0000) >> 16;
g = (src & 0x00ff0000) >> 8;
b= src & 0x000000ff;

r = (r * level) >> 8;
g= (g * level) >> 8;
b = (b * level) >> 8;

dst = a | (r << 16) | (g << 8) | b;
Now notice that each component is shifted down just for the result to be shifted back up the same distance so no need to do those shifts (it makes no difference to the maths). The individual shift right 8 can all be done at once by masking off the parts of the components we want (the masks are 8 bits to the left of where we masked the originals), or them togother and do the shift on the combined value.

Initially you mask off each component, no need to shift the value down as we would only need to shift the result back up.

Code: Select all

r = src & 0x00ff0000;
Then you multiply by the scale factor you want, but treating this scale as an 8.8 fixed point value (so 256 = 1.0, 128 = 0.5 etc.). We don't want the fraction part so mask off the integer section (this is in the byte higher than where the source byte is).

Code: Select all

r = (r * level) & 0xff000000;
All three values need shifting back 8 bits (the divide by 256), we can or them together first since we know the bits are otherwise in the correct places and just do the one shift on that.

Code: Select all

(r | g | b) >> 8
She who travels light — forgot something.

grininmonkey
Posts: 92
Joined: Mon Jul 30, 2018 3:44 pm

Re: [Solved] Framebuffer and Freetype2 Font Color Control

Fri Oct 12, 2018 5:31 pm

Really nice explanation! I'll admit that I "kinda" follow it, but does gives me enough insight to further understand. In general, I have recently realized that my initial fault and failure in attempting to learn C was maintaining my higher level programming thought process.... where as in C I need to start visualizing and understanding memory and addressing and the fundamental behavior of operations against that.

My first C hair pulling frustration for me was not the concepts of pointers and reference ..... but rather strings of all things... and better yet... an empty multi-dimension array who's size is defined/expanded and or resized dynamically... but I am slowly getting it now.... and really enjoying the learning process.

My first revaluation was to no longer visualize or think of a number (for example) as just a number... but rather to think/visualize such as in this example of working with an ARGB values as...

AAAAAAAA 00000000 00000000 00000000
00000000 RRRRRRRR 00000000 00000000
00000000 00000000 GGGGGGGG 00000000
00000000 00000000 00000000 BBBBBBBB

And not merely the value itself in short form .... so the concepts of shifting etc... finally make sense to me ;-)

Return to “C/C++”