In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Circles Mosaic

Creates a mosaic with circles that don't overlaps each other
/**
 * Copyright will_costa ( http://wonderfl.net/user/will_costa )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/2HZz
 */

package {
    import com.adobe.images.JPGEncoder;
    import com.bit101.components.PushButton;

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.net.FileReference;
    import flash.utils.ByteArray;

    /**
     * @author Will Costa
     * @author http://www.willcosta.net
     */
    [SWF(backgroundColor="#000000", frameRate="60", width="465", height="465")]
    public class CirclesMosaic extends Sprite {
        public static const ITERATIONS_PER_FRAME : int = 20;
        
        private var _source : BitmapData;
        private var _container : Bitmap;
        private var _mosaic : Mosaic;
        private var _fileLoader:FileLoader;
        private var _loadButton:PushButton;
        private var _saveButton:PushButton;
        private var _initialized:Boolean = false;

        public function CirclesMosaic() {
            Wonderfl.capture_delay(20);
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            _fileLoader = new FileLoader();
            _fileLoader.addEventListener(Event.INIT, _fileLoader_onCompleteHandler);
            _loadButton = new PushButton(this, 0, 0, "Load Image", _loadButton_onClickHandler);
            _saveButton = new PushButton(this, _loadButton.width + 5, 0, "Save Image", _saveButton_onClickHandler);
            _saveButton.enabled = false;
        }
           
        // ----------------------------------
        // Private Functions
        // ----------------------------------
        private function init():void{
            dispose();
            _initialized = true;
            _source = resizeBitmapData(_fileLoader.bitmapData);
            _mosaic = new Mosaic(_source);
            _container = new Bitmap(_mosaic.bitmapData);
            _container.x = (465-_container.width)/2;
            _container.y = (465-_container.height)/2;
            addChildAt(_container, 0);

            addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
            _saveButton.enabled = true;
        }
        
        private function dispose():void{
            if(!_initialized) return;
            _mosaic.dispose();
            removeChild(_container);
            _source.dispose();
        }
        
           private function resizeBitmapData(bitmapData : BitmapData) : BitmapData {
            var bmp : Bitmap = new Bitmap(bitmapData);
            if(bmp.width > 465){
                bmp.width = 465;
                bmp.scaleY = bmp.scaleX;
            }
            if(bmp.height > 465){
                bmp.height = 465;
                bmp.scaleX = bmp.scaleY;
            }
            var resizedBD:BitmapData = new BitmapData(bmp.width, bmp.height);
            resizedBD.draw(bmp,bmp.transform.matrix);
            return resizedBD;
        }
           
           // ----------------------------------
        // Event Handlers
           // ----------------------------------
           private function _loadButton_onClickHandler(event:Event):void{
            _fileLoader.load();
        }
        
        private function _saveButton_onClickHandler(event : Event):void {
            var myBitmapData : BitmapData = new BitmapData(_container.width, _container.height);
            myBitmapData.draw(_container);
            var jpgEncoder:JPGEncoder = new JPGEncoder(80);
            var imgByteData:ByteArray = jpgEncoder.encode(myBitmapData);
            var file:FileReference = new FileReference();
            file.save(imgByteData, "image_mosaic.jpg");
        }
        
        private function _fileLoader_onCompleteHandler(event : Event) : void {
            init();
        }

        private function onEnterFrameHandler(event : Event) : void {
            for (var i : int = 0; i < ITERATIONS_PER_FRAME; i++) {
                _mosaic.expandPixel(int(Math.random() * _mosaic.width), int(Math.random() * _mosaic.height));    
            }
        }
        
    }
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Shape;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.geom.Point;
import flash.net.FileFilter;
import flash.net.FileReference;

internal class Mosaic {
    public static const IMAGE_DEPTH : int = 6;
    public static const BASE_COLOR:uint = 0xFF00FF00;
    public var width : Number = 0;
    public var height : Number = 0;
    private var _originalSource : BitmapData;
    private var _source : BitmapData;
    private var _filledArea : BitmapData;
    private var _bitmapData : BitmapData;
    private var _circle : Shape;

    public function Mosaic(source : BitmapData) {
        width = source.width;
        height = source.height;
        _circle = new Shape();
        _source = source;
        _originalSource = _source.clone();
        changeColorDepth(_source, IMAGE_DEPTH);
        _bitmapData = new BitmapData(width, height, false, 0);
        _filledArea = new BitmapData(width, height, true, BASE_COLOR);
    }
    
    public function expandPixel(x : int, y : int):void {
        var checkColor : uint = _filledArea.getPixel32(x, y);
        if(checkColor != BASE_COLOR) return;
        
        var color : uint = _source.getPixel32(x, y);
        var fillColor : uint = _originalSource.getPixel(x, y);
        var strokeColor : uint = darkenColor(fillColor);
        
        var area : BitmapData = _source.clone();
        area.threshold(area, area.rect, new Point(), "==", color,0);
        var size:int = 1;
        
        while(_circle.width < _source.width){
            _circle.graphics.clear();
            _circle.graphics.lineStyle(1, 0);
            _circle.graphics.beginFill(fillColor);
            _circle.graphics.drawCircle(size, size, size);
            _circle.graphics.endFill();
            _circle.graphics.lineStyle();
            _circle.graphics.beginFill(strokeColor);
            if(size > 5)_circle.graphics.drawCircle(size, size, size/2);
            _circle.graphics.endFill();
            var hit : BitmapData = new BitmapData(_circle.width, _circle.height, true, 0);
            hit.draw(_circle);
            if(hit.hitTest(new Point(x-size, y-size), 255, area, new Point(0, 0))) {
                _circle.x = x - size;
                _circle.y = y - size;
                _source.draw(_circle, _circle.transform.matrix);
                _bitmapData.draw(_circle, _circle.transform.matrix);
                _filledArea.draw(_circle, _circle.transform.matrix);
                break;
            }
            hit.dispose();
            size += 1;
        }
        area.dispose();
    }
    
    public function dispose():void {
        _bitmapData.dispose();
        _filledArea.dispose();
        _source.dispose();
        _originalSource.dispose();
    }
    
    
    private function changeColorDepth(source : BitmapData, depth : int = 16) : void {
        var Ra : Array = new Array(256);
        var Ga : Array = new Array(256);
        var Ba : Array = new Array(256);
        var n : Number = 256 / ( depth / 3 );
        for (var i : int = 0;i < 256;i++) {
            Ba[i] = Math.floor(i / n) * n;
            Ga[i] = Ba[i] << 8;
            Ra[i] = Ga[i] << 8;
        }
        source.paletteMap(source, source.rect, new Point(), Ra, Ga, Ba);
    }
    
    private function darkenColor(color : uint) : uint {
            var q : Number = .9;
            var colorA : uint = (color >> 24) & 0xFF;
            var colorR : uint = (color >> 16) & 0xFF;
            var colorG : uint = (color >> 8) & 0xFF;
            var colorB : uint = color & 0xFF;
        
            var resultA : uint = colorA * q;
            var resultR : uint = colorR * q;
            var resultG : uint = colorG * q;
            var resultB : uint = colorB * q;
            var resultColor : uint = resultA << 24 | resultR << 16 | resultG << 8 | resultB;
            return resultColor;  
    }
    
    public function get bitmapData() : BitmapData {
        return _bitmapData;
    }
    
    
}

internal class FileLoader extends EventDispatcher {
    public var data : *;
    public var bitmapData : BitmapData;
    private var typeFilter : Array;
    private var file : FileReference;
    private var loader : Loader;

    public function FileLoader() {
        init();
    }

    private function init():void {
        file = new FileReference();
        file.addEventListener(Event.SELECT, select, false, 0, true);
        file.addEventListener(Event.CANCEL, cancel, false, 0, true);
        file.addEventListener(Event.COMPLETE, complete, false, 0, true);
        var fileFilter : FileFilter = new FileFilter("Images", "*.jpg;*.jpeg;*.gif;*.png");
        typeFilter = [fileFilter];
        loader = new Loader();
        loader.contentLoaderInfo.addEventListener(Event.INIT, initialize, false, 0, true);
    }

    public function load():void {
        file.browse(typeFilter);
    }
    
    private function select(evt : Event):void {
        file.load();
        dispatchEvent(evt);
    }

    private function cancel(evt : Event):void {
        dispatchEvent(evt);
    }

    private function complete(evt : Event):void {
        data = evt.target.data;
        loader.loadBytes(data);
        dispatchEvent(evt);
    }

    private function initialize(evt : Event):void {
        bitmapData = null;
        var bitmap : Bitmap = Bitmap(evt.target.content);
        bitmapData = bitmap.bitmapData;
        dispatchEvent(evt);
    }
}