Начну с оффтопа
Начать хотелось бы с предыстории и задачи, которую я решаю на работе. Есть сайт, фотографии на котором при публикации должны подходить под определенное соотношение сторон (3х2). При этом в работе часто возникают определенные трудности. Например, что делать, если автор сделал скрин-шот, который не соответствует этому соотношению?
Здесь помочь может дизайнер, который вставит изображение на подходящий фон, или просто при загрузке выбирать, какую часть изображения придется отрезать. Оба варианта по своим причинам неудобны. Первый — из-за времени, второй — из-за потери содержания. Отсюда и родилась задача написать сервис, который автоматически будет выполнять работу дизайнера: возьмет изображение и поместит его в рамки с необходимым соотношением сторон. Получится примерно следующее:
Развивая эту идею, появилась потребность делать не монохромный фон, пускай и с возможностью задавать любой цвет, а делать градиент, который будет учитывать цвета изображения. Отсюда и родились мои первоначальные расчеты и эта статья.
Дисклеймер
Я ни в коем случае не претендую на уникальность работы и правильность моего подхода и моих расчетов. Не исключаю, что уже существуют готовые формулы и алгоритмы. Но здесь я попытался самостоятельно изучить этот вопрос и погрузиться в тему математики растровых изображений.
Методика построения градиента
Поскольку цветовые компоненты изображения представляют из себя числа, например RGB {173, 217, 54}, то при построении градиента мы имеем переход от одного числа до другого. Здесь сразу вспоминаются школьные арифметическая и геометрическая прогрессии, которые помогут нам в расчетах.
Линейный градиент
Рассмотрим арифметическую прогрессию. В ней каждый следующий элемент отличается от предыдущего на конкретную константу, называемую разностью прогрессии.
Здесь d и есть разность арифметической прогремсии. Из этой формулы можно вычислить следующие параметры:
Именно последняя формула нам и даст необходимый шаг градиента. Под шагом градиента я понимаю то, на сколько цветовая компонента пикселя отличается от пикселя . Условно, параметр R изменился с 201 до 203. Здесь шагом является .
Но какой подход использовать дальше? Из уравнения следует, что существует при любом . Подразумевается, что градиент строится между несколькими пикселями, поэтому условие выполняется всегда.
Далее я предполагаю высчитывать параметр для каждой компоненты пикселя. В моем случае, в формате будут существовать , и . В первом предположении, которое я пока что не тестировал, изменяться они будут независимо друг от друга.
Математика будет следующей: берем у исходного изображения в верхней строке цвет 1-го и последнего пикселей. Вычисляем для каждого из них . В общем случае оно будет представлять вещественное число с плавающей точкой. Представляем каждую компоненту цвета аналогично в виде числа с плавающей точкой и каждый последующий пиксель изменяем по формуле .
Для отображения же конкретного цвета я предполагаю отсекать дробную часть или, по-другому, округлять в меньшую сторону. За счет этого создастся плавный переход от начального цвета к конечному.
Послесловие
Как я уже говорил, я не претендую на истину в последней инстанции. В этой статье я рассмотрел только мои расчеты с использованием арифметической прогрессии. Во второй будут представлены расчеты для геометрической прогрессии.
Скорее всего, моя математика обладает большим количеством пробелов и недостатков, поэтому я буду благодарен любой обратной связи. И опять же повторюсь, что я не претендую на научность, а ищу конкретное решение для конкретной бизнес-задачи.
Автор: neuron-nexus