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

NESImage

画像を擬似ファミコンカラーパレットで(低精度)減色します。
色数は、ファミコンの同時発色数の制限等は再現してないので最大52色です。
Get Adobe Flash player
by o8que 16 Feb 2011
/**
 * Copyright o8que ( http://wonderfl.net/user/o8que )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/mx0p
 */

package {
    import com.adobe.images.PNGEncoder;
    import com.bit101.components.CheckBox;
    import com.bit101.components.Label;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.net.FileReference;
    
    [SWF(width="465",height="465")]
    public class Main extends Sprite {
        private static const MAX_WIDTH:int = 256; // 生成する画像の最大幅
        private static const MAX_HEIGHT:int = 224; // 生成する画像の最大高さ
        
        private var _loader:LocalImageLoader;
        private var _display:Bitmap;
        private var _loadButton:Button;
        private var _saveButton:Button;
        private var _EDCheck:CheckBox;
        
        public function Main() {
            graphics.beginFill(0x000000);
            graphics.drawRect(0, 0, 465, 465);
            graphics.endFill();
            
            _loader = new LocalImageLoader();
            _display = new Bitmap(new BitmapData(1, 1, true, 0x00FFFFFF));
            addChild(_display);
            
            _loadButton = new Button(100, 20);
            _loadButton.x = 122; _loadButton.y = 420;
            _loadButton.setFace(new Label(null, 0, 0, "Load"));
            _loadButton.addEventListener(MouseEvent.CLICK, clickLoadButtonHandler);
            addChild(_loadButton);
            
            _saveButton = new Button(100, 20);
            _saveButton.x = 242; _saveButton.y = 420;
            _saveButton.setFace(new Label(null, 0, 0, "Save"));
            _saveButton.addEventListener(MouseEvent.CLICK, clickSaveButtonHandler);
            addChild(_saveButton);
            _saveButton.enabled = false;
            
            _EDCheck = new CheckBox(this, 0, 445, "ErrorDiffusion");
            _EDCheck.x = 122 + (int((100 - _EDCheck.width) / 2));
            _EDCheck.selected = true;
        }
        
        private function clickLoadButtonHandler(event:MouseEvent):void {
            _loader.addEventListener(Event.COMPLETE, quantizeImage);
            _loader.addEventListener(Event.CANCEL, cancelLoading);
            _loader.load();
            _loadButton.enabled = false;
        }
        
        private function quantizeImage(event:Event):void {
            _loader.removeEventListener(Event.COMPLETE, quantizeImage);
            _loader.removeEventListener(Event.CANCEL, cancelLoading);
            
            var image:DisplayObject = _loader.content;
            image.scaleX = image.scaleY = Math.min(1, MAX_WIDTH / image.width, MAX_HEIGHT / image.height);
            var bmd:BitmapData = new BitmapData(image.width, image.height, false, 0x000000);
            bmd.draw(image, image.transform.matrix, null, null, null, true);
            
            _display.bitmapData = NESImage.quantize(bmd, _EDCheck.selected);
            _display.scaleX = _display.scaleY = Math.min(1, 465 / _display.bitmapData.width, 465 / _display.bitmapData.height);
            _display.x = int((465 - _display.width) / 2);
            _display.y = int((465 - _display.height) / 2);
            
            _loadButton.enabled = _saveButton.enabled = true;
        }
        
        private function cancelLoading(event:Event):void {
            _loader.removeEventListener(Event.COMPLETE, quantizeImage);
            _loader.removeEventListener(Event.CANCEL, cancelLoading);
            _loadButton.enabled = true;
        }
        
        private function clickSaveButtonHandler(event:MouseEvent):void {
            (new FileReference()).save(PNGEncoder.encode(_display.bitmapData),"NESImage.png");
        }
    }
}
/* ------------------------------------------------------------------------------------------------
 * NESImage
 * ------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.BitmapData;
    import flash.display.Loader;
    import frocessing.color.ColorHSL;
    
    //public
    class NESImage {
        
        public static function quantize(source:BitmapData, usesErrorDiffusion:Boolean):BitmapData {
            var width:int = source.width;
            var height:int = source.height;
            var bmd:BitmapData = new BitmapData(width, height, false, 0x000000);
            bmd.lock();
            
            var x:int, y:int;
            var original:ColorHSL = new ColorHSL();
            var quantized:ColorHSL = new ColorHSL();
            if (usesErrorDiffusion) {
                var error:ColorError;
                var errorTable:Vector.<Vector.<ColorError>> = new Vector.<Vector.<ColorError>>(height + 1, true);
                for (y = height; y >= 0; y--) {
                    errorTable[y] = new Vector.<ColorError>(width + 2, true);
                    for (x = width + 1; x >= 0; x--) {
                        errorTable[y][x] = new ColorError();
                    }
                }
            }
            // 誤差拡散を行うかどうかで、各閾値を少し変える
            var thresholds:Vector.<Number> = new Vector.<Number>(6, true);
            thresholds[0] = (usesErrorDiffusion) ? 0.1 : 0.125;
            thresholds[1] = (usesErrorDiffusion) ? 0.9 : 0.875;
            thresholds[2] = (usesErrorDiffusion) ? 0.2 : 0.225;
            thresholds[3] = (usesErrorDiffusion) ? 0.625 : 0.6;
            thresholds[4] = (usesErrorDiffusion) ? 0.875 : 0.85;
            thresholds[5] = (usesErrorDiffusion) ? 0.25 : 0.3;
            
            for (y = 0; y < height; y++) {
                for (x = 0; x < width; x++) {
                    original.value = source.getPixel(x, y);
                    
                    // 誤差の補正を加える
                    if (usesErrorDiffusion) {
                        error = errorTable[y][x + 1];
                        original.hsl(original.h + error.h, original.s, original.l + error.l);
                    }
                    
                    var originalH:Number = original.h;
                    var originalS:Number = original.s;
                    var originalL:Number = original.l;
                    var quantizedH:Number;
                    var quantizedS:Number;
                    var quantizedL:Number;
                    
                    if (originalL < thresholds[0]) {
                        // 黒
                        quantizedH = quantizedS = quantizedL = 0;
                    }else if (originalL > thresholds[1]) {
                        // 白
                        quantizedH = quantizedS = 0;
                        quantizedL = 1;
                    }else if (originalS < thresholds[2]) {
                        // モノクロ
                        quantizedH = quantizedS = 0;
                        if (originalL > thresholds[3]) {
                            if (originalL > thresholds[4]) {
                                quantizedL = 1;
                            }else {
                                quantizedL = 0.75;
                            }
                        }else {
                            if (originalL > thresholds[5]) {
                                quantizedL = 0.5;
                            }else {
                                quantizedL = 0;
                            }
                        }
                    }else {
                        // カラー
                        quantizedS = 1;
                        if (originalH < 135) {
                            if (originalH < 65) {
                                if (originalH < 10) {
                                    quantizedH = 0;
                                }else if (originalH < 30) {
                                    quantizedH = 20;
                                }else {
                                    quantizedH = 40;
                                }
                            }else {
                                if (originalH < 105) {
                                    quantizedH = 90;
                                }else {
                                    quantizedH = 120;
                                }
                            }
                        }else if (originalH < 255) {
                            if (originalH < 195) {
                                if (originalH < 165) {
                                    quantizedH = 150;
                                }else {
                                    quantizedH = 180;
                                }
                            }else {
                                if (originalH < 225) {
                                    quantizedH = 210;
                                }else {
                                    quantizedH = 240;
                                }
                            }
                        }else {
                            if (originalH < 320) {
                                if (originalH < 285) {
                                    quantizedH = 270;
                                }else {
                                    quantizedH = 300;
                                }
                            }else {
                                if (originalH < 350) {
                                    quantizedH = 340;
                                }else {
                                    quantizedH = 0;
                                }
                            }
                        }
                        
                        if (originalL > 0.5) {
                            if (originalL > 0.7) {
                                quantizedL = 0.8;
                            }else {
                                quantizedL = 0.6;
                            }
                        }else {
                            if (originalL > 0.3) {
                                quantizedL = 0.4;
                            }else {
                                quantizedL = 0.2;
                            }
                        }
                    }
                    quantized.hsl(quantizedH, quantizedS, quantizedL);
                    bmd.setPixel(x, y, quantized.value);
                    
                    // 元の色と変換後の色の誤差を拡散させる
                    if (usesErrorDiffusion) {
                        var diffH1:Number = (quantizedS == 1) ? originalH - quantizedH : 0;
                        var diffH2:Number = (diffH1 < 0) ? 360 + diffH1 : 360 - diffH1;
                        var errorH:Number = ((Math.abs(diffH1) < Math.abs(diffH2)) ? diffH1 : diffH2) * 0.0625;
                        var errorL:Number = (originalL - quantizedL) * 0.0625;
                        errorTable[y][x + 2].add(errorH * 7, errorL * 7);
                        errorTable[y + 1][x].add(errorH * 3, errorL * 3);
                        errorTable[y + 1][x + 1].add(errorH * 5, errorL * 5);
                        errorTable[y + 1][x + 2].add(errorH, errorL);
                    }
                }
            }
            
            bmd.unlock();
            return bmd;
        }
    }
//}
class ColorError {
    public var h:Number;
    public var l:Number;
    
    public function ColorError() {
        this.h = this.l = 0;
    }
    
    public function add(h:Number, l:Number):void {
        this.h += h;
        this.l += l;
    }
}
/* ------------------------------------------------------------------------------------------------
 * Button
 * ------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.DisplayObject;
    import flash.display.GradientType;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.filters.DropShadowFilter;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Point;
    
    //public 
    class Button extends Sprite {
        private var _size:Point;
        private var _border:Shape;
        private var _background:Shape;
        private var _faceContainer:Sprite;
        private var _face:DisplayObject;
        private var _facePosition:Point;
        private var _hovered:Boolean;
        private var _pressed:Boolean;
        
        private var _selected:Boolean;
        private var _enabled:Boolean;
        
        public function Button(width:int, height:int) {
            _size = new Point(width, height);
            addChild(_border = new Shape());
            addChild(_background = new Shape());
            addChild(_faceContainer = new Sprite());
            _faceContainer.addChild(_face = new Shape());
            _facePosition = new Point(0, 0);
            _hovered = _pressed = false;
            
            var matrix:Matrix = new Matrix();
            matrix.createGradientBox(_size.x - 2, _size.y - 2, Math.PI / 2, 1, 1);
            _background.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0xE0E0E0], [1, 1], [0, 255], matrix);
            _background.graphics.drawRect(1, 1, _size.x - 2, _size.y - 2);
            _background.graphics.endFill();
            
            selected = false;
            enabled = true;
            
            mouseChildren = false;
            addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
            addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
        }
        
        private function rollOverHandler(event:MouseEvent):void {
            _hovered = true;
            draw();
            addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
        }
        
        private function rollOutHandler(event:MouseEvent):void {
            removeEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
            _hovered = false;
            draw();
        }
        
        private function mouseDownHandler(event:MouseEvent):void {
            _pressed = true;
            draw();
            stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
        }
        
        private function mouseUpHandler(event:MouseEvent):void {
            stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
            _pressed = false;
            draw();
        }
        
        private static const DOWN:Array = [new DropShadowFilter(1, 45, 0x404040, 0.5, 1, 1, 1, 1, true)];
        private static const UP:Array = [];
        private static const HOVER:ColorTransform = new ColorTransform(0.5, 0.5, 0.5, 1, 128, 128, 128);
        private static const NORMAL:ColorTransform = new ColorTransform(1, 1, 1);
        private static const DISABLED:ColorTransform = new ColorTransform(0.7, 0.7, 0.7);
        
        private function draw():void {
            _border.graphics.clear();
            _border.graphics.beginFill((_selected) ? 0xFFFF00 : 0xC0C0C0);
            _border.graphics.drawRect(0, 0, _size.x, _size.y);
            _border.graphics.endFill();
            
            _background.filters = (_pressed) ? DOWN : UP;
            
            _face.x = _facePosition.x + int(_pressed);
            _face.y = _facePosition.y + int(_pressed);
            
            transform.colorTransform = (_enabled) ? ((_hovered) ? HOVER : NORMAL) : DISABLED;
        }
        
        public function setFace(face:DisplayObject):void {
            _faceContainer.removeChild(_face);
            _face = face;
            _face.x = _facePosition.x = (_size.x - _face.width) / 2;
            _face.y = _facePosition.y = (_size.y - _face.height) / 2;
            _faceContainer.addChild(_face);
        }
        
        public function get selected():Boolean { return _selected; }
        public function get enabled():Boolean { return _enabled; }
        
        public function set selected(value:Boolean):void {
            _selected = value;
            draw();
        }
        public function set enabled(value:Boolean):void {
            _enabled = buttonMode = mouseEnabled = value;
            draw();
        }
    }
//}
/* ------------------------------------------------------------------------------------------------
 * LocalImageLoader
 * ------------------------------------------------------------------------------------------------
 */
//package {
    import flash.display.DisplayObject;
    import flash.display.Loader;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.net.FileFilter;
    import flash.net.FileReference;
    
    //public 
    class LocalImageLoader extends EventDispatcher {
        private var _loader:Loader;
        private var _file:FileReference;
        private var _fileFilter:Array;
        
        public function LocalImageLoader() {
            _loader = new Loader();
            _file = new FileReference();
            _fileFilter = [new FileFilter("Image (*.png;*.jpg;*.gif)", "*.png;*.jpg;*.gif")];
        }
        
        public function load():void {
            _file.addEventListener(Event.SELECT, onFileSelected);
            _file.addEventListener(Event.CANCEL, cancelFileSelection);
            _file.browse(_fileFilter);
        }
        
        private function onFileSelected(event:Event):void {
            _file.addEventListener(Event.COMPLETE, onFileLoaded);
            _file.load();
        }
        
        private function onFileLoaded(event:Event):void {
            removeFileListeners();
            _loader.unload();
            _loader.contentLoaderInfo.addEventListener(Event.INIT, onLoadCompleted);
            _loader.loadBytes(_file.data);
        }
        
        private function onLoadCompleted(event:Event):void {
            _loader.contentLoaderInfo.removeEventListener(Event.INIT, onLoadCompleted);
            dispatchEvent(new Event(Event.COMPLETE));
        }
        
        private function cancelFileSelection(event:Event):void {
            removeFileListeners();
            dispatchEvent(new Event(Event.CANCEL));
        }
        
        private function removeFileListeners():void {
            _file.removeEventListener(Event.SELECT, onFileSelected);
            _file.removeEventListener(Event.CANCEL, cancelFileSelection);
            _file.removeEventListener(Event.COMPLETE, onFileLoaded);
        }
        
        public function get content():DisplayObject { return _loader.content; }
    }
//}