Как фоторедактор для Android превратился из начальной версии Snapster в официальные фильтры приложения ВКонтакте.

Эта история началась в 2015 году, когда мы начали разработку Snapster, независимого приложения для редактирования фотографий. В то время и в наших официальных приложениях, и в Instagram инструменты для редактирования фотографий были довольно примитивными. Сделайте снимок, сделайте простые изменения цвета с помощью OpenGL-шейдеров и примените текстуры поверх, если вы хотите гламурные изображения. Вызов выполнен.

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

Мы решили, что было бы здорово, если бы пользователи могли создавать свои собственные фильтры прямо с телефона. Процесс создания фильтров должен быть простым, чтобы достойный результат можно было получить простым случайным нажатием кнопки. Более того, редактор должен работать быстро, так как высокое качество исполнения чрезвычайно важно, а это означает, что мы должны максимально использовать возможности, предоставляемые встроенным графическим процессором.

Учитывая, что уникальные фильтры не могут быть созданы из-за регулировки основных параметров (яркость, контраст и т. Д.), Мы решили добавить в редактор полную цветокоррекцию.

Коррекция цвета

Базовый алгоритм цветокоррекции состоит из двух шагов:

  1. Найдите на изображении все пиксели, которые удовлетворяют заранее заданным условиям. Например, если вы хотите заменить все чисто красные пиксели на что-то другое, необходимо найти все пиксели, соответствующие цветовому коду RGB (255, 0, 0).
  2. Измените выбранные пиксели на желаемый цвет.

Звучит довольно просто, но сразу возникло несколько вопросов:

  1. Как можно установить критерии поиска? Очевидно, что условия, когда «компонент R равен 255, а G и B равны 0», трудно воспроизвести на практике. Как можно определить алгоритм, необходимый для выбора пикселей, похожих на этот цвет?
  2. Как быстро эти пиксели могут быть расположены на изображении? Если условия поиска слишком сложные, то качественной работы можно ожидать только при использовании очень мощных устройств.
  3. Если под критерии поиска попадают пиксели разных цветов, их нельзя строго изменить на цвет N без учета их исходного цвета.

Чтобы найти пиксели желаемого цвета, необходимо определить критерии поиска. Если мы хотим найти все пиксели, которые отличаются от определенного цвета не более чем на N, где N - это динамически заданная ошибка, как это можно сделать? Поскольку различные цвета можно деконструировать на отдельные компоненты, которые представляют собой значения координат, евклидово расстояние можно использовать для вычисления разницы между двумя цветами.

Сначала мы попытались найти необходимые пиксели изображения, измерив расстояние между их значениями цвета RGB. Однако полученные результаты поиска были далеки от идеала. Хотя человеческому глазу пиксели могут показаться очень похожими, на самом деле они могут находиться на значительном евклидовом расстоянии друг от друга. Проблема в том, что изменения цвета RGB очень нелинейны по отношению к человеческому восприятию, а это означает, что небольшое изменение значения RGB может быть очень заметным для человеческого глаза и наоборот. Сравнивать:

Чтобы решить эту проблему, мы перешли к использованию цветовой модели CIELab.

CIELab - это цветовая модель, максимально приближенная к цветовому восприятию человека. В CIELab любой цвет индивидуально определяется яркостью L и двумя хроматическими компонентами: a (расположение между зеленым и фиолетовым) и b (расположение между синим и желтым).

CIELab позволяет оценить разницу цветов, видимую человеческим глазом, с помощью простого вычисления евклидова расстояния между двумя цветами. Другими словами, можно выделить пиксели, которые имеют тот же цвет, что и желаемый, в пределах некоторой ошибки N, установив условие «если евклидово расстояние между Lab-значением некоторого пикселя и Lab-значением X цвет меньше N, пиксель хороший ».

Кроме того, при использовании этой модели для человеческого глаза становится очень естественным процесс замены выбранных пикселей желаемым цветом. Основываясь на том же евклидовом расстоянии, мы также можем рассчитать, как изменить цвет, сохраняя естественное изображение.

Первоначальная реализация

Мы хотели дать пользователям возможность сразу видеть результаты на экране, для чего требуется кроссплатформенное решение. Следовательно, единственный вариант - OpenGL.

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

Автоматическое улучшение нашего редактора основано на технике выравнивания гистограммы. Цель состоит в том, чтобы настроить гистограмму исходного изображения, чтобы она напоминала гистограмму линейной функции. Хотя существует несколько таких методов, мы используем CLAHE.

CLAHE (адаптивное выравнивание гистограммы с ограничением контраста) является адаптивным, поскольку обрабатывается не вся гистограмма изображения, а отдельные ее фрагменты меньшего размера. Контраст ограничен, поскольку контраст изменяется только в указанных пределах, чтобы избежать нежелательного усиления фонового шума в изображении.

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

При первоначальной реализации конвейер редактора выглядел так:

  1. Применение автоусиления с заданной интенсивностью.
  2. Применение основных операций.
  3. Конвертация полученного изображения в Lab.
  4. Применение цветокоррекции.

На этом этапе пользователям была предоставлена ​​возможность выбрать любой цвет в любом количестве для цветокоррекции. В результате шейдер OpenGL собирался динамически в то время, когда пользователь выбирал и редактировал цвета.

Преобразование из RGB в Lab было выполнено без какой-либо оптимизации, что означает, что значение цвета RGB было преобразовано в XYZ и только затем из XYZ в Lab. Оба преобразования требуют больших вычислительных ресурсов, что создает узкое место для всего редактора. Для решения проблемы мы перешли на технологию 3D Lookup Table.

Основная концепция чрезвычайно проста. 3D LUT - это трехмерная таблица, в которой хранятся соответствующие входные и выходные значения цвета. Для любого входного значения в одной цветовой модели мы можем однозначно определить соответствующий выход другой модели. Работает довольно быстро!

Такая организационная схема конвейера оказалась действенной, но, конечно, огромный мир Android-устройств доставлял дополнительные проблемы. К таким проблемам относятся банальная нехватка видеопамяти и невероятно низкая производительность на некоторых устройствах, а также строгие ограничения на количество инструкций, доступных в одном шейдере для некоторых графических процессоров, в результате чего шейдер цветокоррекции не может компилироваться. Даже если проблемы минимальной видеопамяти и низкой производительности могут быть решены за счет снижения разрешения рендеринга на слабых устройствах, проблему количества инструкций решить не так просто. Нам нужно было научиться динамически разбивать шейдер цветокоррекции на части и только тогда, когда это необходимо, поскольку каждый дополнительный шаг на конвейере снижает производительность.

Что дальше?

После выпуска версии 1.0 мы решили добавить больше возможностей редактирования, поэтому мы включили в редактор популярный для фотографов инструмент Tone Curve. Используя кривые в приложении, можно регулировать яркость пикселей в определенных полосах RGB. В этом случае значения пикселей изменяются в соответствии с формой кривой, которую пользователь видит на экране.

Внедрение кривых помогло оптимизировать некоторые основные операции, тем самым позволяя применять кривые, яркость, контраст, выцветание, температуру и оттенок (оттенок) за один проход с использованием трех 1D Lookup Tables.

Использование OpenGL требует строгого ограничения размера выходного изображения, поскольку все текстуры должны храниться в видеопамяти. Некоторые устройства Android в то время с трудом могли визуализировать квадрат размером более 1500x1500 пикселей с помощью нашего конвейера, а мы хотели даже большего. Но если мы ничего не могли сделать с самим редактором, то решение для рендеринга конечного продукта было найдено путем дублирования функциональности конвейера на чистом C. Полученный код мог хранить все промежуточные текстуры в обычной оперативной памяти и использовать все многоядерные возможности процессора на макс. Благодаря этому пользователи даже особо слабых устройств могли сохранять изображения в чрезвычайно высоком разрешении.

Фильтры в основном приложении

Когда пришло время обновить фоторедактор в основном приложении ВКонтакте для Android, мы решили воспользоваться результатами, полученными в Snapster. В настоящее время доступен тот же набор стандартных фильтров, и редактор позволяет переключать фильтры, проводя пальцем по изображению, при этом два фильтра могут одновременно отображаться на экране. Благодаря быстрому смахиванию все происходит мгновенно.

Таких результатов нельзя было достичь, используя полный конвейер редактора Snapster, поскольку он слишком тяжелый и лучше подходит для более точной ретуши фотографий. Тот факт, что почти весь конвейер статичен, играет важную роль в реализации. Если бы Snapster имел возможность изменять любой фильтр по желанию, основное приложение должно было бы предоставлять возможность применения готовых фильтров. Это позволило нам использовать вышеупомянутую технологию 3D Lookup Table при применении фильтров. Вместо преобразования из RGB в Lab мы можем довольно быстро преобразовать цвет из исходной фотографии в цвет фильтра.

Заключение

Нам удалось перейти от неуклюжих изменений цвета к мощному и гибкому инструменту для расширенного редактирования изображений. Теперь он не только работает, но и работает быстро. Snapster стал местом для экспериментов, которые мы можем считать успешными, поскольку продукт представляет собой отличный редактор, которым можно гордиться. Этот опыт помог нам и официальному приложению ВКонтакте, которое потенциально получит некоторые дополнительные функции от Snapster.

Если вы знаете и любите Android, работайте с нами над разработкой приложений, которые миллионы людей используют каждый день.

Вопросы?

Вопросы к автору можно отправлять в официальное сообщество нашего технического блога.