魚眼レンズ? 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;
}
}}