1

BitmapDataを操作およびアニメーション化して、以下のリンクにあるような渦巻き効果を作成したいと思います。

http://www.flash-filter.net/swirl-effect.phtml

どのようなテクニックを適用できますか?

ところで:はい、私は効果が醜いことを知っています。

4

4 に答える 4

3

スワール効果がどのように達成されるか、つまりアルゴリズムを探している場合。これは、画像がどのように変換されるかを段階的に説明したものです。画像のツイストとスワールのアルゴリズム

于 2012-05-05T16:19:02.203 に答える
2

このためのピクセルベンダーフィルターがあります。このリンクをチェックしてください:

http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&extid=1536021

これがTweeningPixelBenderフィルターのチュートリアルです

http://plasticsturgeon.com/2011/03/pixel-transition-tweening-a-pixel-bender-filter-in-as3/

AS3ImageProcessingライブラリを確認することもできます

http://blog.joa-ebert.com/imageprocessing-library/

これはあなたに良い出発点を与えるはずです

于 2012-05-05T15:08:51.390 に答える
2

Pixel Bender ist krieg!

私は以前の回答に同意しますが、この種の効果は、何年も前から存在しているビットマップフィルター、つまりDisplacementMapFilterのみを使用することで実行できることを指摘しておきます。ピクセルを円方向に移動するディスプレースメントマップを作成し、このマップを画像に複数回適用します。これにより、渦巻く変化が得られます。

これが私の簡単な実装です。
使い方はとても簡単です(クラスの後を見てください)。

package org.noregret.images
{
    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.display.BlendMode;
    import flash.display.DisplayObject;
    import flash.display.GradientType;
    import flash.display.InterpolationMethod;
    import flash.display.SpreadMethod;
    import flash.display.Sprite;
    import flash.filters.DisplacementMapFilter;
    import flash.filters.DisplacementMapFilterMode;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;

    /**
     * @author Nox Noctis (http://noregret.org)
     */
    public class Swirl 
    {
        public var target : DisplayObject;
        public var allowCache : Boolean = false;
        public var levels : uint;
        public var isDestroyed : Boolean;

        protected var bitmapMargin : Point;
        protected var filter : DisplacementMapFilter;
        protected var radius : int;
        protected var cache : Object;
        protected var map : BitmapData;

        protected var targetRect : Rectangle;
        protected var mapOffset : Point;
        protected var maxLevel : Number = 1;

        public function Swirl(_target : DisplayObject, _filterLevels : uint = 10, _allowCache : Boolean = true) 
        {

            target = _target;
            allowCache = _allowCache;
            levels = _filterLevels;

            cache = {};

            filter = new DisplacementMapFilter();
            filter.componentX = BitmapDataChannel.RED;
            filter.componentY = BitmapDataChannel.GREEN;
            filter.scaleX = -20;
            filter.scaleY = -20;
            filter.mapPoint = new Point();
            filter.mode = DisplacementMapFilterMode.IGNORE;
        }

        private function createDisplacementMap() : void
        {
            targetRect = target.getRect(target);

            radius = Math.max(Math.max(targetRect.width, targetRect.height), 100) / 2;
            radius = Math.sqrt(2) * radius;

            mapOffset = new Point(radius - targetRect.width / 2, radius - targetRect.height / 2);   

            var mapSprite : Sprite = new Sprite();
            var redLayer : Sprite = new Sprite();
            var greenLayer : Sprite = new Sprite();
            var grayLayer : Sprite = new Sprite();
            mapSprite.addChild(redLayer);
            mapSprite.addChild(greenLayer);
            mapSprite.addChild(grayLayer);

            var gradientMatrix : Matrix;

            gradientMatrix = new Matrix();
            gradientMatrix.createGradientBox(radius * 2, radius * 2, Math.PI / 2, -radius, -radius);

            redLayer.graphics.lineStyle(0, 0, 0);
            redLayer.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0], [100, 100], [0, 255], gradientMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);

            redLayer.graphics.drawCircle(0, 0, radius);
            redLayer.graphics.endFill();


            greenLayer.graphics.lineStyle(0, 0, 0);
            gradientMatrix.createGradientBox(radius * 2, radius * 2, 0, -radius, -radius);
            greenLayer.graphics.beginGradientFill(GradientType.LINEAR, [0x00FF00, 0x00FF00], [0, 100], [10, 245], gradientMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);

            greenLayer.graphics.drawCircle(0, 0, radius);
            greenLayer.graphics.endFill();
            greenLayer.blendMode = BlendMode.ADD;


            gradientMatrix = new Matrix();
            gradientMatrix.createGradientBox(radius * 2, radius * 2, 0, -radius, -radius);
            grayLayer.graphics.lineStyle(0, 0, 0);
            grayLayer.graphics.beginGradientFill(GradientType.RADIAL, [0x808080, 0x808080], [0, 100], [0, 0xFF], gradientMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);
            grayLayer.graphics.drawCircle(0, 0, radius);
            grayLayer.graphics.endFill();

            var rect : Rectangle = mapSprite.getRect(mapSprite);
            var matrix : Matrix = new Matrix();
            matrix.translate(-rect.x, -rect.y);
            if (map) {
                map.dispose();
            }
            map = new BitmapData(rect.width, rect.height, false, 0xFF808080);
            map.draw(mapSprite, matrix);
            filter.mapBitmap = map;
        }

        public function swirlTo(ratio : Number) : BitmapData
        {
            if (isDestroyed) {
                trace("Swirl: error! Tried to swirl on disposed item.");
                return null;
            }
            if (ratio < 0) {
                ratio = 0;
            }

            var level : uint = Math.round(levels * ratio);
            var cacheName : String = getCacheName(level);
            if (cache[cacheName]) {
                return (cache[cacheName] as BitmapData).clone();
            }

            var rect : Rectangle = target.getRect(target);
            if (!map || rect.width != targetRect.width || rect.height != targetRect.height) {
                createDisplacementMap();
                flushCache();
            }

            var point : Point = new Point(-targetRect.x, -targetRect.y);
            bitmapMargin = new Point(point.x + mapOffset.x, point.y + mapOffset.y);

            var bmp : BitmapData;
            if (cache["l" + maxLevel]) {
                bmp = cache["l" + maxLevel] as BitmapData;
            } else {
                bmp = new BitmapData(map.width, map.height, true, 0);
                var matrix : Matrix = new Matrix();
                matrix.translate(bitmapMargin.x, bitmapMargin.y);
                bmp.draw(target, matrix, null, null, null, true);
            }            

            if (level == 0) {
                cache[cacheName] = bmp.clone();
                return bmp;
            }

            var destPoint : Point = new Point();
            for (var i : Number = maxLevel;i <= level; i++) {
                bmp.applyFilter(bmp, bmp.rect, destPoint, filter);
                if (allowCache) {
                    cache["l" + i] = bmp.clone();
                }
            }
            maxLevel = Math.max(maxLevel, level);

            return bmp;
        }

        private function getCacheName(level : uint) : String
        {
            return "l" + level;
        }

        public function flushCache() : void
        {
            for each (var bmp:BitmapData in cache) {
                bmp.dispose();
            }
            cache = {};
        }

        public function destroy() : void
        {
            flushCache();
            target = null;
            map.dispose();
            map = null;
            isDestroyed = true;
        }
    }
}

使用例:

package
{
    import flash.display.Sprite;
    import flash.display.Loader;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    import flash.display.Bitmap;
    import org.noregret.images.Swirl;

    [SWF(width="800",height="600",backgroundColor="#FFFFFF",fps="30")]
    public class TestSwirl extends Sprite
    {
        private const loader:Loader = new Loader();
        private const swirlBitmap:Bitmap = new Bitmap();
        private var swirl:Swirl;
        private var time:Number = 0;

        public function TestSwirl()
        {
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
            var request:URLRequest = new URLRequest("http://i.stack.imgur.com/Vtsvm.gif");
            loader.load(request, new LoaderContext(true));            
        }

        protected function onLoadComplete(event:Event):void
        {
            var original:Bitmap = loader.content as Bitmap;
            addChild(original);

            swirlBitmap.bitmapData = original.bitmapData.clone();
            swirlBitmap.x = original.x + original.width + 10;
            addChild(swirlBitmap);        

            swirl = new Swirl(original,80);
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }

        protected function onEnterFrame(event:Event):void
        {
            var ratio:Number = Math.abs(Math.sin(time));
            // ***
            swirlBitmap.bitmapData = swirl.swirlTo(ratio);
            // ***
            time += .02;
        }
    }
}
于 2012-05-05T19:58:13.637 に答える
1

PixelBenderを使用して独自のビットマップフィルターを作成することをお勧めします。

于 2012-05-05T15:08:33.933 に答える