画像変形の練習 

by otherone
画像を四点で変形できるものを作成してみました。


参考サイト
http://www.d-project.com/flex/009_FreeTransform/
♥0 | Line 194 | Modified 2011-11-02 16:57:50 | MIT License | (replaced)
play

ActionScript3 source code

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

package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;

    /**
     * ...
     * @author moriya
     */
    public class Main extends Sprite
    {
        private const STW:uint = stage.stageWidth,STH:uint = stage.stageHeight;
        private var container:Sprite;
        private var bm:Bitmap;
        private var bmd:BitmapData;
        private var g:Graphics;
        private var h:uint,w:uint;
        private var sp0:Sprite,sp1:Sprite,sp2:Sprite,sp3:Sprite;
        private var a0:Point,a1:Point,a2:Point,a3:Point;
        private var b0:Point, b1:Point, b2:Point, b3:Point;
        private var _imgLoader:Loader;
        private var _imgLoaderInfo:LoaderInfo;

        public function Main():void
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event = null):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            var url:String = "http://assets.wonderfl.net/images/related_images/a/af/af90/af90356c6bcf822829d5f2787430a0c15332e42a";
            var urlReq:URLRequest = new URLRequest(url);
            var context:LoaderContext = new LoaderContext();
            context.checkPolicyFile = true;
            _imgLoader = new Loader();
            _imgLoaderInfo = _imgLoader.contentLoaderInfo;
            _imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageloaded);
            _imgLoader.load(urlReq, context);

            graphics.beginFill(0x000000, 1);
            graphics.drawRect(0, 0, STW, STH);
            graphics.endFill();
        }

        private function onImageloaded(e:Event):void
        {
            container = new Sprite();
            bmd =  new BitmapData(_imgLoader.width, _imgLoader.height);
            bmd.draw(_imgLoader);
            bm = new Bitmap(bmd);            
            
            h = bm.height;
            w = bm.width;
            g=container.graphics;
            container.x = (STW - w) * .5, container.y = (STH - h) * .5;
            addChild(container);

            //変形用のボタン
            sp0 = new Sprite(),sp1 = new Sprite(),sp2 = new Sprite(),sp3 = new Sprite();
            circle(sp0), circle(sp1), circle(sp2), circle(sp3);
            sp0.x = 0, sp0.y = 0, sp1.x = w, sp1.y = 0, sp2.x = 0, sp2.y = h, sp3.x = w, sp3.y = h;
            container.addChild(sp0), container.addChild(sp1), container.addChild(sp2), container.addChild(sp3);
            sp0.name = 'b0',sp1.name = 'b1',sp2.name = 'b2',sp3.name = 'b3';
            sp0.addEventListener(MouseEvent.MOUSE_DOWN, fnDown);
            sp1.addEventListener(MouseEvent.MOUSE_DOWN, fnDown);
            sp2.addEventListener(MouseEvent.MOUSE_DOWN, fnDown);
            sp3.addEventListener(MouseEvent.MOUSE_DOWN, fnDown);

            sp0.addEventListener(MouseEvent.MOUSE_MOVE, fnMove);
            sp1.addEventListener(MouseEvent.MOUSE_MOVE, fnMove);
            sp2.addEventListener(MouseEvent.MOUSE_MOVE, fnMove);
            sp3.addEventListener(MouseEvent.MOUSE_MOVE, fnMove);

            sp0.addEventListener(MouseEvent.MOUSE_UP, fnUp);
            sp1.addEventListener(MouseEvent.MOUSE_UP, fnUp);
            sp2.addEventListener(MouseEvent.MOUSE_UP, fnUp);
            sp3.addEventListener(MouseEvent.MOUSE_UP, fnUp);

            a0 = new Point(0, 0),a1 = new Point(w, 0),a2 = new Point(0, h),a3 = new Point(w, h);
            b0 = new Point(0, 0), b1 = new Point(w, 0), b2 = new Point(0, h), b3 = new Point(w, h);
            fnDraw();
            //addEventListener(Event.ENTER_FRAME, fnUpdate);
        }

        /*private function fnUpdate(e:Event):void
        {
        fnDraw();
        }*/
        private function fnDraw():void
        {
            g.clear();
            TransformUtil.drawBitmapQuadrangle(g, bmd, a0, a1, a2, a3, b0, b1, b2, b3);//TransformUtil.drawBitmapTriangle(g,bmd, a0, a1, a2, b0, b1, b2);
        }

        private function fnDown(mouseEvent:MouseEvent):void
        {
            mouseEvent.currentTarget.startDrag();
        }

        private function fnMove(mouseEvent:MouseEvent):void
        {
            var _trgt:Object=mouseEvent.currentTarget
            this[_trgt.name].x = _trgt.x, this[_trgt.name].y = _trgt.y;
            fnDraw();
        }

        private function fnUp(mouseEvent:MouseEvent):void
        {
            var _trgt:Object=mouseEvent.currentTarget
            _trgt.stopDrag();
        }

        private function circle(sp:Sprite):void
        {
            var g:Graphics = sp.graphics;
            g.beginFill (0xFF0000,0.8);    // 面のスタイル設定
            g.drawCircle  ( 0, 0 ,6);//グラフィックス.drawCircle ( x 座標 , y 座標, 半径 );
        }

    }

}

import flash.geom.Point;
import flash.geom.Matrix;
import flash.display.Graphics;
import flash.display.BitmapData;

/**
 * TransformUtil
 * @author Kazuhiko Arase
 */
class TransformUtil {

    /**
     * ビットマップの三角形を描く。
     * <br/>0 - 1
     * <br/>| /
     * <br/>2
     * @param g グラフィックス
     * @param bitmapData ビットマップデータ
     * @param a0 転送元(ビットマップデータ)の座標
     * @param a1 転送元(ビットマップデータ)の座標
     * @param a2 転送元(ビットマップデータ)の座標
     * @param b0 転送先(グラフィック)の座標
     * @param b1 転送先(グラフィック)の座標
     * @param b2 転送先(グラフィック)の座標
     */
    public static function drawBitmapTriangle(
    g : Graphics, bitmapData : BitmapData,
    a0 : Point, a1 : Point, a2 : Point,
    b0 : Point, b1 : Point, b2 : Point
    ) : void {
        var matrix : Matrix = createMatrix(a0, a1, a2, b0, b1, b2);
        g.beginBitmapFill(bitmapData, matrix);
        drawTriangle(g, a0, a1, a2, matrix);
        g.endFill();
    }

    /**
     * ビットマップの四角形を描く。
     * <br/>0 - 1
     * <br/>|   |
     * <br/>2 - 3
     * @param g グラフィックス
     * @param bitmapData ビットマップデータ
     * @param a0 転送元(ビットマップデータ)の座標
     * @param a1 転送元(ビットマップデータ)の座標
     * @param a2 転送元(ビットマップデータ)の座標
     * @param a3 転送元(ビットマップデータ)の座標
     * @param b0 転送先(グラフィック)の座標
     * @param b1 転送先(グラフィック)の座標
     * @param b2 転送先(グラフィック)の座標
     * @param b3 転送先(グラフィック)の座標
     * @param hDiv 水平方向の分割数
     * @param vDiv 垂直方向の分割数
     */
    public static function drawBitmapQuadrangle(
    g : Graphics, bitmapData : BitmapData,
    a0 : Point, a1 : Point, a2 : Point, a3 : Point,
    b0 : Point, b1 : Point, b2 : Point, b3 : Point,
    hDiv : int = 4, vDiv : int = 4
    ) : void {

        for (var h : int = 0; h < hDiv; h++) {

            var h0 : Number = h / hDiv;
            var h1 : Number = (h + 1) / hDiv;

            var ta0 : Point = getPoint(a1, a0, h0);
            var ta1 : Point = getPoint(a1, a0, h1);
            var ta2 : Point = getPoint(a3, a2, h0);
            var ta3 : Point = getPoint(a3, a2, h1);

            var tb0 : Point = getPoint(b1, b0, h0);
            var tb1 : Point = getPoint(b1, b0, h1);
            var tb2 : Point = getPoint(b3, b2, h0);
            var tb3 : Point = getPoint(b3, b2, h1);

            for (var v : int = 0; v < vDiv; v++) {

                var v0 : Number = v / vDiv;
                var v1 : Number = (v + 1) / vDiv;

                var tta0 : Point = getPoint(ta1, ta0, v0);
                var tta1 : Point = getPoint(ta1, ta0, v1);
                var tta2 : Point = getPoint(ta3, ta2, v0);
                var tta3 : Point = getPoint(ta3, ta2, v1);

                var ttb0 : Point = getPoint(tb1, tb0, v0);
                var ttb1 : Point = getPoint(tb1, tb0, v1);
                var ttb2 : Point = getPoint(tb3, tb2, v0);
                var ttb3 : Point = getPoint(tb3, tb2, v1);

                drawBitmapTriangle(g, bitmapData,
                tta0, tta1, tta2, ttb0, ttb1, ttb2);
                drawBitmapTriangle(g, bitmapData,
                tta3, tta1, tta2, ttb3, ttb1, ttb2);
            }
        }
    }

    private static function getPoint(p0 : Point, p1 : Point, ratio : Number) : Point {
        return new Point(
        p0.x + (p1.x - p0.x) * ratio,
        p0.y + (p1.y - p0.y) * ratio
        );
    }

    private static function createMatrix(
    a0 : Point, a1 : Point, a2 : Point,
    b0 : Point, b1 : Point, b2 : Point
    ) : Matrix {

        var ma : Matrix = new Matrix(
        a1.x - a0.x, a1.y - a0.y,
        a2.x - a0.x, a2.y - a0.y);
        ma.invert();

        var mb : Matrix = new Matrix(
        b1.x - b0.x, b1.y - b0.y,
        b2.x - b0.x, b2.y - b0.y);

        var m : Matrix = new Matrix();

        // O(原点)へ移動
        m.translate(-a0.x, -a0.y);

        // 単位行列に変換(aの座標系の逆行列)
        m.concat(ma);

        // bの座標系に変換
        m.concat(mb);

        // b0へ移動
        m.translate(b0.x, b0.y);

        return m;
    }

    private static function drawTriangle(
    g : Graphics,
    p0 : Point, p1 : Point, p2 : Point,
    matrix : Matrix
    ) : void {

        p0 = matrix.transformPoint(p0);
        p1 = matrix.transformPoint(p1);
        p2 = matrix.transformPoint(p2);

        g.moveTo(p0.x, p0.y);
        g.lineTo(p1.x, p1.y);
        g.lineTo(p2.x, p2.y);
        g.lineTo(p0.x, p0.y);
    }
}