HSL интерполяция - PullRequest
       22

HSL интерполяция

3 голосов
/ 13 сентября 2009

Если компонент оттенка моего цвета HSL указан в градусах, как я могу правильно интерполировать два оттенка? Использование (h1 + h2) / 2 не дает желаемых результатов во всех случаях. Вот два примера, которые иллюстрируют почему:

Пусть:

красный = 0 °
желтый = 60 °
синий = 240 °

(красный + желтый) / 2 = 30 ° (оранжевый)
(желтый + синий) / 2 = 150 ° (синий зеленый)
(красный + синий) / 2 = 120 ° (зеленый)

Как видите, усреднение красного и синего дает зеленый вместо пурпурного / пурпурного! Однако, если мы позволим:

красный = 360 °
желтый = 60 °
синий = 240 °

(красный + желтый) / 2 = 210 ° (сине-зеленый)
(желтый + синий) / 2 = 150 ° (синий зеленый)
(красный + синий) / 2 = 300 ° (пурпурный)

Теперь красный и синий дают ожидаемый цвет, а красный и желтый - синий и зеленый! Каким образом я могу интерполировать компонент оттенка цвета, чтобы результат соответствовал тому, что можно ожидать от смешивания реальной краски? Спасибо!

Ответы [ 3 ]

3 голосов
/ 13 сентября 2009

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

Вот функция Python, которая выбирает угол между двумя углами на окружности. В основном он просто пробует два варианта (добавляя 360 или нет) и выбирает тот, который дает угол, ближайший к исходным углам:

pairs = [(0, 60), (60, 239), (60, 241), (0, 240), (350, 30)]

def circ_ave(a0, a1):
    r = (a0+a1)/2., ((a0+a1+360)/2.)%360 
    if min(abs(a1-r[0]), abs(a0-r[0])) < min(abs(a0-r[1]), abs(a1-r[1])):
        return r[0]
    else:
        return r[1]

for a0, a1 in pairs:
    print a0, a1, circ_ave(a0, a1)

производит:

0 60    30.0
60 239  149.5  # 60, 240 is ambiguous
60 241  330.5
0 240   300.0
350 30  10.0

(я чувствую, что должен быть более простой способ сделать это вычисление, но мне это не пришло в голову.)

1 голос
/ 13 сентября 2009

Для каждого значения цвета x, x < 360 это может быть x или x+360. Затем у вас есть 4 пары значений цвета. Если вы найдете наименьшую пару расстояний, используйте эту пару для интерполяции цвета. Это может дать вам правильный визуальный эффект.

Например,

красный = 0 ° или 360 °
желтый = 60 ° или 420 °
синий = 240 ° или 600 °

наименьшее расстояние красного и желтого составляет 60 (красный 0 желтый 60), поэтому интерполяция должна быть 30.
наименьшее расстояние желтого и синего составляет 180 (желтый 60 синий 240), поэтому интерполяция должна быть 150.
наименьшее расстояние красного и синего составляет 60 (красный 360 синий 240), поэтому интерполяция должна быть 300.

1 голос
/ 13 сентября 2009

Возможно, вы не хотели этого слышать, но конвертируйте в RGB, интерполируйте и конвертируйте обратно.

edit: только что увидел, что "ожидается смешивание реальной краски"

В этом случае вы, вероятно, захотите преобразовать в цветовое пространство CMY, а не в RGB. Взгляните на смешение цветов в Википедии .

...