Stage3d AGAL GPU处理照片 旧照片效果 sepia || pixelbender

如果看不到下边的flash,请更新flash player到最新版本。

利用AGAL实现旧照片效果,大家可以对照一下之前一篇文章,关于图像处理(pixelbender)。硬件处理肯定会更快,但这里无法表现出来,毕竟图片就这么小。拖拉进度条,可以设置照片旧的程度。

package 
{
    import com.adobe.utils.AGALMiniAssembler;
    import com.bit101.components.HSlider;
    import com.bit101.components.PushButton;
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.Stage3D;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.display3D.textures.Texture;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.geom.Matrix3D;
    import flash.net.FileFilter;
    import flash.net.FileReference;
    import flash.utils.ByteArray;
    
    import net.hires.debug.Stats;
    
    /**
     * 借用了boycy815的代码框架
     * @author kenkozheng
     */
    [SWF(frameRate="60")]
    public class AGAL_Filter extends Sprite 
    {
        private const WIDTH:Number = 512;
        private const HEIGHT:Number = 512;
        
        //stage3d五巨头
        private var _stage3d:Stage3D;
        private var _context3d:Context3D;
        private var _program3d:Program3D;
        private var _index:IndexBuffer3D;
        private var _vertex:VertexBuffer3D;
        private var _texture:Texture;
        
        [Embed(source=("4.jpg"))]
        private var ImageSource:Class;
        
        private var _vertexProgram:String = "mov op, va0\n" +
                                        "mov v0, va1";            //传递给片段shader坐标值
        
        private var _fragmentProgram:String = "tex ft1, v0, fs0<2d,linear,nomip>\n" +
                                            "m44 ft2, ft1, fc1\n" +            //颜色变换
                                            "mul ft2, ft2, fc0.x\n" +        //效果图跟原图做multiply,向量float4 * float = float4,类似PixelBender
                                            "mul ft1, ft1, fc0.y\n" +
                                            "add ft2, ft2, ft1\n" +
                                            "mov oc, ft2";
        
        public function AGAL_Filter():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            removeEventListener(Event.ADDED_TO_STAGE, init);
            _stage3d = stage.stage3Ds[0];
            _stage3d.addEventListener(Event.CONTEXT3D_CREATE, onCreate);
            _stage3d.requestContext3D();
            addChild(new Stats());
        }
        
        private function onCreate(e:Event):void
        {
            e.target.removeEventListener(Event.CONTEXT3D_CREATE, onCreate);
            
            _context3d = _stage3d.context3D;
            _context3d.enableErrorChecking = true;
            
            var agal:AGALMiniAssembler = new AGALMiniAssembler();
            
            var vp:ByteArray = agal.assemble("vertex", _vertexProgram);
            var fp:ByteArray = agal.assemble("fragment", _fragmentProgram);
            _program3d = _context3d.createProgram();
            _program3d.upload(vp, fp);
            _context3d.setProgram(_program3d);
            
            _context3d.configureBackBuffer(WIDTH, HEIGHT, 0, false);
            _context3d.setBlendFactors("one", "zero");
            _context3d.setCulling("back");
            
            //两个三角形拼成平面
            _index = _context3d.createIndexBuffer(6);
            _index.uploadFromVector(new<uint>[0, 1, 2, 0, 2, 3], 0, 6);
            
            _vertex = _context3d.createVertexBuffer(4, 4);
            //这是由于纹理的坐标原点是左上角,y轴向下,最大值为1最小值为0
            //而顶点的坐标原点则是在舞台中央,而且y轴向上,最大值为1最小值为-1
            //那么(-1,-1)点对应的纹理就是(0,1)
            _vertex.uploadFromVector(new<Number>[
                //x, y, u, v
                -1, -1, 0, 1,
                -1, 1, 0, 0,
                1, 1, 1, 0,
                1, -1, 1, 1], 0, 4);
            _context3d.setVertexBufferAt(0, _vertex, 0, "float2"); //xy坐标
            _context3d.setVertexBufferAt(1, _vertex, 2, "float2");    //uv坐标
            
            //纹理位图
            var bt:Bitmap = Bitmap(new ImageSource());
            var btmap:BitmapData = new BitmapData(WIDTH, HEIGHT);
            btmap.draw(bt);
            
            //上传纹理
            _texture = _context3d.createTexture(btmap.width, btmap.height, "bgra", false);
            _texture.uploadFromBitmapData(btmap);
            _context3d.setTextureAt(0, _texture);
            //multiple比例
            _context3d.setProgramConstantsFromVector("fragment", 0, new<Number>[1, 0, 0, 0]);
            //颜色矩阵
            _context3d.setProgramConstantsFromMatrix("fragment", 1, new Matrix3D(new <Number>[
                0.393, 0.768, 0.189, 0,
                0.349, 0.686, 0.168, 0,
                0.272, 0.534, 0.13, 0,
                0, 0, 0, 1
            ]));
            
            _context3d.clear(0, 0, 0, 0);
            _context3d.drawTriangles(_index);
            _context3d.present();
            
            start();
        }
        
        private function start():void
        {
            new PushButton(this, 282, 515, "change", onUpload);
            new HSlider(this, 392, 520, onBar).setSliderParams(0, 1, 1);
        }
        
        private function onBar(e:Event):void
        {
            var v:Number = e.currentTarget.value;
            _context3d.setProgramConstantsFromVector("fragment", 0, new<Number>[v, 1-v, 0, 0]);
            _context3d.clear(0, 0, 0, 0);
            _context3d.drawTriangles(_index);
            _context3d.present();
        }
        
        private function onUpload(e:Event):void
        {
            var fr:FileReference = new FileReference();
            fr.addEventListener(Event.SELECT, onSelect);
            fr.browse([new FileFilter("jpg/png", "*.jpg;*.png")]);
        }
        
        private function onSelect(e:Event):void
        {
            e.currentTarget.removeEventListener(Event.SELECT, onSelect);
            e.currentTarget.addEventListener(Event.COMPLETE, onComplete);
            e.currentTarget.addEventListener(Event.OPEN, function(e:Event):void { } );
            e.currentTarget.load();
        }
        
        private function onComplete(e:Event):void
        {
            e.currentTarget.removeEventListener(Event.COMPLETE, onComplete);
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderOnComplete);
            loader.loadBytes(e.currentTarget.data);
        }
        
        private function loaderOnComplete(e:Event):void
        {
            e.currentTarget.removeEventListener(Event.COMPLETE, loaderOnComplete);
            
            var btmap:BitmapData = new BitmapData(WIDTH, HEIGHT);
            var scale:Number = Math.max(WIDTH/e.currentTarget.loader.width, HEIGHT/e.currentTarget.loader.height);
            btmap.draw(e.currentTarget.loader, new Matrix(scale, 0, 0, scale), null, null, null, true);
            
            _texture.uploadFromBitmapData(btmap);
            
            _context3d.clear(0, 0, 0, 0);
            _context3d.drawTriangles(_index);
            _context3d.present();
        }
    }
    
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏developerHaoz 的安卓之旅

Android 带你撸一个好玩的 DoodleView(涂鸦)

可以看到这个这个自定义 View 的功能还是很丰富的,无论是设置画笔的形状、颜色、粗细,还是进行重置和保存,该有的 API,基本都已经实现了。有需要的读者直接 ...

923
来自专栏Android先生

Android自定义View——从零开始实现雪花飘落效果

前言:转眼已是十一月下旬了,天气慢慢转冷,不知道北方是不是已经开始下雪了呢?本期教程我们就顺应季节主题,一起来实现 雪花飘落的效果吧。本篇效果思路参考自国外大神...

1222
来自专栏青蛙要fly的专栏

项目需求讨论-自定义滚轮

大家好,这次又是到了实际的项目需求讨论时间,我的一些文章下面,有时候有人评论,求源码,求Demo,我的主张是仔细看文章,自己理解了再写一遍,会懂得更多。大部分人...

1022
来自专栏向治洪

解决Scrollview 嵌套recyclerview不能显示,高度不正常的问题

我们先看一个效果,问题说的就是中间的Grid效果在Scrollview 嵌套recyclerview显示问题,在Android Api 24是好的,不过在5,1...

6485
来自专栏郭霖

Android多点触控技术实战,自由地对图片进行缩放和移动

在上一篇文章中我带着大家一起实现了Android瀑布流照片墙的效果,虽然这种效果很炫很酷,但其实还只能算是一个半成品,因为照片墙中所有的图片都是只能看不能点的。...

2425
来自专栏项勇

笔记11 | 动态设置TextView的字体大小

1866
来自专栏lzj_learn_note

Android红包雨动画

上面就红包实体类的源码,重点就是在创建红包实体的时候,初始化红包相关的值,如生成红包图片,图片的宽高,红包初始位置,下落速度等。比较简单。

4524
来自专栏Android机动车

ViewAnimationUtils实现揭露动画

以上效果就是通过ViewAnimationUtils实现的,利用简单的几行代码,实现酷炫的揭露动画。

752
来自专栏郭霖

Android PowerImageView实现,可以播放动画的强大ImageView

我个人是比较喜欢逛贴吧的,贴吧里总是会有很多搞笑的动态图片,经常看一看就会感觉欢乐很多,可以释放掉不少平时的压力。确实,比起一张单调的图片,动态图片明显更加的有...

2645
来自专栏Sorrower的专栏

Android绘制(一):来用shape绘出想要的图形吧!

1354

扫码关注云+社区