Просто в теории: как альфа-компонент предварительно умножается на другие компоненты PNG в iPhone OS, и как он может быть правильно умножен?
На самом деле, я думал, что будет легкий способ добиться этого. Что мне нужно, так это чистая альфа-информация. Для тестирования у меня есть PNG размером 50 x 55 пикселей, где на каждом краю прямоугольник 5x5 пикселей полностью прозрачен. В этих областях альфа должна быть 0. В любом другом месте она должна быть 255. Я убедился, что мой PNG создан правильно, и он также выглядит правильно.
Пожалуйста, скажите мне, если это теоретически правильно: я создал CGImageRef, который имеет только альфа-канал и ничего больше. Это делается с помощью CGBitmapContextCreate и kCGImageAlphaOnly в качестве параметра. CGBitmapContextGetBitsPerPixel(context) возвращает мне 1, так что это указывает на то, что у меня действительно только один компонент на пиксель: желаемое альфа-значение. Я читал, что CGBitmapContextCreate будет обрабатывать все преобразования из данного изображения в новый созданный контекст. Мое изображение ранее было PNG-24 с прозрачностью, но pngcrunch из Xcode, похоже, как-то их конвертирует.
Итак, просто в теории: есть ли у меня хоть какой-то шанс добраться до правильной, неумноженной альфы на данный момент? Кажется, что значения, которые я получаю, почти совпадают, но в большом прозрачном квадрате 5x5 я получаю значения, такие как 19, 197, 210, 0, 0, 0, 98 и так далее. Если бы они были правдой, я бы увидел что-то на картинке. Само изображение сплошное синее.
3 ответа
Преумножение не влияет на альфа-канал, оно влияет на цветовые каналы.
Формула для растрового композитинга (наложение одного растрового изображения поверх другого):
dst.r = src.r * src.a + dst.r * (1.0 - src.a);
dst.g = src.g * src.a + dst.g * (1.0 - src.a);
dst.b = src.b * src.a + dst.b * (1.0 - src.a);
Преумножение обрезает первое выражение умножения:
dst.r = src.r′ + dst.r * (1.0 - src.a);
dst.g = src.g′ + dst.g * (1.0 - src.a);
dst.b = src.b′ + dst.b * (1.0 - src.a);
Это работает, потому что исходные компоненты цвета уже умножены на альфа-компонент - отсюда и название "предварительно умножено". Теперь не нужно их умножать, потому что у него уже есть результаты.
неумноженная альфа
Сам альфа-компонент никогда не умножается заранее: на что бы вы его умножили? Компоненты цвета предварительно умножаются на альфа.
Поскольку предварительное умножение значений цвета является простым, как:
r = (r * a) / 255;
g = (g * a) / 255;
b = (b * a) / 255;
Получение обратного будет:
if (a > 0) {
r = (r * 255) / a;
g = (g * 255) / a;
b = (b * 255) / a;
}
Эта формулировка не верна. Цель состоит в том, чтобы найти немультиплексированные (r, g, b), которые в последствии приводят к тем же мультиплексированным значениям (однако невозможно найти исходные значения r, g, b).
Однако с формулой выше мы находим для примера
alpha = 100
r_premulti = 1
реконструированный г = 2;
Позднее, если этот r снова мультиплексируется, мы находим 2 * 100 / 255 = 0, но вместо этого мы хотели r_premulti == 1!!
Правильная формула должна округляться. Пример для r-компонента:
reconstruced r = ceiling(r_premulti * 255 / alpha)