альфа канал
От: Шебеко Евгений  
Дата: 02.06.10 10:29
Оценка:
Есть буфер с альфа каналом, ну и цвета с альфа составляющей.
Не могу их правильно смешать Уже весь мозг себе сломал.

Основная идея в том, что если буфер залит непрозрачным цветом, то цвета должны смешиваться с фоном,
а если фон прозрачный, то не должны.

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

Пока что велосипед выглядит так:

static AGG_INLINE void blend_pix(value_type* p, 
                                    unsigned cr, unsigned cg, unsigned cb,
                                    unsigned alpha, 
                                    unsigned cover=0)
{
    if(alpha==0)return;
    calc_type a=p[Order::A];
    
    if(a==0)
    {
        p[Order::R]=(value_type)cr;
        p[Order::G]=(value_type)cg;
        p[Order::B]=(value_type)cb;
        p[Order::A]=(value_type)alpha;
        return;
    }

    calc_type r = p[Order::R];
    calc_type g = p[Order::G];
    calc_type b = p[Order::B];
    p[Order::R] = (value_type)((cr*alpha*base_mask+r*a*(base_mask-alpha))/base_mask/base_mask);
    p[Order::G] = (value_type)((cg*alpha*base_mask+g*a*(base_mask-alpha))/base_mask/base_mask);
    p[Order::B] = (value_type)((cb*alpha*base_mask+b*a*(base_mask-alpha))/base_mask/base_mask);
    p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift));
}


Использую agg. Но это в принципе не важно. Давайте будем считать
что цвета у нас от 0 до 1. И альфа канал тоже от 0 до 1.
r,g,b,a — цвет фона.
cr,cg,cb,ca — накладываемый сверху цвет.

Код у нас получается такой:
if(ca==0)return;
if(a==0)
{
    r=cr;
    g=cg;
    b=cb;
    a=ca;
    return;
}

r=cr*ca+r*a*(1.0-ca);
g=cg*ca+g*a*(1.0-ca);
b=cb*ca+b*a*(1.0-ca);
a=ca+a-ca*a;


Первый if: Если новый цвет целиком прозрачный, то он не оказывает никакого влияния на буфер, даже если тот тоже целиком прозрачный.
Второй if — это костыль.
Посмотрим на выражение: r=cr*ca+r*a*(1.0-ca);
Допустим буфер у нас целиком прозрачный, тогда правая часть суммы r*a*(1.0-ca)=0.
Допустим мы накладываем белый цвет, с прозрачностью 0.5. Тогда левая часть суммы, превращает наш цвет из белого в серый.
Хотя по идее он должен был остаться белым с альфа каналом 0.5.

Эту формулу взял с википедии. Мне она показалась наиболее разумной в моём случае.
Формула смешивания альфа канал хз почему такая. Взял с той же википедии и в том же agg часто используется именно в таком виде.
Что она значит, так и не понял Для меня это "суммируем значение прозрачности, главное чтобы она не превысила максимальное значение"

В чём проблема с моим кодом?

1. Хотелось бы убрать костыли и не изобретать велосипед.
2. Хотелось бы добиться непрерывности функций.
Ещё раз приведу формулу: r=cr*ca+r*a*(1.0-ca);
Допустим буфер у нас "почти прозрачный" a — стремится к нулю, тогда правая часть суммы r*a*(1.0-ca) тоже стремиться к нулю.
И мы получаем туже проблему, что белый полупрозрачный цвет превращается в грязно-серый.
3. Хотелось бы понять как именно складывать альфа канал.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.