Нужна помощь в работе с предварительно умноженным альфа - PullRequest
0 голосов
/ 25 мая 2010

Я пытаюсь обновить исходное изображение содержимым нескольких целевых изображений. Из того, что я могу сказать, использование умножения предварительно умноженной альфы - это путь, но я думаю, что делаю что-то не так (функция ниже). изображение, с которого я начинаю, инициализируется со всеми значениями ARGB, установленными на 0. Когда я запускаю функцию, один раз получающееся изображение выглядит великолепно, но когда я начинаю наложение на любые другие, все пиксели, которые имеют альфа-информацию, действительно испорчены. Кто-нибудь знает, если я делаю что-то явно неправильно или мне нужно что-то еще, чтобы изменить значения цвета?

void CompositeImage(unsigned char *src, unsigned char *dest, int srcW, int srcH){
int w = srcW;
int h = srcH;

int px0;
int px1;
int px2;
int px3;

int inverseAlpha;

int r;
int g;
int b;
int a;

int y;
int x;

for (y = 0; y < h; y++) {
    for (x= 0; x< w*4; x+=4) {
        // pixel number
        px0 = (y*w*4) + x;
        px1 = (y*w*4) + (x+1);
        px2 = (y*w*4) + (x+2);
        px3 = (y*w*4) + (x+3);

        inverseAlpha = 1 - src[px3];

        // create new values
        r = src[px0]  + inverseAlpha * dest[px0];
        g = src[px1]  + inverseAlpha * dest[px1];
        b = src[px2]  + inverseAlpha * dest[px2];
        a = src[px3]  + inverseAlpha * dest[px3];

        // update destination image
        dest[px0] = r;
        dest[px1] = g;
        dest[px2] = b;
        dest[px3] = a;
    }
}

}

1 Ответ

2 голосов
/ 25 мая 2010

Мне не ясно, с какими данными вы работаете. У ваших исходных изображений уже есть альфа-значения, предварительно умноженные, поскольку они сохранены? Если нет, то предварительно умноженная альфа здесь не применима, и вам нужно было бы сделать нормальное альфа смешивание.

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

inverseAlpha = 1 - src[px3];

Это необходимо изменить на:

inverseAlpha = 255 - src[px3];

Здесь у вас есть все целочисленные типы значений, поэтому обычный диапазон входящего значения 0..255 приведет к диапазону inverseAlpha, равному -254..1, что даст вам действительно странные результаты.

После изменения 1 на 255 вам также необходимо разделить результаты для каждого канала на 255, чтобы уменьшить их до соответствующего диапазона. Альтернативой является выполнение промежуточных вычислений с использованием чисел с плавающей точкой вместо целых чисел и деление начальных значений канала на 255,0 (вместо этих других изменений), чтобы получить значения в диапазоне 0..1.

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

r = src[px0]  + inverseAlpha * dest[px0] / 255;

Если ваши исходные данные не имеют предварительно умноженного альфа, то это должно быть:

r = src[px0] * src[px3] / 255  + inverseAlpha * dest[px0] / 255;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...