Статьи

Управляйте визуальными эффектами с помощью ColorMatrixFilter и ConvolutionFilter

ColorMatrixFilter и ConvolutionFilter могут использоваться для визуального преобразования ваших объектов Flash. В этой статье я покажу вам, как легко ими манипулировать, используя классный инструмент, который я создал для простых экспериментов.




Ребята, вы когда-нибудь экспериментировали с фильтрами ColorMatrix и Convolution от Flash? Я копался в квесте, чтобы найти интересные вещи, которые можно сделать с помощью Flash, и наткнулся на них. Экспериментируя с ними, можно получить удивительные результаты.

Я написал EffectsTester, чтобы было легко экспериментировать с ними. Посмотрите на эти камшоты, которые я сделал, играя с ним:

Энди Уорхол пожирает твое сердце.

Теперь, если вам это интересно, позвольте мне рассказать вам о том, что представляют собой эти два фильтра.

Фильтр цветовой матрицы используется для управления цветом экранного объекта.

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

Изображение из Wikimedia Commons. Спасибо Майку Хорвату и якоболусу.

Изображение из Wikimedia Commons. Спасибо Майку Хорвату и якоболусу.

Количество красного в пикселе может варьироваться от нуля (вообще никакого красного) до 255. То же самое для зеленого и синего. Итак, на изображении выше вы можете видеть, что чистый желтый пиксель имеет красный = 255, а зеленый = 255. Белый имеет красный, зеленый и синий, все настроены на 255. У черных все три установлены на ноль.

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

Во-первых, давайте сосредоточимся на этих трех значениях:

Давайте по очереди обозначим эти значения a [0], a [1] и a [2]. Теперь подумайте только об одном пикселе во всем исходном изображении (подойдет тот, который находится в верхнем левом углу). Давайте назовем количество красного в этом srcR , количество зеленого srcG и количество синего srcB .

Вопрос в том, сколько красного будет в этом пикселе конечного изображения, destR ? Flash использует этот расчет:

1
destR = ( a[0] * srcR ) + ( a[1] * srcG ) + ( a[2] * srcB );

Здесь вы можете видеть, что a [0] равно 1, а a [1] и a [2] равны нулю, поэтому:

1
2
3
destR = ( 1 * srcR ) + ( 0 * srcG ) + ( 0 * srcB );
//which means…
destR = srcR;

Там нет изменений! Но что если мы изменили a [0] на ноль и a [1] на 1? Потом:

1
2
3
destR = ( 0 * srcR ) + ( 1 * srcG ) + ( 0 * srcB );
//which means…
destR = srcG;

… количество красного в целевом пикселе будет равно количеству зеленого в исходном пикселе! Кроме того, если вы изменили вторую строку на «1 0 0» , то количество зеленого в целевом пикселе будет равно количеству красного в исходном пикселе; вы бы поменяли их местами, и ваша оранжевая рыба превратилась бы в зеленую:

Красная рыба
Зеленая рыба

Вы, вероятно, задаетесь вопросом о столбце A и строке и о столбце Offset . Ну, А означает альфа, что означает прозрачность. Значения A имеют почти такой же эффект, как и значения RGB, но поскольку ни одно из этих образцов изображений не является прозрачным, продемонстрировать это сложно. Столбец «Смещение» позволяет просто увеличивать или уменьшать количество красного, синего или зеленого в целевом пикселе: введите -255 в столбце «Смещение» строки R, и вы увидите, что на изображении больше нет красного.

Я понимаю, что это сложно понять, просто прочитав об этом, поэтому мы рассмотрим некоторые интересные примеры эффектов. В любом случае, это намного веселее. Но сначала, для любопытства, вот фактическая математическая формула, которую использует Flash:

1
2
3
4
destR = ( a[0] * srcR ) + ( a[1] * srcG ) + ( a[2] * srcB ) + ( a[3] * srcA ) + a[4];
destG = ( a[5] * srcR ) + ( a[6] * srcG ) + ( a[7] * srcB ) + ( a[8] * srcA ) + a[9];
destB = ( a[10] * srcR ) + ( a[11] * srcG ) + ( a[12] * srcB ) + ( a[13] * srcA ) + a[14];
destA = ( a[15] * srcR ) + ( a[16] * srcG ) + ( a[17] * srcB ) + ( a[18] * srcA ) + a[19];

(Каждое из значений, которые вы видите в матрице 5×4, может варьироваться от -255 до 255.)

Взгляните на образец изображения «Color Chart»:

Теперь предположим, что вы хотите удалить весь красный цвет с картинки. Просто установите все значения в строке R на ноль:

Это означает:

1
2
3
4
5
destR = ( 0 * srcR ) + ( 0 * srcG ) + ( 0 * srcB ) + ( 0 * srcA ) + 0;
//which means:
destR = 0 + 0 + 0 + 0 + 0;
//so:
destR = 0;

Теперь предположим, что вы хотите добавить еще немного зеленого, где раньше был красный. Поставьте «1» на входе 0x1, чтобы строка G гласила «1 1 0 0 0»:

Давайте теперь добьемся чего-то очень странного, изменив строку G на «0 -1 0 0 50»:

Что сейчас произошло? Например, если в каком-то случайном пикселе у вас был зеленый = 30, он был умножен на ‘-1’, а затем добавлено 50, поэтому результат будет: (30 * -1) + 50 = 20.

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

1
2
3
4
5
6
7
8
9
destG = ( 0 * srcR ) + ( -1 * srcG ) + ( 0 * srcB ) + ( 0 * srcA ) + 50;
//remember srcG = 51:
destG = 0 + (-51) + 0 + 0 + 50;
//so:
destG = — 51 + 50;
//so:
destG = -1;
//but a pixel can’t have a negative amount of green, so this is just set to zero:
destG = 0;

Теперь попробуйте это:

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

Икс

Здесь только пиксели с количеством зеленого меньше 50. Чем темнее пиксель, тем больше зеленого цвета в исходном изображении. Это основной принцип в любом случае. Я знаю, на первый взгляд это может показаться сложным, но поиграйте с этим, и в конце концов вы получите это 🙂

Хорошо, давайте перейдем к чему-то стандартному: изображение в градациях серого. Измените свою матрицу следующим образом:

У вас есть оттенки серого. Ницца 🙂

Давайте достигнем другого популярного цветового состояния: Inverted Colors.

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

1
2
3
destR = 255 — srcR;
destG = 255 — srcG;
destB = 255 — srcB;

Но это легко! Все, что нам нужно сделать, это установить матрицу следующим образом:

Тада! Электрическая рыба:

Большинство из более экзотических эффектов, которые могут быть достигнуты с помощью ColorMatrixFilter, выполняются путем установки отрицательного значения для цвета и положительного значения для смещения — или наоборот. Положите «-1» от 0x3 до 2×3 (альфа) и 255 для смещения альфы (4×3).
Ух ты, теперь я знаю теперь, как они сделали Терминатор 2 🙂

Честно говоря, я не совсем уверен в том, что я только что сделал — через какое-то время становится очень сложно отслеживать вычисления.

Хотя можно понять, как ColorMatrixFilter работает с математической точки зрения, в действительности это будет вопрос игры с ним. Вы никогда не можете быть точно уверены, что произойдет, когда вы введете какие-то конкретные значения. Вот почему я сделал этот EffectsTester. Так что поиграй. Сделайте себя металлическим зеленым, или красным, или бесцветным.

Когда у вас есть эффект, который вам нравится, вы можете применить его к любому DisplayObject (MovieClip, Sprite, Bitmap …) в вашем собственном коде, например так:

01
02
03
04
05
06
07
08
09
10
//first import ColorMatrixFilter up at the top of your code:
import flash.filters.ColorMatrixFilter;
 
//…later on:
var filters:Array = new Array();
//for everything after » = new», copy and paste from the «Grab The Code» box of EffectsTester:
var cmf:ColorMatrixFilter = new ColorMatrixFilter(new Array(-1,0,0,0,255,0,-1,0,0,255,0,0,-1,0,255,0,0,0,1,0));
//the next two lines apply the filter to your display object:
filters.push( cmf );
myDisplayObject.filters = filters;

Теперь давайте посмотрим на фильтр свертки.

Из справочника по классу Adobe:

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

ConvolutionFilter проходит через все пиксели экранного объекта. Для каждого из них он использует значение центра в матрице в качестве значения текущего пикселя, которым манипулируют. Например, в матрице 3 x 3 центральное значение равно (1, 1). Затем он умножает значения из матрицы на окружающие пиксели и добавляет результирующие значения для всех пикселей, чтобы получить значение для результирующего центрального пикселя.

Понимание точной математики под матрицей Convolution стоит целой новой статьи, поэтому я не буду рассказывать обо всем этом здесь. Если вы хотите попасть в это, проверьте этот пост на adobe.com .

Однако простая игра со значениями в конечном итоге даст вам все возможные эффекты, которых вы можете достичь. И это будет весело 🙂 Итак, посмотрим, что мы можем сделать!

Фильтр свертки использует матрицу, как и фильтр цветовой матрицы. Опять же, значения варьируются от -255 до 255. И снова вы получаете большинство интересных эффектов, комбинируя отрицательные значения с положительными.

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

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

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

Теперь уменьшите значение «делителя» до «-1», чтобы стать солдатом на задании ночью.

Многое может быть достигнуто, если вы еще немного удерживаете кнопку мыши 🙂 Опустите и поднимите некоторые значения до крайности. Не забудьте отрегулировать «делитель» — это важно. Увеличьте свою матрицу. Сделайте это 5×5, например.

Чтобы применить эффект в своем собственном коде, используйте объект filters , как вы это делали для ColorMatrixFilter:

01
02
03
04
05
06
07
08
09
10
//first import ConvolutionFilter up at the top of your code:
import flash.filters.ConvolutionFilter;
 
//…later on:
var filters:Array = new Array();
//for everything after » = new», copy and paste from the «Grab The Code» box of EffectsTester:
var cf:ConvolutionFilter = new ConvolutionFilter(3,3,new Array(1,0,-10,-2,3,1,6,1,-1),0);
//the next two lines apply the filter to your display object:
filters.push( cf );
myDisplayObject.filters = filters;

Наконец: попробуйте объединить оба фильтра.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
//first import the filter classes up at the top of your code:
import flash.filters.ColorMatrixFilter;
import flash.filters.ConvolutionFilter;
 
//…later on:
var filters:Array = new Array();
//for everything after » = new», copy and paste from the «Grab The Code» box of EffectsTester:
var cmf:ColorMatrixFilter = new ColorMatrixFilter(new Array(-1,0,0,0,255,0,-1,0,0,255,0,0,-1,0,255,0,0,0,1,0));
var cf:ConvolutionFilter = new ConvolutionFilter(3,3,new Array(1,0,-10,-2,3,1,6,1,-1),0);
 
//the next three lines apply the filters to your display object:
filters.push( cf );
filters.push( cmf );
myDisplayObject.filters = filters;

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