F. P.
F. P.

Reputation: 5086

Computing "average" of two colors

This is only marginally programming related - has much more to do w/ colors and their representation.

I am working on a very low level app. I have an array of bytes in memory. Those are characters. They were rendered with anti-aliasing: they have values from 0 to 255, 0 being fully transparent and 255 totally opaque (alpha, if you wish).

I am having trouble conceiving an algorithm for the rendering of this font. I'm doing the following for each pixel:

            // intensity is the weight I talked about: 0 to 255
            intensity = glyphs[text[i]][x + GLYPH_WIDTH*y];
            if (intensity == 255)
                continue; // Don't draw it, fully transparent
            else if (intensity == 0) 
                setPixel(x + xi, y + yi, color, base); // Fully opaque, can draw original color
            else { // Here's the tricky part
                // Get the pixel in the destination for averaging purposes
                pixel = getPixel(x + xi, y + yi, base);
                // transfer is an int for calculations
                transfer = (int)  ((float)((float) (255.0 - (float) intensity/255.0) * (float) color.red + (float) pixel.red)/2); // This is my attempt at averaging
                newPixel.red = (Byte) transfer;
                transfer = (int)  ((float)((float) (255.0 - (float) intensity/255.0) * (float) color.green + (float) pixel.green)/2);
                newPixel.green = (Byte) transfer;
                // transfer = (int) ((float) ((float) 255.0 - (float) intensity)/255.0 * (((float) color.blue) + (float) pixel.blue)/2);
                transfer = (int)  ((float)((float) (255.0 - (float) intensity/255.0) * (float) color.blue + (float) pixel.blue)/2);
                newPixel.blue = (Byte) transfer;
                // Set the newpixel in the desired mem. position
                setPixel(x+xi, y+yi, newPixel, base);
            }

The results, as you can see, are less than desirable. That is a very zoomed in image, at 1:1 scale it looks like the text has a green "aura".

The test, less than great

Any idea for how to properly compute this would be greatly appreciated.

Thanks for your time!

Upvotes: 4

Views: 391

Answers (3)

9dan
9dan

Reputation: 4282

It may be too much complicated to doing alpha blending pixel by pixel because current pixel value modifies next pixel value.

I would redesign the algorithm with the thinking of box wise blending.


With many getPixel calling for a single glyph, you can't produce proper target image.

Upvotes: 1

OJ.
OJ.

Reputation: 29399

You need to blend the background and foreground colours. A-la:

pixelColour = newColour * intensity + backgroundColour * (1 - intensity)

By the way, this is a really slow way of rendering and blending fonts. You should instead render all the characters of the font to an off-screen surface with all the properties you need, and then use that as a texture to render to other surfaces when you need text.

Edit:

This doesn't look right:

(255.0 - (float) intensity/255.0)

It should instead be:

(255.0 - (float) intensity)/255.0

Upvotes: 4

EnabrenTane
EnabrenTane

Reputation: 7466

I believe that "aura" is caused by anti aliasing. The technique averages pixels with their neighbors.

I realize you don't seem to be using OpenGL but this chapter might help explain some of the theory. Wish I had a better answer, but hopefully this points you in the right direction. My first attempt would be to disable Antialiasing since it seems to do more harm than good. There is probably a better solution than that though.

Upvotes: 1

Related Questions