Как стать автором
Обновить

«Hue» во флэше работает неправильно — интриги, расследования

Время на прочтение3 мин
Количество просмотров1.9K
Все руки не доходили поделиться с комьюнити довольно-таки критическим багом, найденном во флэше (по крайней мере, в CS5 — точно).

Оказывается, фильтр Adjust Color → Hue работает некорректно.

Расскажу по-порядку…

Преамбула или «как мы нашли грабли».


Началось все с того, что в нашем проекте (упоминал его в предыдущем хабратопике) мы позволяли создать юзеру всяких зверушек-существ (а-ля Spore) из заранее нарисованных частей. Плюс — у существа есть туловище/ноги/руки, которые генерируются динамически. Художнику было дано задание нарисовать части тела в «чисто-зеленых» цветах. Т.е. используя цвета типа #008800, #00FF00, #002200. Цвет тела существа тоже генерился чисто зеленым.

Все было ок, пока мы не решили ввести разные раскраски. Т.е. из зеленого существа необходимо было получить другой цвет.



Казалось бы, — все просто. Меняем оттенок (hue) и все отлично. Делаем так:

public static function getHueFilter(hue: Number): ColorMatrixFilter {

  var a: AdjustColor = new AdjustColor();
  a.hue = hue;
  a.saturation = 0;
  a.brightness = 0;
  a.contrast = 0;
  return new ColorMatrixFilter(a.CalculateFinalFlatArray()); 
}


* This source code was highlighted with Source Code Highlighter.


И тут-то начались проблемы. Цвет, сдвинутый ровно на 120 градусов вместо чисто-синего превращался в «грязный» синий. А т.к. туловище и конечности у нас раскрашивались ожидаемым «чистым» синим, то имелось явное несоответствие цветов.

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

Но проблема осталась непонятной.

Эксперимент


В попытках докопаться до истины, я провел простой эксперимент. Уже не касаясь ActionScript'а, а чисто в пределах самого Флэша.
  1. создал квадрат с заливкой #008800
  2. преобразовал в муви-клип
  3. сделал копию
  4. на копию добавил фильтр «Adjust Color», где везде нули кроме Hue=120
  5. получил то, что на скрин-шоте ниже — синий цвет нифига не синий



Проверил несколько раз… Логика подсказывала, что такого быть не может. Факты же этому противоречили…

Но результат — налицо.

Проведя такой эксперимент для чистых ярких красного/синего/зеленого — #FF0000, #0000FF, #00FF00 — я получил еще один пруф некорректной работы фильтра во флэше. Кроме того, как можете видеть — на ярких цветах ошибки фильтра еще более очевидны.

Заодно на скрине привел результат работы такого же фильтра в PhotoShop'е. Который, как и ожидалось, поворотом зеленого на 120 градусов, получал точно такой же чистый синий. Без каких-либо примесей.


«Грязнота» полученных цветов видна невооруженным пипеткой глазом. Точнее, полученного синего из поворота зеленого. Полученные из поворота красного и синего, несмотря на свою цветовую «чистоту», почему-то потеряли в яркости. Поворот на угол -120° также дает неверные результаты.

Объяснение.


Как оказалось (спасибо за наводку хабраюзеру lsdima), эффект объясним.

Дело в том, что флэшовский ColorMatrixFilter работает исключительно с цветовым пространством RGB, пытаясь применить ко всем пикселям одну единую матрицу. Для решения же задачи сдвига hue, необходимо перевести все пиксели из RGB в HSL, выполнить преобразование в HSL-пространстве, а потом перевести обратно. С помощью матричных преобразований в RGB-пространстве это невыполнимо.

В то же время никаких инструментов для матричных преобразований в HSL-пространстве во флэше почему-то нет.

Отсюда понятно, почему hue на ColorMatrixFilter работает некорректно.

А т.к. при наложении эффекта «Adjust Color → Hue» в самом флэше, по сути выполняется тоже самое — то и в самом флэше мы получаем тот же результат.

Однако, лично я считаю, что это в корне неправильно. Ведь абсолютно все графические редакторы показали нам, как именно должен работать эффект сдвига hue. И когда во флэше ты берешь и накладываешь привычный hue-эффект, то ожидаешь увидеть вовсе не то, что видишь. Возникает путаница из-за того, что флэш использует общепринятый термин «hue» для обозначения эффекта, который по сути делает несколько другое.

Но факт — есть факт. Имейте в виду.

Выводы.


1. Эффект «hue» во флэше по сути является каким-то «pseudo-hue», пытающимся эмулировать эффект сдвига оттенка не совсем применимыми для этого инструментами.
2. Для полноценного (корректного) эффекта сдвига hue, необходимо попиксельное преобразование изображения в пространство HSL. Во флэше почему-то подобных инструментов нет. Странно, ведь другие эффектры попиксельной обработки изображения существуют (например, тот же blur).

Следовательно, корректный hue-эффект во флэше возможен только в двух случаях:
1. Вручную преобразовав мувик в bitmap и обработав каждый пиксель по отдельности, затратив на это кучу процессорных ресурсов.
2. Когда Adobe добавит классы матричных преобразований в HSL-пространстве. Что-то типа HSLColorMatrixFilter.

Постскриптум


Хабраюзер GeneralSpecific советует обратить внимание на технологию Pixel Bender, доступную в т.ч. и во флэше, для решения этой проблемы. Честно говоря, с ней не сталкивался, так что ничего сказать не могу.
Теги:
Хабы:
+54
Комментарии41

Публикации

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн