DisplacementMapFilter with perlineNoise
DisplacementMapFilter with perlineNoise
動く perlineNoise を DisplacementMapFilter に適用して、写真をぐにゃぐにゃさせます。
左が DisplacementMapFilter によって変形するイメージ、
右がイメージを変形させている Filter に適用されている perlinNoise の bitmapData
画像読み込みは 5ivestar さんの Proxy を使わせていただきました。
wonderfl.kayac.com/code/e40aae6e65d9f379f7cd3684d40eb710a7701a2d
// DisplacementMapFilter with perlineNoise
// 動く perlineNoise を DisplacementMapFilter に適用して、写真をぐにゃぐにゃさせます。
// 左が DisplacementMapFilter によって変形するイメージ、
// 右がイメージを変形させている Filter に適用されている perlinNoise の bitmapData
//
// 画像読み込みは 5ivestar さんの Proxy を使わせていただきました。
// wonderfl.kayac.com/code/e40aae6e65d9f379f7cd3684d40eb710a7701a2d
package {
/**
* @author YOSHIDA, Akio
*/
import flash.display.Sprite;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.IEventDispatcher;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.system.Security;
[SWF(width="465", height="465", frameRate="60", backgroundColor="#000000")]
public class Main extends Sprite {
private var loader:Loader; // ローダー
private var loading:TextField; // ナウローディング表示
// 表示イメージ
private var displayBm:Bitmap;
// 置き換えマップ可視化
private var mapBm:Bitmap;
// 置き換えマップ
private var displacementMap:PerlinNoiseMap;
// DisplacementMapFilter
private var dmf:EasyDMF;
public function Main():void {
Security.loadPolicyFile("http://5ivestar.org/proxy/crossdomain.xml");
// Loader 生成
loader = new Loader();
// イベントリスナー登録
configureListeners(loader.contentLoaderInfo);
// ロード開始
loader.load(new URLRequest("http://5ivestar.org/proxy/http://homepage3.nifty.com/aquioux/swf/as3/wonderfl/aquioux001.jpg"));
// ナウローディング
loading = new TextField();
loading.defaultTextFormat = new TextFormat("_sans", 24, 0xffffff);
loading.text = "Now Loading...";
loading.autoSize = "left";
loading.x = (stage.stageWidth - loading.width) / 2;
loading.y = (stage.stageHeight - loading.height) / 2;
addChild(loading);
}
// イベントリスナー登録
private function configureListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.COMPLETE, completeHandler);
}
// 読み込み完了時のイベントハンドラ
private function completeHandler(e:Event):void {
create();
}
private function create():void {
removeChild(loading);
// 表示イメージ
var w:uint = loader.width;
var h:uint = loader.height;
var margin:uint = 0;
var bmd:BitmapData = new BitmapData(w-margin*2, h-margin*2, false, 0x000000);
bmd.draw(loader.content, new Matrix(1, 0, 0, 1, -margin, -margin));
displayBm = new Bitmap(bmd);
displayBm.x = margin;
displayBm.y = margin;
addChild(displayBm);
loader = null;
// 置き換えマップ可視化
mapBm = new Bitmap();
mapBm.x = w;
mapBm.y = 0;
addChild(mapBm);
// 置き換えマップと DisplacementMapFilter 生成
dmf = new EasyDMF(new PerlinNoiseMap(w, h));
// イベントハンドラ
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
// イベントハンドラ
private function enterFrameHandler(e:Event):void {
dmf.renew();
displayBm.filters = [dmf.filter];
mapBm.bitmapData = dmf.filter.mapBitmap;
}
}
}
// DisplacementMapFilter
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.geom.Point;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
class EasyDMF {
private var _filter:DisplacementMapFilter;
private var map:IDisplacementMap; // 置き換えマップ
public function EasyDMF(map:IDisplacementMap) {
this.map = map;
var scale:uint = 64;
_filter = new DisplacementMapFilter(
map.bitmapData,
new Point(0, 0),
BitmapDataChannel.RED,
BitmapDataChannel.RED,
scale,
scale,
DisplacementMapFilterMode.CLAMP
);
}
public function renew():void {
map.renew();
_filter.mapBitmap = map.bitmapData;
}
public function get filter():DisplacementMapFilter { return _filter; }
}
// DisplacementMap(perlineNoise)
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.geom.Point;
class PerlinNoiseMap implements IDisplacementMap {
private var _bitmapData:BitmapData;
private var w:uint;
private var h:uint;
// perlinNoise パラメータ
private var octaves:uint = 2;
private var seed:Number;
private var channels:uint = BitmapDataChannel.RED | BitmapDataChannel.GREEN | BitmapDataChannel.BLUE;
private var offset:Array = new Array();
private var offx:Vector.<int> = new Vector.<int>(octaves,true);
private var offy:Vector.<int> = new Vector.<int>(octaves,true);
private var rate:uint = 2;
public function PerlinNoiseMap(w:uint, h:uint) {
this.w = w;
this.h = h;
_bitmapData = new BitmapData(w, h, false, 0x000000);
seed = Math.floor(Math.random()*0xffff);
for (var i:int=0; i<octaves; i++) {
offset[i] = new Point(Math.random() * w , Math.random() * h);
offx[i] = Math.random() * rate * 2 - rate;
offy[i] = Math.random() * rate * 2 - rate;
}
}
public function renew():void {
for (var i:int=0; i<octaves; i++) {
offset[i].x += offx[i];
offset[i].y += offy[i];
}
_bitmapData.perlinNoise(w, h, octaves, seed, false, true, channels, false, offset);
}
public function get bitmapData():BitmapData { return _bitmapData; }
}
// interface of DisplacementMap
import flash.display.BitmapData;
interface IDisplacementMap {
function renew():void;
function get bitmapData():BitmapData;
}