Direct2D. Эффект Brightness. Яркость

Эффект Brightness

Если под яркостью понимать «осветление» или «затемнение», то в Direct2D этого можно добиться, как минимум, тремя эффектами: Brightness, Exposure, HighlightsShadows. Есть еще универсальный эффект цветовой матрицы. Но эффект Brightness своим существованием напрямую отвечает за яркость, поэтому на нем и сосредоточимся.

Что такое яркость?

Вообще, понятия «яркости» и «насыщенности» носят очень интуитивный характер. Поэтому никто толком сформулировать не может. И если неожиданно поинтересоваться: «что значит плоский?», человек начнет что-то изображать ладонью, все время повторяя — «ну, плоский». Вот с яркостью точно также.

Три определения яркости из разных источников.

Определение из Wiki. О субъективности понятия говорит наличие и содержание вкладки «обсуждение» статьи.

Светлота́ (англ. lightness) — одна из основных характеристик цвета наряду с насыщенностью и тоном. Это  субъективная яркость участка изображения, отнесённая к субъективной яркости аналогично освещённой поверхности, воспринимаемой человеком как белая.

Wiki

Определение из блога Юлии Келиди:

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

блог Юлии Келиди

Специализированное определение со SkillBox’а:

Насыщенность и Яркость
SkillBox

[свернуть]

Если сравнивать эффект Brightness с результатами эффекта Saturation, то это разные понятия. В отличие от определения SkillBox’а, яркость одного цвета лежит в диапазоне от абсолютно белого, до абсолютно черного. В то время как насыщенность лежит в интервале от своего самого «сочного» до серого.

Понять степень яркости можно только через сравнительную степень — чуть светлее, чуть темнее, совсем темный и т.д. Если внимательно прочитать определения, то все они говорят об относительности сравниваемого цвета, либо с его окружением, либо с черным цветом, либо с белым.

Яркость, это как точка в евклидовой геометрии — аксиома. То есть то, что мы понимаем даже не мозжечком, а подвздошной чакрой.

Эффект Brightness

Эффект Brightness появился в версии Direct2D 1.1. Минимальные требования Windows 8 или Platform Update for Windows 7. У меня в виртуалке две 7-ки. Так вот, в той, где IE10, этот эффект присутствует.

Для версии 1.1 в стандартной поставке Delphi ничего нет, мы это обсуждали ранее. Поэтому подключаем модуль Winapi.D2DMissing из библиотеки SVGIconImageList.

В этом модуле содержится описание для интерфейсов: ID2D1DeviceContext, ID2D1Image и ID2D1Effect. Остальное ищем и дописываем руками.

CLSID для эффекта Brightness:

Для того, чтобы задать кривую яркости нужны две точки, белая и черная. Чтобы установить их, описываем тип свойств яркости:

Нам понадобится еще один тип и небольшая функция:

Таким образом, итоговая функция для создания эффекта выглядит так:

Кривая яркости

Чтобы посчитать значения пикселей итогового растрового изображения используется передаточная функция. Результатом работы функции является кривая яркости. Форму кривой задают две точки — белая и черная. Рассмотрим рисунок:

Рис.1. Кривая яркости

Слева находится исходник. Справа — изображение, обработанное эффектом яркости. В центре видим диаграмму. Это кривая изменения яркости. По оси X — яркость исходного изображения, по оси Y — посчитанная яркость итогового изображения.

Перетаскивая точки, можно видеть, как меняется яркость правого изображения.

В MSDN описано уравнение, по которому можно построить кривую. На рис.1. кривая строится по указанной в статье передаточной функции. Но есть большое подозрение, что представленное уравнение — неполное.

Передаточная функция

Далее следует перевод фрагмента статьи MSDN.

Эффект Brightness использует белую и черную точки для создания передаточной функции обработки растрового изображения. Следующее уравнение описывает эту функцию. Интенсивность входного сигнала находится в диапазоне от 0 до 1.

1. Для преобразования данных изображения из линейного пространства в нелинейное, используется это уравнение:

2. Обработка изображения происходит в соответствии со следующими значениями:

  • input — значения интенсивности пикселей входного изображения от 0 до 1.
  • WhitePt (x, y) — местоположение кривой преобразования для более ярких пикселей.
  • BlackPt (x, y) — это положение кривой преобразования для более темных пикселей.

3. Обратное преобразование данных изображения в линейное пространство происходит согласно этому уравнению:

Окончательное выходное уравнение и его составные части показаны здесь.

Претензии к функции

Складывается ощущение, что яркость считается по несколько иным законам. Это уравнение — какой-то неполный фрагмент из них. Но это мое личное мнение.

Доводы:

  • Указан расчет коэффициента C, но он нигде не используется.
  • Указан расчет переменной ElbowCalc, но она нигде не используется.
  • Откуда-то свалилась константа 0.37.

Рассмотрим формулу в пункте 1. DtoLogI — на самом деле это расчет X по Y. Если из этой формулы вывести обратное уравнение, то получим следующее:

Latex formula

Последнее слагаемое в знаменателе, ни что иное, как коэффициент С. И формула становится:

Latex formula

Получилось классическое уравнение параболы. Коэффициент С нашел свое применение. Выходит, что в пункте 3 представлена урезанная формула, которая никак не может быть обратной для пункта 1.

Далее, фраза Input ≥ Elbow Point, явно указывает на ElbowPt. Однако, в результате экспериментов оказалось, что ElbowCalc куда более похож на правду.

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

Рис.2. Расчетная (синяя) и реальная (красная) кривые яркости

Если ввести параметры, как на рис.3., то получится кривая 2-го порядка. То есть именно такая, какая должна быть для уравнения параболы. Однако, кривая, построенная по реальным данным, имеет вид прямой.

Рис.3. Теория vs Практика (красная — реальные данные)

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

При этом параболическая кривая явно проигрывает по смыслу просто прямой. Потому что непонятно, зачем вдруг такое замысловатое распределение яркости. Зато с прямой все выглядит логично, понятно, ожидаемо и легко объяснимо.

Решение без функции

От кривой яркости отказываться не хочется. Это очень удобно — манипулировать не числами, а мышкой. Поэтому было сделано следующим образом.

При старте приложения формируется битмап, с вертикально расположенными линиями, цветом от 0 до 255.

Формирование шаблона для кривой яркости

[свернуть]

Когда нужно получить кривую, применяем эффект Brightness к шаблону, и считываем получившуюся яркость. По оси X — значение цвета из шаблона, по оси Y — из получившегося изображения.

Получение реальной кривой яркости

[свернуть]
Рис.4. Шаблон и результат применения эффекта Brightness к шаблону

На рис.4. видно, что при таких заданных точках, помимо эффекта яркости, получаем еще и инвертирование. Это логично, если посмотреть на диаграмму. Чем темнее пиксель в исходнике, тем светлее результат.

Как применять эффект

В предыдущей статье подробно изложено, как рисовать с помощью TDirect2DCanvas. Также, рассказано об интерфейсах ID2D1DeviceContext и ID2D1Effect. Поэтому некоторые детали реализации пропущу.

Примеры

Рис.5. Фото из открытых источников
Рис.6. Оригинал фото
Рис.7. Применен эффект Brightness

У меня таких много. Приведу еще один.

Рис.8. Фото задумчивой девушки
Рис.9. Фото задумчивой девушки в приятном полумраке
Рис.10. Фото задумчивой девушки на съемках сериала в освещенном павильоне

Скачать

Исходники (Delphi XE 7-10) 2.84 Mб

Исполняемый файл D2DEffects 0.1 (zip) 2.78 Мб


5 2 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
2 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Alexey
Alexey
1 месяц назад

Однако, забавно, что уравнение кривой яркости на MSDN не совсем некорректное. А если посмотреть иные источники? Наверняка ведь принцип рассчёта тот же. Но не это главное, главное, что эффект работает и показано, как его использовать.

Надеюсь, в следующих статьях будет затронут и упомянутый Saturation, и контраст, и, что особо интересно, есть ли в D2D эффект перецвечивания, оно же пигментация, оно же hue ( http://en.wikipedia.org/wiki/Hue )?
Вообще, имхо, все эти эффекты из теории цвета напрашиваются в отдельный подцикл — яркость, контраст, насыщенность, пигментация, изменения цветовой температуры….

Вообще, как по мне, то тема крайне интересная, так как на практике применений может быть множество, начиная от банальной настройки отображения UI и обработки фотографий, заканчивая, например, подбором гаммы из N сочетаемых между собой цветов (полезно, например, для разработки все того же UI, что бы он не был вырвиглазным, если у программиста не очень развито чувство цветовой гармонии))).

А в целом — благодарствую за статью, как обычно, материал на высоте. Спасибо!

2
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x
()
x