Тонирование в сторону или от оттенка на определенный процент - PullRequest
5 голосов
/ 23 июня 2010

Я пытаюсь эмулировать Эффект оттенка Open XML. Что он делает, это изменяет оттенок пикселей на изображении, сдвигая оттенок. Требуется 2 параметра: 1) hue (в градусах) и 2) amt (сумма, процент). Это # 2, с которыми у меня проблемы. Спецификация гласит:

Оттенок : смещение значений цвета эффекта в сторону или от оттенка на указанная сумма.

  • amt (Сумма) - указывает, насколько смещается значение цвета.
  • оттенок (оттенок) - указывает оттенок, к которому следует подкрашивать.

Не обращая внимания на конструкцию XML, я могу эмулировать значения, у которых amt составляет 100%. Так, например, если я хочу синий (оттенок: 240 °), я могу создать его ( Тонированный один). Вот пример:

Оригинал и Тонировка (оттенок = 240, сумма = 100%).
Original Modified

Это достигается просто установкой оттенка на 240, сохранением насыщенности и яркости, преобразованием в RGB и записью каждого пикселя.

Вот чего я не могу достичь:

Оттенок = 240 ( синий ), Сумма = 30% , 50% и 80% соответственно
30% 50% 80%

Опять же, в спецификации для Amount указано Определяет, на сколько смещено значение цвета . Я перепробовал здесь все способы, чтобы заставить это работать, но, похоже, не могу (hue=hue*amount, originalhue * amount + hue и т. Д.)

Дополнительные примеры: Hue = 120 ( зеленый ), сумма = 30% , 50% 80% и 100% соответственно. 100% , который я могу получить.
30% 50% 80% 100%

Вот несколько списков значений одного пикселя на картинках выше:

Пиксель 159, 116 - Синие картинки

        <b>Hue    Amount    R    G    B    | H    S     L</b>
<b>Original                 244  196   10  <b>|</b>  48  0.92  0.5</b>
Blue    240     30%      237   30   45  <b>|</b> 356  0.85  0.52
Blue    240     50%      245    9  156  <b>|</b> 323  0.93  0.5
Blue    240     80%      140   12  244  <b>|</b> 273  0.91  0.5
Blue    240    100%       12   12  244  <b>|</b> 240  0.91  0.5

Пиксель 159, 116 - Зеленые картинки

        <b>Hue    Amount    R    G    B    | H    S     L</b>
<b>Original                 244  196   10  <b>|</b>  48  0.92  0.5</b>
Green    120     30%     211  237   30  <b>|</b>  68  0.85  0.52
Green    120     50%     159  237   30  <b>|</b>  83  0.85  0.52
Green    120     80%      81  237   29  <b>|</b> 105  0.85  0.52
Green    120    100%      29  237   29  <b>|</b> 120  0.85  0.52


Итак, вопрос: кто-нибудь знает, как это должно работать? Примечание: это , а не дубликат:

Ответы [ 2 ]

6 голосов
/ 26 июня 2010

Я совершенно уверен, что ваша проблема проистекает из того, как вы интерполируете углы. Вот функция интерполяции (написанная на python), которая должна сделать свое дело. Он основан на предложении из ветки форумов xna Кратчайшая двухмерная интерполяция углов .

def wrap(value, lower, upper):
    distance = upper - lower
    return value - ((value-lower)//distance)*distance

def shortestangle(a,b):
    angle = wrap(b-a, 0, 360)
    if angle>=180: angle -= 360
    return angle

def interpolate(a,b,amount):
    return (a+shortestangle(a,b)*amount)%360

Теперь interpolate(originalHue,hue,amount) должен дать желаемый результат.

Редактировать: Насколько я понимаю, ваша цель состоит в том, чтобы повернуть исходный оттенок к определенному целевому оттенку на определенную величину. Я уверен, что вы уже знакомы с этим, но для иллюстрации приведу цветовое колесо.

Цветовое колесо http://www.sapdesignguild.org/resources/glossary_color/images/color_wheel2.jpg

Проблема в том, что смешивание (или интерполяция) двух углов не является тривиальным, поэтому код, подобный hue = ((hue - originalHue) * amount) + originalHue, работать не будет. Существует бесконечное количество способов перехода из одного угла в другой из-за крутого поворота на 360 °. Чтобы получить угол от 0 ° до 60 °, вы можете повернуть на 60 ° против часовой стрелки, 420 ° против часовой стрелки, 300 ° по часовой стрелке и т. Д. Обычно самый короткий угол - желаемый.

Например, давайте рассмотрим шеи пингвинов: если ваш первоначальный оттенок 30 ° (оранжевый), ваша цель 240 ° (синий) и 50%, вы получите следующие результаты:

//Linear Interpolation
(30° + (240° - 30°)*0.5) = 135° (green)

//"Shortest 2D Angle Interpolation"
(30° + shortestangle(30°,240°)*0.5) % 360 = (30° + (-150°)*0.5) % 360 = 315° (magenta)

Я предполагаю, что второй результат - это тот, который вы ищете, но я могу ошибаться, и ошибка может быть где-то еще полностью ...

1 голос
/ 27 июня 2010

Вам следует взглянуть на TintParams в GDI + (но не в .NET) - это может быть именно то, что вы ищете.

...