Смешайте два непрозрачных цвета с режимом наложения "оттенок"
Я хочу реализовать цветовое смешение, как описано в спецификации W3C для компоновки и смешивания. (Я делаю это в JavaScript, но язык не должен иметь большого значения для решения моей проблемы.)
В ретроспективе: во время реализации ответа на этот вопрос я понял, что это, вероятно, сделает для довольно приятного отдельного пакета. Если вам интересно, вы можете захватить его из npm.
До сих пор это было очень хорошо, но я хотел бы сделать эти алгоритмы еще одним шагом и добавить поддержку альфа-каналов. Благодаря спецификации SVG-компоновки, обеспечивающей все необходимые формулы, которые были не слишком сложными.
Но теперь я застрял в реализации режимов смешивания, которые спецификация W3C описывает как не разделяемые, которые (как известно из Photoshop ): оттенок, насыщенность, цвет и яркость.
К сожалению, алгоритмы для них недоступны в спецификации SVG, и я понятия не имею, как с ними работать. Я думаю, есть модифицированные версии формулы, предоставленные W3C для работы с альфа-каналами, которые мне не хватает.
Чтобы сделать мою проблему немного более визуальной, я покажу, что Photoshop дает мне оттенок, смешивающий два цвета:
![Пример смешивания оттенков Photoshop для двух непрозрачных цветов]()
Это то, что я также могу воспроизвести с помощью альфа-алгоритма из упомянутой спецификации W3C.
То, что я не могу воспроизвести, - это результат, который дает Photoshop, когда я добавляю нижнюю альфу как на исходный, так и на задний план:
![Пример смешивания оттенков Photoshop с двумя цветами с непрозрачностью 60% каждый]()
Кто-нибудь знает, как добиться этого результата программно?
Обновление 1: Измененные иллюстрации (добавление кодов HSVA и RGBA), чтобы уточнить используемые цвета.
Обновление 2: Чтобы проверить возможные решения, я приложу два других примера смешивания Photoshop:
![Пример смешивания оттенков Photoshop с двумя цветами с различными комбинациями непрозрачности]()
![Пример смешивания оттенков Photoshop с двумя цветами с различными комбинациями непрозрачности]()
Обновление 3: Так получилось, что помимо того, что я не знаю понятия смешивания цветов, я также перепутал настройки Photoshop, поставив задачу решить мой вопрос Еще труднее. Исправлены примеры изображений для возможных будущих прохожих.
Ответы
Ответ 1
Оттенок Hue, который у вас есть на втором изображении, не соответствует формуле композиции альфа-цвета, но скорее отражает композицию Porter Duff alpha Источник Далее, как определено здесь 9.1.4. Source Over и использует следующую формулу:
![Источник по формуле]()
Если вы хотите добиться такого смешения, которое не является подходящим сочетанием оттенков, вы можете использовать следующую фолрулу в javascript:
PDso = { // Ported Duff Source Over
r: ((S.r * S.a) + (B.r * B.a) * (1 - S.a)) / aR,
g: ((S.g * S.a) + (B.g * B.a) * (1 - S.a)) / aR,
b: ((S.b * S.a) + (B.b * B.a) * (1 - S.a)) / aR,
};
// where
// S : the source rgb
// B : the backdrop rgb
// aR : the union alpha (as + ab * (1 - as))
Режим смешивания оттенков с альфа-каналом
Вот скриншот точного источника смешивания оттенков на фоне с использованием формулы композиции альфа-цвета, которую я создал в Photoshop:
![Photoshop Hue Blend Mode]()
Средний квадрат с зелеными выделенными буквами - это правильное представление смешивания. Вот смесь смешивания CSS Hue с цветом источника внутри цвета фона, используя новый CSS mix-blend-mode
(запустите фрагмент кода):
.blends div {
width:140px;
height:140px;
}
.source {
mix-blend-mode: hue;
}
.backdrop.alpha {
background-color: rgba(141, 214, 214, .6);
isolation: isolate;
}
.source.alpha {
background-color: rgba(255, 213, 0, .6);
}
<div id="main">
<div class="blends alpha">
<div class="backdrop alpha">
<div class="source alpha"></div>
</div>
</div>
</div>
Ответ 2
Начиная с здесь
Слияние оттенков создает цвет с оттенком цвета источника и насыщенностью и яркостью цвета фона.
Я могу придумать некоторые формулы, но они могут быть мусором, хотя они полностью воспроизводят исходные номера:
h: hSource + deltaH * (1 - aSrouce) * aBackdrop * 0.41666666 = 50; 63
s: sBackdrop * 0.9 + deltaS * (1 - aBackdrop) * aSource * 0.20833333 = 45; 47.5
l: lBackdrop * 0.957142857 + deltaL * (1 - aBackdrop) * aSource * 0.77 = 67; 63.3
a: 1 - (1 - aSource) ^ 2 всегда совпадает