In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

魚眼レンズ? forked from: DisplacementMapFilter 球

package {
    import flash.display.Sprite;
    import flash.events.StatusEvent;
    import flash.events.Event;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.system.Security;
    import flash.system.SecurityPanel;
    import flash.geom.Point;
    import flash.filters.BitmapFilterQuality;
    import flash.display.BitmapDataChannel;
    import flash.filters.BitmapFilter;
    import flash.filters.DisplacementMapFilter;
    import flash.filters.DisplacementMapFilterMode;
    import flash.geom.Matrix;
    
    public class Test extends Sprite {
        
        private var camera:Camera;
        private var video:Video;
        private var source:BitmapData;
        
        private var sp:Sprite = new Sprite();
        
        private var interval:int = 10;
        
        private var bd:BitmapData;
        private var bm:Bitmap;
        
        private const W:Number = stage.stageWidth;
        private const H:Number = stage.stageHeight;
        
        public function Test() {
            
            camera = Camera.getCamera();
            if (camera != null) {
                if (camera.muted) {
                    Security.showSettings(SecurityPanel.PRIVACY);
                    camera.addEventListener(StatusEvent.STATUS, StatusHandler);
                } else {
                    ConnectCamera();
                }
            } else {
                trace("カメラが見つかりません");
            }
        }
        
        private function StatusHandler(e:StatusEvent):void {
            
            if (e.code == "Camera.Unmuted") {
                ConnectCamera();
                camera.removeEventListener(StatusEvent.STATUS, StatusHandler);
            }
        }
        
        private function ConnectCamera():void {
            
            camera.setMode(W, H, 30);
            video = new Video(W, H);
            video.attachCamera(camera);
            
            source = new BitmapData(video.width,video.height,false,0xFFFFFF);
            
            bd = new BitmapData(video.width,video.height,false,0xFFFFFF);
            bm = new Bitmap(bd);
            
            //bm.x = stage.stageWidth/2 - video.width/2;
            //bm.y = stage.stageHeight/2 - video.height/2;
            
            var maskSp:Sprite = new Sprite();
            maskSp.graphics.beginFill(0xFF0000);
            maskSp.graphics.drawCircle(W/2, H/2, W/2);
            maskSp.graphics.endFill();
            bm.mask = maskSp;
            
            addChild(bm);
            var dmf:DisplacementMapFilter = createDMF(W/2);
            bm.filters = [dmf]
            
            addEventListener(Event.ENTER_FRAME, Loop);
        }
        
        private function Loop(e:Event):void {
            
            bd.fillRect(source.rect, 0xFFFFFF);
            bd.draw(video);
        }
        
        private function createDMF(radius:Number):DisplacementMapFilter {
            
            var mapBitmap:BitmapData = new BitmapData(radius*2, radius*2, false);
            var maxDistance:Number = radius;//適当。適宜調整
            var dmf:DisplacementMapFilter = new DisplacementMapFilter(
                mapBitmap,
                new Point(bm.width/2 - radius, bm.height/2 - radius),
                BitmapDataChannel.BLUE,//x方向の移動に使う色
                BitmapDataChannel.GREEN,//y方向の移動に使う色
                maxDistance,
                maxDistance,
                DisplacementMapFilterMode.COLOR
            );
            
            var yMax:int = radius * 2;
            var xMax:int = radius * 2;
            var center:Number = radius;
            
            mapBitmap.lock();
            for (var yy:int = 0; yy < yMax; ++yy) {
                for (var xx:int = 0; xx < xMax; ++xx) {
                    var dx:Number = xx - center;
                    var dy:Number = yy - center;
                    var distance:Number = Math.sqrt(dx * dx + dy * dy);
                    
                    if (distance <= radius) {
                        //座標変換公式
                        //http://kenpei-web.hp.infoseek.co.jp/math/coordinates/
                        //中心に近づくほど90度(Math.PI / 2)になるようにする。
                        var rate:Number = distance/radius;
                        var theta:Number = Math.PI/2 * rate;
                        var phi:Number = Math.atan2(dy, dx);
                        var toX:Number = (radius * Math.sin(theta) * Math.cos(phi)) + center;
                        var toY:Number = (radius * Math.sin(theta) * Math.sin(phi)) + center;
                        var colorX:Number = getColor(xx - toX, dmf.scaleX);
                        var colorY:Number = getColor(yy - toY, dmf.scaleY);
                        var color:uint = colorY << 8 | colorX;
                    }
                    else {
                        //何も変化しない色
                        color = 0x80808080;
                    }
                    mapBitmap.setPixel(xx, yy, color);
                }
            }
            mapBitmap.unlock();
            return dmf;
        }
        
        /**
         * @param    diff 動かしたい距離
         * @param    scale 取り得る値の最大値
         * @return
         */
        
        private function getColor(diff:Number, scale:Number):uint {
            return Math.round((diff * 0x100) / scale) + 0x80;
        }
    }}