R2A
forked from 速度測定テンプレート2 (diff: 139)
BitmapDataのR値をAlpha値にしてトリムする処理の比較。 get/setはメンド臭かったのでB値で処理 ColorFilterで出来るかは知らないし行列も出来ないので誰か出来る人検証してください
ActionScript3 source code
/**
* Copyright zahir ( http://wonderfl.net/user/zahir )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/1EEh
*/
// forked from zahir's 速度測定テンプレート2
package
{
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.utils.getTimer;
[SWF(width="465",height="465")]
public class Instrumentation extends Sprite
{
private var event:Event;
private var runsLen:int = 10;
private var runCount:int = 0;
private var t:TextField;
private var recodes:Array;
private const ZERO:Point = new Point();
private var src:BitmapData;
private var alphaMap:BitmapData;
private var bd:BitmapData;
private var filter:R2AFilter;
private var rect:Rectangle;
private const LOOP:int = 100;
private function exec(first:Boolean = false):void
{
var i:int = 0;
var time1:int;
var time2:int;
var count:int = 0;
if(first) recodes = [];
// ここから処理
time1 = getTimer();
for(i=0;i<LOOP;i++)
{
bd.applyFilter( alphaMap, rect, ZERO, filter );
bd.copyPixels( src, rect, ZERO, bd, ZERO );
}
time2 = getTimer() - time1;
if(first) recodes[count++] = new RecodeData( "pbjFilter -> copyPixels", time2, "サイズが大きいと効果を発揮" );
else (recodes[count++] as RecodeData).time = time2;
time1 = getTimer();
for(i=0;i<LOOP;i++)
{
bd.copyPixels( src, rect, ZERO );
bd.copyChannel( alphaMap, rect, ZERO, BitmapDataChannel.RED, BitmapDataChannel.ALPHA);
}
time2 = getTimer() - time1;
if(first) recodes[count++] = new RecodeData( "copyPixels -> copyChannel", time2, "" );
else (recodes[count++] as RecodeData).time = time2;
time1 = getTimer();
for(i=0;i<LOOP;i++)
{
bd.copyPixels( src, rect, ZERO );
var x:int = bd.width;
var y:int = bd.height;
for(var j:int = 0; j < x; j++)
{
for(var k:int = 0; k<y; k++)
{
var c:uint = alphaMap.getPixel( k, j);
var _a:int = c &0xFF;
c = _a <<24 | bd.getPixel( k,j );
bd.setPixel32( k, j, c );
}
}
}
time2 = getTimer() - time1;
if(first) recodes[count++] = new RecodeData( "get -> set pixel", time2, "" );
else (recodes[count++] as RecodeData).time = time2;
// ここまで処理
/* TEMPLETE
time1 = getTimer();
for(i=0;i<LOOP;i++)
{
}
time2 = getTimer() - time1;
if(first) recodes[count++] = new RecodeData( "", time2, "" );
else (recodes[count++] as RecodeData).time = time2;
//*/
runCount++;
var _loop:String = LOOP.toString().replace( /([0-9]+?)(?=(?:[0-9]{3})+$)/g , "$1," );
t.text = "各 " + _loop + " 回ループ を " + runCount + " 回実行しました。\n\n";
if( recodes.length ) listUp();
t.appendText("clickで再計算");
if(event){
runsLen--;
trace(runsLen);
if(runsLen <= 0) return;
dispatchEvent( event );
}
}
public function Instrumentation()
{
var size:int = 465/3;
src = new GradientBitmapData( size, size ).data;
alphaMap = new AlphaMap( size, size ).data;
bd = new BitmapData( size,size, true, 0 );
filter = new R2AFilter();
rect = bd.rect;
addChild( (t = new TextField() ) ).width = t.height = 465;
addEventListener( MouseEvent.CLICK, onClick);
/* ある程度回数を回したいとき用
addEventListener("ex", onRun);
event = new Event("ex");
//*/
exec(true);
}
private function onClick( e:MouseEvent ):void
{
exec();
}
private function onRun(e:Event):void
{
exec();
}
private function listUp():void
{
var str:String = "";
var recode:Array = copy();
recode.sortOn( "time", Array.NUMERIC );
var max:int = (recode[ recode.length - 1 ] as RecodeData).time;
for( var i:int = 0, len:int = recode.length; i<len; i++)
{
var data:RecodeData = recode[i] as RecodeData;
var n:int = max / data.time * 100;
str += data.title + " :: " + data.time + " ms\n\t\t最低速に比べて約 " + n + " %高速 \n";
if(data.message == "") str += "\n";
else str += "\t\t" + data.message + "\n\n";
}
t.appendText( str );
}
private function copy():Array
{
var arr:Array = [];
for(var i:int = 0, len:int = recodes.length; i<len; i++){
arr[i] = recodes[i];
}
return arr;
}
}
}
import flash.display.BitmapData;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shader;
import flash.display.Shape;
import flash.filters.ShaderFilter;
import flash.geom.Matrix;
import flash.utils.ByteArray;
import mx.utils.Base64Decoder;
class AbstBitmapData
{
protected var bd:BitmapData;
public function AbstBitmapData( w:int, h:int )
{
bd = new BitmapData(w,h,false, 0xFFFFFF);
setup();
}
protected function setup():void
{
}
public function get data():BitmapData
{
return bd.clone();
}
}
class GradientBitmapData extends AbstBitmapData
{
public function GradientBitmapData( w:int, h:int)
{
super(w,h);
}
override protected function setup():void
{
var s:Shape = new Shape();
var g:Graphics = s.graphics;
var m:Matrix = new Matrix();
m.createGradientBox( bd.width, bd.height );
g.beginGradientFill( "linear", [0xFF0000, 0xFFFF00, 0x00FF00], [1,1,1], [0,0x88,0xFF],m);
g.drawRect( 0,0, bd.width, bd.height );
g.endFill();
bd.draw( s );
}
}
class AlphaMap extends AbstBitmapData
{
public function AlphaMap(w:int,h:int)
{
super(w,h);
}
override protected function setup():void
{
var s:Shape = new Shape();
var g:Graphics = s.graphics;
var m:Matrix = new Matrix();
m.createGradientBox( bd.width, bd.height );
g.beginGradientFill( "radial", [0, 0xFFFFFF], [1,1], [0x99,0xFF],m);
g.drawRect( 0,0, bd.width, bd.height );
g.endFill();
bd.draw( s );
}
}
/*
* srcのRedチャンネルをAlphaにするだけのPixelBenerFilter
*/
class R2AFilter extends ShaderFilter{
static private var code:ByteArray;
{ static private var dec:Base64Decoder = new Base64Decoder() ;
dec.decode(
"pQEAAACkCQBHMkFGaWx0ZXKgDG5hbWVzcGFjZQBqcC56YWhpcgCgDHZlbmRvcgB6YWhpcgCgCHZl" +
"cnNpb24AAQCgDGRlc2NyaXB0aW9uAGdyYXlTY2FsZSAtPiBhbHBoYQChAQIAAAxfT3V0Q29vcmQA" +
"owAEc3JjAKECBAEAD2RzdAAwAgDxAAAQAB0BAPMCABsAHQEAEAEAAAA=" );
code = dec.toByteArray(); dec = null;
}public function R2AFilter(){ super( new Shader( code) ) }
}
class RecodeData
{
private var count:int = 0;
public var title:String = "";
private var _time:uint;
public var message:String = "";
public function RecodeData( title:String, time:int, message:String = "" )
{
this.title = title;
this.time = time;
this.message = message;
}
public function get time():int
{
return _time / count;
}
public function set time( value:int ):void
{
_time += value;
count++;
}
}