Используем фильтр PixelBender’а для двух картинок во Flex

stilldre

Вот такой незамысловатый эффект получился при использовании pixel bender’а.

На самом деле такой эффект я впервые увидел у Andre Michelle, но сорсов он не выложил. В те времена я написал его на восьмом плеере (AS2), но с выходом новых возможностей решил повторить эксперимент. Обошлось не без приключений, зато код получился без граблей, которые приходилось строить в восьмерке.

Смотреть. (5 мб)

Пишем фильтр

Переменные:
src – первая входная картинка
src2 – вторая входная картинка
white – белый цвет
black – черный цвет
min – значение по которому определяем ставить белый или черный цвет в выходящее изображение

Логика фильтра такова:
- (a1) берем цвет первого пикселя первой картинки
- (a2) берем цвет первого пикселя второй картинки
- (ss) вычитаем из a1 a2
- если разница каждого цвета ss больше min тогда в выходящей картинке на месте первого пикселя будет белый цвет иначе черный

<languageVersion : 1.0;>

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

package {
   
    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();
        }
       
    }
}

Комментариев пока нет

Ответить