добавление альфа-значений в алгоритм билинейного изменения размера - PullRequest
2 голосов
/ 07 декабря 2008

Итак, я пытаюсь использовать алгоритм билинейной интерполяции для изменения размера изображений и добавления альфа-значений. Я использую Actionscript 3 для этого, но я не думаю, что язык уместен.

Код, приведенный ниже, на самом деле работает очень хорошо, но края вокруг «стертых» областей кажутся темнее. Есть ли простой способ для него не включать то, что я могу предположить только черный (0x00000000), когда он находит свое среднее значение?

Код:

x_ratio = theX - x;
y_ratio = theY - y;
x_opposite = 1 - x_ratio;
y_opposite = 1 - y_ratio;

a = getPixel32(x, y);
be =getPixel32(x + 1, y);
c = getPixel32(x, y + 1);
d = getPixel32(x + 1, y + 1);
alph    = (t(a)  * x_opposite  + t(be)   * x_ratio) * y_opposite + (t(c) * x_opposite  + t(d) * x_ratio) * y_ratio;
red     = (r(a)  * x_opposite  + r(be)   * x_ratio) * y_opposite + (r(c) * x_opposite  + r(d) * x_ratio) * y_ratio;
green   = (g(a)  * x_opposite  + g(be)   * x_ratio) * y_opposite + (g(c) * x_opposite  + g(d) * x_ratio) * y_ratio;
blue    = (b(a)  * x_opposite  + b(be)   * x_ratio) * y_opposite + (b(c) * x_opposite  + b(d) * x_ratio) * y_ratio;

Изображение эффекта: http://beta.shinyhammer.com/images/site/eraser_pixelborders.jpg

Публикация кода решения!

a = getPixel32(x, y);
be =getPixel32(x + 1, y);
c = getPixel32(x, y + 1);
d = getPixel32(x + 1, y + 1);
asum = (t(a) + t(be) + t(c) + t(d)) / 4;

alph    = (t(a)  * x_opposite  + t(be)   * x_ratio) * y_opposite + (t(c) * x_opposite  + t(d) * x_ratio) * y_ratio;
red     = ((r(a) * t(a) * x_opposite  + r(be) * t(be) * x_ratio) * y_opposite + (r(c) * t(c) * x_opposite  + r(d) * t(d) * x_ratio) * y_ratio);
red = (asum > 0) ? red / asum : 0;
green   = ((g(a) * t(a) * x_opposite  + g(be) * t(be) * x_ratio) * y_opposite + (g(c) * t(c) * x_opposite  + g(d) * t(d) * x_ratio) * y_ratio);
green = (asum > 0) ? green /  asum : 0;
blue    = ((b(a) * t(a) * x_opposite  + b(be) * t(be) * x_ratio) * y_opposite + (b(c) * t(c) * x_opposite  + b(d) * t(d) * x_ratio) * y_ratio);
blue = (asum > 0) ? blue / asum : 0;

Ответы [ 2 ]

5 голосов
/ 07 декабря 2008

Вам нужно умножить каждое из ваших значений r, g, b на соответствующую альфу, прежде чем работать с ними, а затем разделить значения на конечную альфа, когда вы закончите. Легко представить эффект, который будет иметь место, когда один из пикселей будет иметь альфа-ноль - каждое из значений r, g, b будет умножено на ноль, поэтому не имеет значения, каковы их исходные значения! Они не будут способствовать окончательному результату.

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

Часто изображения сохраняются в памяти с альфа-каналом, уже умноженным на значения r, g, b - это называется предварительно умноженным альфа ( ссылка на Википедию ).

2 голосов
/ 07 декабря 2008

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

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

Для «предварительно не умноженной альфа» алгоритм компоновки LIRP (линейная интерполяция), равный

d = Kf + (1-K)b

... где K - альфа переднего плана, f - значение переднего плана, а b - фон.

Для «предварительно умноженной альфы» вы используете

d = f + (1-K)b

... который удаляет одно из умножений, что может сделать процесс быстрее (и дешевле в аппаратном обеспечении). Ключевым документом для чтения является Портер и Дафф - «Компоновка цифровых изображений»

Если вы используете Windows, функция Win32 AlphaBlend требует предварительно умноженного альфа-канала, поэтому по возможности хорошо оставаться в предварительно умноженном домене.

...