Введение
Pixel Bender – был разработан в недрах лаборатории Адоби, для того, чтобы дать разработчику возможность внедрять свои алгоритмы по обработке изображений на низком уровне в приложения: Flash, Flex, AiR, After Effects, Photoshop.
Хузяйке на заметку:
1) Перед тем как читать данную статью, советую вам посмотреть мои видео-уроки по пиксель бендеру(http://flastar.ru).
2)Скачайте Pixel Bender.( http://www.adobe.com/go/pixelbender_toolkit)
3) Примерно по такому пути найдите две пдфки C:\Program Files\Adobe\Adobe Utilities\Pixel Bender Toolkit\docs\ Если будут возникать вопросы в процессе написания фильтров или будет желание изучить его более подробнее, то бращаться желательно к ним т.к. это единственная официальная документация по PB на сегодняшний день.
Язык Pixel Bender
Сначала рассмотрим процесс создания фильтров в PB.
1) Мы
его пишем
2) Для того, чтобы хоть как-нибудь динамически контролировать фильтры, лабораторные Адоби-парни сделали специально для этого ползунки(один ползунок одна переменная, созданная вами) в правой части, для изменения значения переменных в фильтре.
3) Тестируем
4) Экспортируем в байт-код и сохраняем его в файл с расширением PBJ
PB язык, это CИ-подобный язык. Постараюсь как меньшге теории)
![]()
Это наш шаблон для любого фильтра. Чтобы он появился в редакторе кода, нажмите Ctrl+N
В тэге kernel описывается фильтр. Описание, версия, автор ну и т.д.
input это то, что к нам приходит из внешнего мира, т.е. входящая картинка. В данном примере инпут будет типа image4 и название его экземпляра будет src.
Output это
то, что у нас получается в результате. Тип
pixel4, у него есть 4 параметра: a(alpha),
r(red channel), b(blue channel), g(green channel).
Функция evaluatePixel, вызывается для каждого пикселя. Для того, чтобы узнать какой пиксель обрабатывается в данный момент нужно использовать outCoord(), это переменная типа float2, вектору которого два параметра, x и y.
Векторы:
float2 bool2
int2 pixel2
float3 bool3
int3 pixel3
float4 bool4 int4 pixel4
Инициализируются
они так:
vector_type(element1 [, element2…])
Пример: float3(0.5,
0.6, 0.7)
В PB есть свизлинг, и это очень
чотко(не могу не употребить это слово). Пример:
float3 vec3;
float2 vec2;
vec3.xy = vec2; // другими словами: vec3.x=vec2.x; vec3.y = vec2.y; vec3.z – не
изменяется
vec3.xz = vec2; //другими словами: vec3.x=vec2.x; vec3.z = vec2.y; vec3.x – не изменяется
vec3.yz *= vec2.yy; //другими словами: vec3.y *=vec2.y; vec3.z *= vec2.y; vec3.x – не изменяется
Матрицы:
float2x2
float3x3
float4x4
Примеры:
float2x2( float2, float2 );
float2x2( float, float, float, float );
float3x3( float3, float3, float3 );
float3x3( float, float, float, float, float, float, float, float, float );
float4x4( float4, float4, float4, float4 );
float4x4( float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float );
Обращаться к ним по такому шаблону:
matrix[ column
][ row ]
Массивы:
ВНИМАНИЕ! В PB использовать
массивы нельзя, если вы пишите фильтр для FlashPlayer.
Void:
Все функции, которые ничего не
возвращают должны быть объявлены как void.
Математические функции:
11
Все математические функции можно найти в PixelBenderLanguage10.pdf на стр.28 Там всё аккуратно показано и рассказано)
Создание динамичных параметров:
parameter int angle
<
minValue : 0;
maxValue : 360;
defaultValue : 30;
>;
Переменная angle, типа int, может
иметь все значения в диапазоне [0; 360], первое значение = 30.
Создание Фильтров
Запускаем PB. Нажимаем Ctrl+N. Внимательно смотрим.
Что такое dst = sampleNearest(src,outCoord()); ?
PB обрабатывает и выводит изображение по пикселю. Переменная dst и есть пиксель, у него 4 параметра a(alpha), g(green channel), r(red channel), b(blue channel). С помощью функции sample, sampleLinear, sampleNearest мы можем определять пиксель в координатах исходного изображения. Sample и sampleLinear одинаковы. А вот sampleNearest немножко отличается, если он видит, что пиксель находящийся на заданных координатах пуст (т.е. не существует), то он возвращает самый близкий по координатам пиксель.
outCoord(), как вы уже догадались имеет тип float2.
По-русски:
sampleNearest(изображение, float2(координатаХ, координатаY));
Не секрет,
для того, чтобы осветлить изображение нужно повысить значение каналов. Повышаем:
dst +=
sampleNearest(src,outCoord());
dst +=
sampleNearest(src,outCoord());
dst +=
sampleNearest(src,outCoord());
Нажимаем кнопку Run. И видим, что у нас изображение стало светлее.
Осталось разобраться с осями. В пиксель бендере оси направлены так:
![]()
Теперь попробуем сместить наше изображение на 10 пикселей выше и на 15 пикселей левее. Для этого пишем:
dst = sampleNearest(src,outCoord()+float2(15,10));
По правилу свизлинга получиться так:
outCoord()+float2(15,10) = float2(outCoord().x+15,
outCoord().y+10);
Как я люблю свизлинг) И слово то какое, чоткое)
Теперь попробуем копировать пиксели.
Возьмем пример. Заполним все пиксели с координатой x меньше 50, y’ками с пикселей в координате x 50.
if(outCoord().x<float(50))
{
dst =
sampleNearest(src,float2(float(50), outCoord().y));
}
else
{
dst = sampleNearest(src,
outCoord());
}
Вот что должно получится:
![]()
Теперь попробуем создать пучок света на изображении.
Как говорилось выше, чтобы сделать пиксель светлее нужно увеличить значение каналов.
Возьмем некую координату пучка света, допустим, это будет параметр
float2 center = float2(100,100);
возьмем размер свечения 200
Для того чтобы придать правильное значения каждому пикселю, нужно делить размер нашего свечения на расстояние от его центра до текущего пикселя.
dst = 200/distance(outCoord(),
center) * sampleNearest(src, outCoord());
Вот что получится
![]()
Далее попробуем сделать эффект пикселизации:
![]()
Допустим, нам требуется сделать пиксели размером 5x5. Цвет этого большого пикселя мы будем брать из его верхнего левого угла. По мере обхода пикселей, мы будем делить каждую координату на размер большого пикселя, тем самым мы узнаем какой он стоит по счету m и n. Далее нужно умножить m(номер большого пикселя по x) и n(номер большого пикселя по y) на размер большого пикселя. Теперь мы узнаем координату верхнего левого угла большого пикселя.
float2 sc = floor(outCoord() /
float2(dimAsFloat, dimAsFloat));
sc *= dimAsFloat;
outputPixel =
sampleNearest(inputImage, sc);
Теперь попробуем реализовать блур.
Создадим «контейнер» в который будем добавлять наше изображение со смещением.
float4 outpixel;
outpixel +=
sampleNearest(src,outCoord()+float2(1,1)); // Сместили влево, вверх
outpixel +=
sampleNearest(src,outCoord()+float2(1,-1)); // Сместили влево, вниз
outpixel +=
sampleNearest(src,outCoord()+float2(-1,1)); // Сместили вправо, вверх
outpixel += sampleNearest(src,outCoord()+float2(-1,-1));
// Сместили влево, вниз
dst = outpixel / float(4.0); // Выводим полученный пиксель, не забывая уменьшить значение канала путем деления. Если мы не поделим, то изображение получиться яркое и контрастное.
Вот результат:
![]()
Фильтр crossStitch
![]()
![]()
![]()
![]()
Его можно найти в Adobe Pixel Bender Exchange. Немного подумаем по поводу реализации. Сам фильтр превращает картинку в сетку, т.е. на выходе изображение содержит меньше половины пикселей чем оригинал. Следовательно по мере обхода каждого пикселя входящего изображения (функция evaluatePixel) будем смотреть координаты, если пиксель лежит на диагонали квадрата размером size(динамический параметр), то его выводим. Смотрим на реализацию.
![]()
Экспорт PBJ файлов
![]()
Импорт в код
PBJ файлов
Способ № 1
![]()
Загружаем наш PBJ файл.
Создаем экземпляр класса Shader, внутрь пихаем байт-код нашего фильтра
Выставляем динамические переменные в нашем фильтре
Создаем экземпляр класса ShaderFilter, ему передаем объект класса Shader
К нашему DisplayObject применяем фильтр.
Способ № 2
Если вам лень загружать из внешнего мира фильтр, то можно воспользоваться замечательным китайцем PBJ String Generator (http://code.google.com/p/cjlibrarycs4). Копируем байт-код нашего фильтра, вставляем в код и дальше как по маслу)
Способ № 3
Людям юзающим haXe ОЧЕНЬ повезло. Динамическое создание фильтров в haXe, и есть одна из причин полюбить его. Подробнее на http://haxe.org
Где брать готовые
фильтры?
Adobe Pixel Bender Exchange Site (http://www.adobe.com/cfusion/exchange/index.cfm?event=productHome&exc=26)
Petri
Leskinen
(http://pixelero.wordpress.com/category/pixel-bender/)
Mrdoob
(http://www.mrdoob.com/blog/post/586)
Kevin
GoldSmith
(http://blogs.adobe.com/kevin.goldsmith/)
За крутыми алгоритмами лазить сюда http://iquilezles.org/www/index.htm