Вычисление «среднего» двух цветов - PullRequest
4 голосов
/ 31 декабря 2010

Это только незначительно связано с программированием - имеет гораздо больше работы с цветами и их представлением.

Я работаю над приложением очень низкого уровня. У меня есть массив байтов в памяти. Это персонажи. Они были обработаны сглаживанием: они имеют значения от 0 до 255, 0 - полностью прозрачный и 255 - полностью непрозрачный (альфа, если хотите).

У меня проблемы с созданием алгоритма рендеринга этого шрифта. Я делаю следующее для каждого пикселя:

            // 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);
            }

Результаты, как вы видите, ниже желаемых. Это очень увеличенное изображение, в масштабе 1: 1 это выглядит так, как будто текст имеет зеленую «ауру».

The test, less than great

Любая идея о том, как правильно вычислить это, будет принята с благодарностью.

Спасибо за ваше время!

Ответы [ 3 ]

4 голосов
/ 31 декабря 2010

Вам нужно смешать цвета фона и переднего плана. A-ла:

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

Кстати, это действительно медленный способ рендеринга и смешивания шрифтов. Вместо этого вы должны визуализировать все символы шрифта за пределами экрана со всеми необходимыми свойствами, а затем использовать их в качестве текстуры для рендеринга на другие поверхности, когда вам нужен текст.

Edit:

Это выглядит не так:

(255.0 - (float) intensity/255.0)

Вместо этого должно быть:

(255.0 - (float) intensity)/255.0
1 голос
/ 31 декабря 2010

Выполнение альфа-смешивания пиксель за пикселем может быть слишком сложным, потому что текущее значение пикселя изменяет значение следующего пикселя.

Я бы изменил алгоритм с мыслью о смешивании по ячейкам.


Из-за того, что многие getPixel вызывают один глиф, вы не можете создать правильное целевое изображение.

1 голос
/ 31 декабря 2010

Я считаю, что "аура" вызвана сглаживанием. Техника усредняет пиксели со своими соседями.

Я понимаю, что вы, похоже, не используете OpenGL, но эта глава может помочь объяснить некоторые теории. Хотел бы я иметь лучший ответ, но, надеюсь, это указывает вам верное направление. Моей первой попыткой было бы отключить сглаживание, так как оно приносит больше вреда, чем пользы. Хотя, возможно, есть лучшее решение, чем это.

...