Мне не ясно, с какими данными вы работаете. У ваших исходных изображений уже есть альфа-значения, предварительно умноженные, поскольку они сохранены? Если нет, то предварительно умноженная альфа здесь не применима, и вам нужно было бы сделать нормальное альфа смешивание.
В любом случае, большая проблема в вашем коде заключается в том, что вы не отслеживаете диапазоны значений, с которыми имеете дело.
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.