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

Posterize

FileReference で読み込んだ画像をポスタライズ
@author YOSHIDA, Akio (Aquioux)
Get Adobe Flash player
by Aquioux 25 Dec 2009
/**
 * Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/jox5
 */

package {
	import flash.display.Sprite;
	import flash.events.Event;
	/**
	 * FileReference で読み込んだ画像をポスタライズ
	 * @author YOSHIDA, Akio (Aquioux)
	 */
	[SWF(width = "465", height = "465", frameRate = "20", backgroundColor = "#FFFFFF")]
	
	public class Main extends Sprite {
		
		public function Main() {
			Wonderfl.capture_delay(15);
			
			// Model を生成
			var model:Model = new Model(stage);

			// View を生成
			var view:View = new View(model);
			addChild(view);
			
			// Controller を生成
			var controller:Controller = new Controller(model);
			controller.setup(stage);
		}
	}
}


	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	class Model extends EventDispatcher {

		public const MAX_RENGE:uint = 16;	// ポスタライズ諧調最大値(256より大きい値の設定不可)
		public const MIN_RENGE:uint = 2;	// ポスタライズ諧調最小値(2より小さい値の設定不可)
		
		private var stageWidth:uint;		// ステージ幅
		private var stageHeight:uint;		// ステージ高
		
		private const imageEdge:uint = 420;	// 表示される画像の辺の最大値
		
		private var _saveBitmapData:BitmapData;	// 読み込んだ画像の BitmapData の退避
		private var _rect:Rectangle;						// BitmapData.draw 用 Rectangle
		private const DEST_POINT:Point = new Point(0, 0);	// BitmapData.draw 用 Point

		// --------------------------------------------------
		// View へ渡すデータ(プロパティ)
		// --------------------------------------------------
		/**
		 * 加工済みの画像
		 */
		private var _data:BitmapData;
		public function get data():BitmapData { return _data; }
		
		// --------------------------------------------------
		// 外部との通信をおこなうメソッド
		// --------------------------------------------------
		/**
		 * 対 View 用メソッド
		 * このメソッドの終了時にイベントを発行するので、View との通信手段となる
		 * @private
		 */
		private function update():void {
			dispatchEvent(new Event(Event.CHANGE));
		}
		
		/**
		 * 対 Controller 用メソッド
		 * PushButton
		 * @param	bitmapData	FileReference で読み込んだ画像の BitmapData
		 */
		internal function updateFromPushButton(bitmapData:BitmapData):void {
			_saveBitmapData.fillRect(_rect, 0xFFFFFFFF);
			var scale:Number = imageEdge / Math.max(bitmapData.width, bitmapData.height);
			var w:uint = bitmapData.width  * scale;
			var h:uint = bitmapData.height * scale;
			_saveBitmapData.draw(bitmapData, new Matrix(scale, 0, 0, scale, (stageWidth - w) / 2 >> 0, (stageHeight - h) / 2 >> 0));
			updateFromSlider(MAX_RENGE);
		}
		
		/**
		 * 対 Controller 用メソッド
		 * Slider
		 * @param	val	スライダーからの値
		 */
		internal function updateFromSlider(val:uint):void {
			_data = _saveBitmapData.clone()
			posterize(_data, val);
			update();
		}
		
		// --------------------------------------------------
		// その他のメソッド
		// --------------------------------------------------
		/**
		 * コンストラクタ
		 */
		public function Model(stage:Stage) {
			stageWidth  = stage.stageWidth;
			stageHeight = stage.stageHeight;
			_saveBitmapData = new BitmapData(stageWidth, stageHeight);
			_rect = _saveBitmapData.rect;
		}

		/**
		 * ポスタライズ
		 * @private
		 */
		private function posterize(bitmapData:BitmapData, step:uint):void {
			if (step < MIN_RENGE || step > MAX_RENGE){
				var message:String = "ステップ数は" + MIN_RENGE + "から" + MAX_RENGE + "の間です"
				throw(new Error(message));
			}
			// 各段階における色階層値を計算
			var thresholds:Array = [];
			for (var i:int = 0; i < step; i++) {
				thresholds[i] = ((256 / (step - 1)) * i) >> 0;
			}
			var lastIdx:uint = step - 1;
			if (thresholds[lastIdx] != 255) thresholds[lastIdx] = 255;
			
			// palletMap 用 Array の生成
			var r:Array = [];
			var g:Array = [];
			var b:Array = [];
			for (i = 0; i < 256; i++) {
				var idx:uint = (i / (256 / step)) >> 0;
				var val:uint = thresholds[idx];
				r[i] = val << 16;
				g[i] = val <<  8;
				b[i] = val;
			}
			
			// paletteMap
			bitmapData.paletteMap(bitmapData, _rect, DEST_POINT, r, g, b);
		}
	}


	import flash.display.Bitmap;
	import flash.events.Event;
	/**
	 * @author YOSHIDA, Akio (Aquioux)
	 */

	class View extends Bitmap {
		/**
		 * コンストラクタ
		 * @param	model	Model
		 */
		private var model:Model;
		public function View(model:Model) {
			this.model = model;
			this.model.addEventListener(Event.CHANGE, changeHandler);
		}
		
		/**
		 * Model との通信手段
		 * @private
		 */
		private function changeHandler(event:Event):void {
			// Model からデータを受け取り、視覚化
			this.bitmapData = model.data;
		}
	}


	import com.bit101.components.Label;
	import com.bit101.components.PushButton;
	import com.bit101.components.Slider;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.net.FileReference;

	class Controller {
		private var sliderLayer:Sprite;
		private var slider:Slider;
		private var label:Label;
		private var pushButton:PushButton;
		
		/**
		 * コンストラクタ
		 * @param	model	Model
		 */
		private var model:Model;
		public function Controller(model:Model) {
			this.model = model;
		}
		
		/**
		 * セットアップ
		 * @param	stage	ステージ
		 */
		private var stage:Stage;
		public function setup(stage:Stage):void {
			this.stage = stage;
			this.stage.addChild(sliderLayer = initSlider());
			this.stage.addChild(initPushButton());
		}
		
		/**
		 * スライダーの生成
		 * @private
		 */
		private function initSlider():Sprite {
			var layer:Sprite = new Sprite();
			// スライダー
			slider = new Slider(Slider.HORIZONTAL, null, 0, 0, sliderHandler);
			slider.setSliderParams(model.MIN_RENGE, model.MAX_RENGE, model.MAX_RENGE);
			slider.width = stage.stageWidth;
			slider.y = stage.stageHeight - slider.height;
			layer.addChild(slider);
			// ステップ数を表示するラベル
			label = new Label();
			changeLabel(slider.value);
			label.y = slider.y - label.height;
			layer.addChild(label);
			
			layer.visible = false;	// 最初は不可視
			
			return layer;
		}
		/**
		 * スライダーのラベルの表示を書き換える
		 * @private
		 */
		private function changeLabel(value:uint):void {
			label.text = "Step " + String(value);
		}
		/**
		 * イベントハンドラ
		 * Model との通信手段
		 * Slider のイベント
		 * @private
		 */
		private function sliderHandler(event:Event):void {
			var sliderValue:uint = int(event.target.value);
			changeLabel(sliderValue);	// スライダーのラベルを書き換える
			model.updateFromSlider(sliderValue);
		}
		

		/**
		 * ロード用ボタンの生成
		 * @private
		 */
		private function initPushButton():PushButton {
			pushButton = new PushButton(null, 0, 0, "LOAD", pushButtonHandler);
			pushButton.width = 60;
			return pushButton;
		}
		/**
		 * イベントハンドラ
		 * Model との通信手段
		 * PushButton のイベント
		 * 画像ロード step 1
		 * ファイル選択
		 * @private
		 */
		private var loadFileRef:FileReference;
		private function pushButtonHandler(event:Event):void {
			if (!sliderLayer.visible) sliderLayer.visible = true;
			resetSlider();	// スライダーの初期化
			// FileReference
			loadFileRef = new FileReference();
			loadFileRef.addEventListener(Event.SELECT, loadFileSelectedHandler);
			loadFileRef.browse();
		}
		/**
		 * 画像ロード step 2
		 * ファイル読込
		 * @private
		 */
		private function loadFileSelectedHandler(event:Event):void {
			loadFileRef.addEventListener(Event.COMPLETE, fileLoadCompleteHandler);
			loadFileRef.load();
		}
		/**
		 * 画像ロード step 3
		 * ファイル読込完了
		 * @private
		 */
		private var loader:Loader;
		private function fileLoadCompleteHandler(event:Event):void {
			loader = new Loader();
			loader.loadBytes(FileReference(event.target).data);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadedHandler);
		}
		/**
		 * 画像ロード step 4
		 * 読み込んだ画像の BitmapData を Model に送信
		 * @private
		 */
		private function imageLoadedHandler(event:Event):void {
			model.updateFromPushButton(Bitmap(loader.content).bitmapData);
		}
		
		/**
		 * スライダーのリセット
		 * @private
		 */
		private function resetSlider():void {
			slider.value = model.MAX_RENGE;
			changeLabel(slider.value);
		}
	}