Используем фильтр PixelBender’а для двух картинок во Flex
Вот такой незамысловатый эффект получился при использовании pixel bender’а.
На самом деле такой эффект я впервые увидел у Andre Michelle, но сорсов он не выложил. В те времена я написал его на восьмом плеере (AS2), но с выходом новых возможностей решил повторить эксперимент. Обошлось не без приключений, зато код получился без граблей, которые приходилось строить в восьмерке.
Смотреть. (5 мб)
Пишем фильтр
Переменные:
src – первая входная картинка
src2 – вторая входная картинка
white – белый цвет
black – черный цвет
min – значение по которому определяем ставить белый или черный цвет в выходящее изображение
Логика фильтра такова:
- (a1) берем цвет первого пикселя первой картинки
- (a2) берем цвет первого пикселя второй картинки
- (ss) вычитаем из a1 a2
- если разница каждого цвета ss больше min тогда в выходящей картинке на месте первого пикселя будет белый цвет иначе черный
kernel NewFilter
< namespace : "Your Namespace";
vendor : "Your Vendor";
version : 1;
description : "your description";
>
{
input image4 src;
input image4 src2;
output pixel4 dst;
const pixel4 white = float4(1.0, 1.0, 1.0, 1.0);
const pixel4 black = float4(0.0, 0.0, 0.0, 0.0);
const float min = 0.05;
void
evaluatePixel()
{
pixel4 a1 = sampleNearest(src, outCoord());
pixel4 a2 = sampleNearest(src2, outCoord());
pixel4 ss = a1 - a2;
dst = (ss.r>min && ss.g>min && ss.b>min) ? white : black;
}
}
Пишем программу
Чтение кода не должен вызвать затруднений, только поясню некоторые вещи.
bmp1 – отпечаток картинки видео самого нового кадра
bmp2 – отпечаток bmp1, то есть предыдущий кадр от самого нового
bmp3 – результирующая картинка после применения фильтра PixelBender’а
cmf – фильтр который вычитает из всех пикселей картинки альфу по 10
out – картинка которую мы видим, на нее каждый кадр накладывается bmp3, а также фильтр cmf и blur
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shader;
import flash.display.ShaderJob;
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.BlurFilter;
import flash.filters.ColorMatrixFilter;
import flash.geom.Point;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.utils.ByteArray;
[SWF(width=376, height=160, backgroundColor=0×0)]
public class SubtractTv extends Sprite {
[Embed(source="../assets/kutu.pbj", mimeType="application/octet-stream")]
private var pbj:Class;
private var wid:uint = stage.stageWidth;
private var hei:uint = stage.stageHeight;
private var video:Video;
private var nc:NetConnection;
private var ns:NetStream;
private var bmp1:BitmapData;
private var bmp2:BitmapData;
private var bmp3:BitmapData;
private var out:BitmapData;
private var bmp:Bitmap;
private var shader:Shader;
private var shaderJob:ShaderJob;
private var blur:BlurFilter;
private var cmf:ColorMatrixFilter;
public function SubtractTv() {
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
ns.client = new Object();
ns.play("video.f4v");
video = new Video(wid, hei);
video.attachNetStream(ns);
bmp1 = new BitmapData(wid, hei, true);
bmp2 = bmp1.clone();
bmp3 = bmp1.clone();
out = bmp1.clone();
bmp = new Bitmap(out, "auto", true);
addChild(bmp);
shader = new Shader(new pbj() as ByteArray);
shader.data.src.input = bmp1;
shader.data.src2.input = bmp2;
createShaderJob();
addEventListener(Event.ENTER_FRAME, onEnterFrame);
blur = new BlurFilter(3, 3, 3);
cmf = new ColorMatrixFilter([ 1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, -10]);
}
private function onEnterFrame(e:Event):void {
if (shaderJob.progress != 1) return;
bmp2.draw(bmp1);
try {
bmp1.draw(video);
} catch(e:Error) {}
createShaderJob();
out.applyFilter(out, out.rect, new Point(), blur);
out.applyFilter(out, out.rect, new Point(), cmf);
out.draw(bmp3);
}
private function createShaderJob():void {
shaderJob = new ShaderJob(shader, bmp3, wid, hei);
shaderJob.start();
}
}
}
Комментариев пока нет
Ответить
