forked from: ミップマップでビットマップの縮小

by midisheep forked from ミップマップでビットマップの縮小 (diff: 1)
-------------------------------------------------

ミップマップでビットマップの縮小

画像は大阪市交通局から勝手にお借りしてます。

100%より小さく、少しずつ姿勢を変化させ続けたときに
ビットマップがどのように描画されるかを確認するテストです。

マウスホイール回転で拡大縮小が可能です。

-------------------------------------------------
♥0 | Line 450 | Modified 2011-07-05 00:00:23 | MIT License
play

ActionScript3 source code

/**
 * Copyright midisheep ( http://wonderfl.net/user/midisheep )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/87sf
 */

// forked from Hakuhin's ミップマップでビットマップの縮小
// -------------------------------------------------
//
// ミップマップでビットマップの縮小
//
//
// 画像は大阪市交通局から勝手にお借りしてます。
//
// 100%より小さく、少しずつ姿勢を変化させ続けたときに
// ビットマップがどのように描画されるかを確認するテストです。
//
// マウスホイール回転で拡大縮小が可能です。
//
// -------------------------------------------------
package {
    import flash.events.*;
    import flash.display.*;
    import flash.net.*;
    import flash.text.*;
    import flash.utils.*;
    import flash.system.*;
    import flash.geom.*;
    import flash.filters.*;
    import flash.ui.*;
    import flash.media.*;

    public class Main extends Sprite {
        public function Main() {

        
// -------------------------------------------------
// コンストラクタ
// -------------------------------------------------

// フレームレート
stage.frameRate = 60;

// 100%表示
stage.scaleMode = StageScaleMode.NO_SCALE;

// 左上
stage.align = StageAlign.TOP_LEFT;
stage.align = "TL";

// スプライトを作成
var sprite:Sprite = new Sprite();
var g:Graphics = sprite.graphics;
addChild(sprite);

// 初期化へ
init();


// -------------------------------------------------
// 初期化
// -------------------------------------------------
function init():void{

    // 画像のURL
    var url:String = "http://www.kotsu.city.osaka.jp/ct/image000000500/subway_number.gif";

    // ステージサイズ
    var w:uint;
    var h:uint;
    
    var bmp_src:BitmapData = null;
    
    // ローダー作成
    var loader_obj : Loader = new Loader();
    var info : LoaderInfo = loader_obj.contentLoaderInfo;
    
    // 読み込み完了
    info.addEventListener (Event.INIT,LoaderInfoInitFunc);
    function LoaderInfoInitFunc (event : Event):void {
        
        // メモリからインスタンス化
        var loader_memory : Loader = new Loader();
        loader_memory.contentLoaderInfo.addEventListener (Event.COMPLETE,LoaderInfoCompleteFunc);
        function LoaderInfoCompleteFunc (event : Event):void {
            
            var sprite:Sprite = new Sprite();
            stage.addChild(sprite);

            // キャプチャ
            bmp_src = new BitmapData(loader_memory.width,loader_memory.height,true,0);
            sprite.addChild(loader_memory);
            bmp_src.draw(sprite);
            sprite.removeChild(loader_memory);
            stage.removeChild(sprite);
  
            // リサイズ
            ResizeFunc(null);
        }
        
        // 読み込み開始
        loader_memory.loadBytes(loader_obj.contentLoaderInfo.bytes);
    }


    // 読み込み開始
    load(url);

    // リザルト作成
    var result : Sprite = new Sprite();
    addChild(result);
    result.x = 0;

    // ボタン作成
    var button:Button = new Button(stage);
    button.y = 70;
    button.setSize(60,20);
    button.setLabel("開く");
    result.addChild(button);

    // ボタンが押された
    button.addEventListener(MouseEvent.CLICK,function(e:MouseEvent):void{
        load(text.text);
    });
    
    function load(url:String):void{

        // 読み込み
        loader_obj.load(new URLRequest(url));
    }
    
    // ミップマップ用ラジオボタン
    var radio_off:RadioButton = new RadioButton(stage);
    result.addChild(radio_off);
    radio_off.setLabel("ミップマップなし");
    radio_off.x = 0;
    radio_off.y = 4;
    radio_off.setSize(120,18);
    radio_off.onClick(function(obj:RadioButton):void{mipmap = false;});

    var radio_on:RadioButton = new RadioButton(stage);
    result.addChild(radio_on);
    radio_on.setLabel("ミップマップあり");
    radio_on.x = 0;
    radio_on.y = 22;
    radio_on.setSize(120,18);
    radio_on.onClick(function(obj:RadioButton):void{mipmap = true;});

    // ラジオボタンを関連付け
    radio_on.attachGroup(radio_off);
    radio_on.select();


    // 画質用ラジオボタン
    var radio_low:RadioButton = new RadioButton(stage);
    result.addChild(radio_low);
    radio_low.setLabel("画質:low");
    radio_low.x = 0;
    radio_low.y = 4;
    radio_low.setSize(100,18);
    radio_low.onClick(function(obj:RadioButton):void{stage.quality = StageQuality.LOW;});

    var radio_high:RadioButton = new RadioButton(stage);
    result.addChild(radio_high);
    radio_high.setLabel("画質:high");
    radio_high.x = 0;
    radio_high.y = 22;
    radio_high.setSize(100,18);
    radio_high.onClick(function(obj:RadioButton):void{stage.quality = StageQuality.HIGH;});

    var radio_best:RadioButton = new RadioButton(stage);
    result.addChild(radio_best);
    radio_best.setLabel("画質:best");
    radio_best.x = 0;
    radio_best.y = 40;
    radio_best.setSize(100,18);
    radio_best.onClick(function(obj:RadioButton):void{stage.quality = StageQuality.BEST;});

    // ラジオボタンを関連付け
    radio_low.attachGroup(radio_high);
    radio_low.attachGroup(radio_best);
    radio_high.select();


    // テキストフィールド作成
    var ft_result:TextField = new TextField();
    ft_result.x = 10;
    ft_result.y = 50;
    ft_result.width = 300;
    ft_result.height = 20;
    ft_result.selectable = false;

    // 書式
    var format_result:TextFormat = new TextFormat();
    format_result.font = "MS ゴシック";    // フォント名
    ft_result.defaultTextFormat = format_result;

    // テキスト表示
    result.addChild(ft_result);

    // 読み込み状況
    addEventListener (Event.ENTER_FRAME,EnterFrameFunc);
    function EnterFrameFunc (event : Event) :void{
        ft_result.text = "読込:" + info.bytesLoaded + " / 全体:" + info.bytesTotal;
    }

    // テキストフィールド作成
    var text:TextField = new TextField();
    text.x = 10;
    text.y = 70;
    text.height = 20;
    text.type = TextFieldType.INPUT;
    text.border = true;

    // 書式
    var format:TextFormat = new TextFormat();
    format.font = "MS ゴシック";    // フォント名
    text.defaultTextFormat = format;

    // テキスト表示
    text.text = url;
    result.addChild(text);
    
    // リサイズ時にフィット
    stage.addEventListener(Event.RESIZE,ResizeFunc);
    function ResizeFunc(e:Event):void{
        w = stage.stageWidth;
        h = stage.stageHeight;
        loader_obj.width = w;
        loader_obj.height = h - 100;

        result.y = h - 100;
    
        // テキストフィールド位置
        text.width = w - 10 - 10 - button.width - 10;
    
        // ボタン位置
        button.x = w - button.width - 10;
        
        // ラジオボタン位置
        radio_off.x = w - 270;
        radio_on.x = w - 270;
        radio_low.x = w - 100;
        radio_high.x = w - 100;
        radio_best.x = w - 100;
    }
    ResizeFunc(null);
    
    
    var px:Number = 0;
    var py:Number = 0;
    var rot:Number = 0;
    var sx:Number = 0;
    var sy:Number = 0;
    var scale:Number = 0.25;
    var phase:Number = 0;
    var mipmap:Boolean = true;
    var m:Matrix;

    addEventListener(Event.ENTER_FRAME,function(e:Event):void{

        if(!bmp_src)    return;
        
        // 少し移動
        px += 0.1;
        py += 0.1;

        // 少し回転
        rot += 0.05;

        // 拡大縮小
        phase += 3.0 * Math.PI / 180;
        sx = Math.cos(phase) * 0.015625 + 1.0;
        sy = Math.sin(phase) * 0.015625 + 1.0;
        
        sx *= scale;
        sy *= scale;

        
        if(mipmap){
            var dx:Number = MipmapGetScale(sx);
            var dy:Number = MipmapGetScale(sy);

            var bmp_w:uint = Math.floor(dx * bmp_src.width);
            var bmp_h:uint = Math.floor(dy * bmp_src.height);
            
            var bmp_cpy:BitmapData = new BitmapData(bmp_w,bmp_h,true);
            var q : String = stage.quality;
            stage.quality = StageQuality.BEST;
            bmp_cpy.draw(
                         bmp_src,
                         new Matrix(dx,0,0,dy,0,0),
                         new ColorTransform(1,1,1,1,0,0,0,0),
                         BlendMode.NORMAL,
                         new Rectangle(0,0,bmp_w,bmp_h),
                         true
            );
            stage.quality = q;
            
            m = new Matrix();
            m.identity();
            m.scale(1.0/dx,1.0/dy);
            m.translate(px,py);
            m.translate(-w/2.0,-(h-100)/2.0);
            m.scale(sx , sy);
            m.rotate(rot * Math.PI / 180);
            m.translate( w/2.0, (h-100)/2.0);
        
            g.clear();
            g.beginBitmapFill(bmp_cpy,m,true,true);
            g.drawRect(0,0,w,h-100);
            g.endFill();

        }else{

            m = new Matrix();
            m.identity();
            m.translate(px,py);
            m.translate(-w/2.0,-(h-100)/2.0);
            m.scale(sx , sy);
            m.rotate(rot * Math.PI / 180);
            m.translate( w/2.0, (h-100)/2.0);
        
            g.clear();
            g.beginBitmapFill(bmp_src,m,true,true);
            g.drawRect(0,0,w,h-100);
            g.endFill();

        }
    });
    
    function MipmapGetScale(d:Number):Number{
        if(d <= 0.0)    return 1.0;
        var i:Number = 1.0;
        while(true){
            i /= 2.0;
            if(d > i)    break;
        }
        
        return i * 2.0;
    }
    
    // テキスト表示
    var tf : TextField = new TextField();
    tf.x = 5;
    tf.y = 5;
    tf.width = 150;
    tf.height = 34;
    tf.border = true;
    tf.background = true;
    tf.alpha = 0.9;
    
    // 書式
    format = new TextFormat();
    format.font = "MS ゴシック";
    tf.defaultTextFormat = format;

    addChild(tf);
    addEventListener(Event.ENTER_FRAME,function(e:Event):void{
        var str:String = "";
        var d:Number;
        str += "scaleX : " + Math.floor(sx * 100000) / 100000 + "\n";
        str += "scaleY : " + Math.floor(sy * 100000) / 100000 + "\n";
        tf.text = str;
    });

    // マウス操作
    addEventListener(MouseEvent.MOUSE_WHEEL, function (event:MouseEvent):void{
        scale += event.delta * 0.01;
        if(scale < 0.02)    scale = 0.02;
        if(scale > 1.00)    scale = 1.00;
    });


}




        }
    }
}





import flash.events.*;
import flash.display.*;
import flash.text.*;
import flash.geom.*;

// -------------------------------------------------
// ボタン
// -------------------------------------------------
internal class Button extends Sprite {

    private var _width:Number;
    private var _height:Number;
    
    private var _text:TextField;
    private var _background:Sprite;
    

    public function Button(stage:Stage) {
        var slider:Button = this;

        // 背景用スプライト作成
        _background = new Sprite();
        addChild(_background);

        // テキストフィールド
        _text = new TextField();
        addChild(_text);
    
        _text.x = 0;
        _text.y = 0;
        _text.selectable = false;

        // 書式
        var format:TextFormat = new TextFormat();
        format.align = TextFormatAlign.CENTER;    // 整列
        format.font = "MS ゴシック";    // フォント名
        format.size = 14;                // 文字のポイントサイズ
        format.color = 0x202020;        // 文字の色
        _text.defaultTextFormat = format;
    
        // マウスオーバーで少し明るく
        addEventListener(MouseEvent.MOUSE_OVER,function(e:MouseEvent):void{
            var color : ColorTransform = new ColorTransform(1,1,1,1,8,8,8,0);
            transform.colorTransform = color;
        });

        // マウスアウトで元に戻す
        addEventListener(MouseEvent.MOUSE_OUT,function(e:MouseEvent):void{
            var color : ColorTransform = new ColorTransform(1,1,1,1,0,0,0,0);
            transform.colorTransform = color;                                                           
        });

        // デフォルト値
        setSize(100,100);
        update();
    }
    // リサイズ
    public function setSize(w:Number,h:Number):void{
        // 背景リサイズ
        _width = w;
        _height = h;
        update();
    }
    // ラベルセット
    public function setLabel(str:String):void{
        _text.text = str;
        update();
    }
    // 描画更新
    private function update():void{
        // 背景描画
        var g:Graphics = _background.graphics;
        
        // 角丸矩形描画
        g.clear();
        g.lineStyle ( 0 , 0x808080 , 1.0,false,LineScaleMode.NONE,CapsStyle.ROUND,JointStyle.ROUND);
        g.beginFill ( 0xF0F0F0 , 1.0 );
        g.drawRoundRect ( 0 , 0 , _width , _height , 5 , 5 );
        g.endFill();
        
        // テキスト位置修正
        _text.width  = _width;
        _text.height = _height;
    }
}



import flash.events.*;
import flash.display.*;
import flash.text.*;
import flash.geom.*;

// -------------------------------------------------
// ラジオボタン
// -------------------------------------------------
internal class RadioButton extends Sprite {

    private var _width:Number;
    private var _height:Number;
    
    private var _text:TextField;
    private var _background:Sprite;
    private var _button:Sprite;
    private var _check:Sprite;
    
    private var _pref:RadioButton;
    private var _post:RadioButton;
    
    private var _selected:Boolean;
    private var _onClick:Function;

    public function RadioButton(stage:Stage) {
        var slider:RadioButton = this;
        
        _onClick = null;
        _selected = false;
        
        // リングリスト作成
        _pref = this;
        _post = this;

        // 背景用スプライト作成
        _background = new Sprite();
        addChild(_background);

        // ボタン用スプライト作成
        _button = new Sprite();
        addChild(_button);

        // チェック用スプライト作成
        _check = new Sprite();
        addChild(_check);

        // テキストフィールド
        _text = new TextField();
        addChild(_text);
    
        _text.x = 20;
        _text.y = 0;
        _text.selectable = false;

        // 書式
        var format:TextFormat = new TextFormat();
        format.align = TextFormatAlign.LEFT;    // 整列
        format.font = "MS ゴシック";            // フォント名
        format.size = 14;                        // 文字のポイントサイズ
        format.color = 0x202020;                // 文字の色
        _text.defaultTextFormat = format;
    
        // マウスオーバーで少し明るく
        addEventListener(MouseEvent.MOUSE_OVER,function(e:MouseEvent):void{
            var color : ColorTransform = new ColorTransform(1,1,1,1,8,8,8,0);
            transform.colorTransform = color;
        });

        // マウスアウトで元に戻す
        addEventListener(MouseEvent.MOUSE_OUT,function(e:MouseEvent):void{
            var color : ColorTransform = new ColorTransform(1,1,1,1,0,0,0,0);
            transform.colorTransform = color;                                                           
        });

        // クリック
        addEventListener(MouseEvent.CLICK,function(e:MouseEvent):void{
            select();                                               
        });

        // デフォルト値
        setSize(100,100);
        update();
    }
    // リサイズ
    public function setSize(w:Number,h:Number):void{
        // 背景リサイズ
        _width = w;
        _height = h;
        update();
    }
    // ラベルセット
    public function setLabel(str:String):void{
        _text.text = str;
        update();
    }
    // 描画更新
    private function update():void{
        // 背景描画
        var g:Graphics;
        var height_half:Number = _height / 2;
        var r:Number;

        
        // 背景描画
        g = _background.graphics;
        g.clear();
        g.beginFill ( 0xFFFFFF , 0.0 );
        g.drawRect ( 0 , 0 , _width , _height );
        g.endFill();

        
        // ボタン描画
        g = _button.graphics;
        g.clear();
        g.lineStyle ( 0 , 0x808080 , 1.0,false,LineScaleMode.NONE,CapsStyle.ROUND,JointStyle.ROUND);
        g.beginFill ( 0xF0F0F0 , 1.0 );
        r = height_half - 4;
        if(r < 4) r = 4;
        g.drawCircle ( height_half , height_half , r );
        g.endFill();

        // 背景描画
        g = _check.graphics;
        g.clear();
        g.lineStyle ( 0 , 0x404040 , 1.0,false,LineScaleMode.NONE,CapsStyle.ROUND,JointStyle.ROUND);
        g.beginFill ( 0x606060 , 1.0 );
        r = height_half - 8;
        if(r < 2) r = 2;
        g.drawCircle ( height_half , height_half , r );
        g.endFill();

        // テキスト位置修正
        _text.x  = _height;
        _text.width  = _width;
        _text.height = _height;

        if(_selected)    _check.visible = true;
        else            _check.visible = false;
    }
    
    // グループにセット
    public function attachGroup(button:RadioButton):void{
        button.removeGroup();

        var pref:RadioButton = this;
        var post:RadioButton = _post;

        pref._post = button;
        post._pref = button;
        button._pref = pref;
        button._post = post;
    }

    // グループから外す
    public function removeGroup():void{
        var pref:RadioButton = _pref;
        var post:RadioButton = _post;
        pref._post = post;
        post._pref = pref;
        _pref = this;
        _post = this;
    }
    
    // 選択
    public function select():void{
        // すべてのチェックを外す
        var list:RadioButton = this._post;
        while(true){
            if(list == this)    break;

            list._selected = false;
            list.update();
            list = list._post;
        }
        // チェック
        list._selected = true;
        list.update();
        
        // コールバック関数呼び出し
        if(_onClick != null){
            _onClick(this);
        }
    }

    // イベント登録
    public function onClick(func:Function):void{
        _onClick = func;
    }
}


// -------------------------------------------------
// 外部画像をサムネイルとしてキャプチャ
// -------------------------------------------------
import flash.net.*;
import flash.events.*;
import flash.display.*;
import flash.geom.*;
function ThumbnailCapture(url:String,time:uint,stage:Stage):void{

    // キャプチャタイミング
    Wonderfl.capture_delay( time );

    // スプライト作成
    var sprite : Sprite = new Sprite();

    // ステージ最前面に配置
    stage.addChildAt(sprite,stage.numChildren);
    
    // ローダー
    var loader_obj : Loader = new Loader();
    loader_obj.contentLoaderInfo.addEventListener (Event.INIT,function(e:Event):void{

        // メモリからインスタンス化
        var loader_memory : Loader = new Loader();
        loader_memory.contentLoaderInfo.addEventListener (Event.INIT,function(e:Event):void{

            // キャプチャ
            var bmp : BitmapData = new BitmapData(loader_memory.width,loader_memory.height,true,0);
            sprite.addChild(loader_memory);
            bmp.draw(sprite);
            sprite.removeChild(loader_memory);
            loader_memory.unload();
            loader_obj.unload();
            loader_memory = null;
            loader_obj = null;
            
            
            // 画像を配置
            var bmp_obj : Bitmap = new Bitmap(bmp);
            bmp_obj .width = stage.stageWidth;
            bmp_obj .height = stage.stageHeight;
            stage.addChild(bmp_obj );
            
        });
        
        // 読み込み開始
        loader_memory.loadBytes(loader_obj.contentLoaderInfo.bytes);
    });
    
    // 読み込み開始
    loader_obj.load(new URLRequest(url));
}