Причина, по которой предварительное умножение работает, заключается в том, что он фактически заканчивает возведением в квадрат альфа для цели, прежде чем он добавляет исходное изображение к цели
например. Без предварительного умножения мы получаем это для данных исходного изображения:
srcA = origA
srcR = origR
srcG = origG
srcB = origB
И мы получаем это для результирующего изображения применительно к цели:
a = ((srcA * srcA) >> 8) + ((tgtA * (255 - srcA)) >> 8)
r = ((srcR * srcA) >> 8) + ((tgtR * (255 - srcA)) >> 8)
g = ((srcG * srcA) >> 8) + ((tgtG * (255 - srcA)) >> 8)
b = ((srcB * srcA) >> 8) + ((tgtB * (255 - srcA)) >> 8)
Расширяя это, мы получаем:
a = ((origA * origA) >> 8) + ((tgtA * (255 - origA)) >> 8)
r = ((origR * origA) >> 8) + ((tgtR * (255 - origA)) >> 8)
g = ((origG * origA) >> 8) + ((tgtG * (255 - origA)) >> 8)
b = ((origB * origA) >> 8) + ((tgtB * (255 - origA)) >> 8)
Никаких сюрпризов ...
Теперь для предварительно умноженных данных исходного изображения мы получаем:
srcA = (origA * origA) >> 8
srcR = (origR * origA) >> 8
srcG = (origG * origA) >> 8
srcB = (origB * origA) >> 8
Который применительно к цели:
a = (srcA >> 8) + ((tgtA * (255 - srcA)) >> 8);
r = (srcR >> 8) + ((tgtR * (255 - srcA)) >> 8);
g = (srcG >> 8) + ((tgtG * (255 - srcA)) >> 8);
b = (srcB >> 8) + ((tgtB * (255 - srcA)) >> 8);
Хорошо, мы знаем это, но если мы расширим это, вы увидите разницу:
a = (origA * origA) >> 8 + ((tgtA * (255 – ((origA * origA) >> 8))) >> 8);
r = (origR * origA) >> 8 + ((tgtR * (255 - ((origA * origA) >> 8))) >> 8);
g = (origG * origA) >> 8 + ((tgtG * (255 – ((origA * origA) >> 8))) >> 8);
b = (origB * origA) >> 8 + ((tgtB * (255 – ((origA * origA) >> 8))) >> 8);
Сравните это с расширением без умножения:
a = ((origA * origA) >> 8) + ((tgtA * (255 - origA)) >> 8)
r = ((origR * origA) >> 8) + ((tgtR * (255 - origA)) >> 8)
g = ((origG * origA) >> 8) + ((tgtG * (255 - origA)) >> 8)
b = ((origB * origA) >> 8) + ((tgtB * (255 - origA)) >> 8)
И сразу же вы можете видеть, что мы возводим в квадрат значение origA при применении его к цели, это означает, что большее количество цели достигнет результирующих значений цвета.
Если вы возводите в квадрат, я хочу, чтобы больше цели прошло.
Вот почему при предварительном умножении удаляется количество полос вокруг прозрачных блоков, потому что те пиксели с более низкими значениями альфа-канала получают больше целевых пикселей, чем если бы вы не делали предварительное умножение, и это происходит по экспоненте шкала.
Надеюсь, это прояснит ситуацию.