forked from: 外部SWFアニメから画像の輪郭抽出してPixel表示
forked from 外部SWFアニメから画像の輪郭抽出してPixel表示 feat.chibitami (diff: 1)
ActionScript3 source code
/**
* Copyright hacker_9p8x8mco ( http://wonderfl.net/user/hacker_9p8x8mco )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/jU4B
*/
// forked from yooKo's 外部SWFアニメから画像の輪郭抽出してPixel表示
/**
* 1.外部SWFから輪郭を取得する。
* 2.Papervision3DのPixcel3Dで描画
*
* @author yooKo@serialField
* @version 0.1
* Let's Click!
* Click毎に3段階表示が切り替わる
*
* ↓の画像をお借りしました
* http://zeloma.com/article/92211940.html
*
* なんか動きしょぼいなー・・・
*
**/
package {
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.StageQuality;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.net.URLRequest;
import flash.system.LoaderContext;
//import flash.system.SecurityDomain;
import flash.system.Security;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import org.papervision3d.core.effects.BitmapLayerEffect;
import org.papervision3d.core.effects.BitmapColorEffect;
import org.papervision3d.core.effects.utils.BitmapClearMode;
import org.papervision3d.core.geom.Pixels;
import org.papervision3d.core.geom.renderables.Pixel3D;
import org.papervision3d.view.BasicView;
import org.papervision3d.view.layer.BitmapEffectLayer;
import net.hires.debug.Stats;
[SWF(width="465", height="465", backgroundColor="0x000000", frameRate="40")]
public class Pixcel3DAnime extends BasicView {
private var _loader:Loader;
private var _pixels:Pixels;
private var _rotateX:Number = 0;
private var _rotateY:Number = 0;
private var _currentNum:int = 0;
private var _bmd:BitmapData;
private var _pre:Number;
private var _a:Number;
private var _y:Number;
private var _x:Number;
private var _c:uint;
private const CAMERA_DISTANCE:int = -150;
private const IMAGE_URL:String = "http://selflash.jp/wonderfl/miku.swf";
// ソース画像のどの部分を解析するか
private const TRIMMING_WIDTH:int = 80;
private const TRIMMING_HEIGHT:int = 50;
private const SIZE_WIDHT:int = 220;
private const SIZE_HEIGHT:int = 163;
// 中央に持ってくる為に使う
private const W:Number = TRIMMING_WIDTH + SIZE_WIDHT * .5;
private const H:Number = TRIMMING_HEIGHT + SIZE_HEIGHT * .5;
//========================================================================
// コンストラクタ
//========================================================================
public function Pixcel3DAnime() {
super(0, 0, true, true);
StageQuality.LOW;
/**
*crossdomainにやらSecurity.allowDomain()やらまだまだ理解が浅くてわかんなかった、、
* 読み込む事はできるがdraw()ができなくて悩んだ。
* 結局呼び出す子swfの1フレーム目にSecurity.allowDomain("*")と記述した事でおk。
* ※Security.allowDomain("http://www.selflash.jp/")ではダメだった・・この辺はなんでか分かんない
* http://cocoasaurus.com/blog/2009/09/as3allowdomain-1.html
* ↑のリンク先の情報によると読み込む方と読み込まれる方の両方に Security.allowDomain() を記述しないといけないらしいが
* ↓はコメントアウトしても draw() 出来てる。これもなぜだかわかんない、、、
*/
//Security.allowDomain("*");
if (!stage)
addEventListener(Event.ADDED_TO_STAGE, init);
else
init();
}
//========================================================================
// 画像の読み込み
//========================================================================
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
_loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
_loader.load(new URLRequest(IMAGE_URL), new LoaderContext(true));
}
//========================================================================
// ロード完了後の処理
//========================================================================
private function onCompleteHandler(e:Event):void {
e.target.removeEventListener(Event.COMPLETE, init);
//こいつから色、座標を解析
_bmd = new BitmapData(_loader.width, _loader.height, true, 0xFFFFFF);
//左下に表示するためのやつね
var bmp:Bitmap = new Bitmap(_bmd, "auto", true);
bmp.scaleX = .4;
bmp.scaleY = .4;
bmp.y = stage.stageHeight - bmp.height;
addChild(bmp);
camera.z = CAMERA_DISTANCE;
var _layer:BitmapEffectLayer = new BitmapEffectLayer(viewport, stage.stageWidth, stage.stageHeight, true, 0, BitmapClearMode.CLEAR_PRE, false);
viewport.containerSprite.addLayer(_layer);
_layer.addEffect(new BitmapColorEffect(1.2, 1.2, 1.2, .7));
//_layer.addEffect(new BitmapLayerEffect(new BlurFilter(16, 16, 1), false));
_pixels = new Pixels(_layer);
scene.addChild(_pixels);
addEventListener(Event.ENTER_FRAME, upDate);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDownHandler);
startRendering();
addChild(new Stats());
}
//========================================================================
// 表示の切り替え
// 切り替えの仕組みがしょぼすぎる・・・なんか挙動が変、、スマートな方法あったら教えてください、、
//========================================================================
private function onDownHandler(e:MouseEvent = null):void {
_currentNum++;
if (_currentNum > 4) {
_currentNum = 0;
}
//_currentNum = (_currentNum < 4) ? _currentNum += 1 : 0;
}
//========================================================================
// 常に行う処理
//========================================================================
private function upDate(e:Event):void {
_rotateX += (- viewport.containerSprite.mouseX - _rotateX) * 0.1;
_rotateY += (- viewport.containerSprite.mouseY - 170 - _rotateY) * 0.1;
_pixels.rotationY = _rotateX;
_pixels.rotationX = _rotateY;
//毎回drawさせるよん
_bmd.draw(_loader);
//毎回消すよん
_pixels.removeAllpixels();
//表示の切り替え
switch (_currentNum) {
case 0:
createBody(0, 2);
break;
case 1:
//createBody(-16, 2);
//createFrame(-20, 3, 0xFFFF0066);
//createFrame(-16, 3, 0xFFFF0066);
createBody(-8, 4, 0xFFFF0066);
createFrame(-6, 4, 0xFFFF0066);
createFrame(-4, 4, 0xFFFF0066);
createFrame(-2, 4, 0xFFFF0066);
//createFrame(0, 4, 0xFFFF0066);
//createFrame(1, 4, 0xFFFF0066);
//createFrame(2, 4, 0xFFFF0066);
//createFrame(3, 4, 0xFFFF0066);
createFrame(0, 4, 0xFFFF0066);
//createFrame(5, 4, 0xFFFF0066);
createFrame(2, 4, 0xFFFF0066);
//createFrame(7, 4, 0xFFFF0066);
createFrame(4, 4, 0xFFFF0066);
createFrame(6, 4, 0xFFFF0066);
createBody(8, 4, 0xFFFF0066);
//createFrame(4, 3, 0xFFFF0066);
//createFrame(8, 3, 0xFFFF0066);
//createBody(16, 2);
break;
case 2:
createBody(0, 2, 0xFFCCFF00);
break;
case 3:
createFrame(0, 2, 0xFFCCFF99);
break;
//default :
//createBody(0, 2);
};
}
//========================================================================
// 中身を作成するメソッド
// 呼び出されたら白以外全部解析する
// ※ 引数に色の指定がなければ抽出した色を使う
//========================================================================
private function createBody(depth:Number = 0, distance:Number = 2, color:Number = NaN):void {
for ( _y = TRIMMING_HEIGHT; _y < TRIMMING_HEIGHT + SIZE_HEIGHT; _y += distance ) {
for ( _x = TRIMMING_WIDTH; _x < TRIMMING_WIDTH + SIZE_WIDHT; _x += distance ) {
_c = _bmd.getPixel( _x, _y );
if (_c != 0xFFFFFF) {
_c = (color)?color:rgb2argb(_c, 1);
_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
}
}
}
}
//========================================================================
// 枠組みを作成するメソッド
// 呼び出されたらキャラクターの外枠だけ解析する
// ※ 引数に色の指定がなければ抽出した色を使う
//========================================================================
private function createFrame(depth:Number = -4, distance:Number = 2, color:Number = NaN):void {
for ( _y = TRIMMING_HEIGHT; _y < TRIMMING_HEIGHT + SIZE_HEIGHT; _y += distance ) {
for ( _x = TRIMMING_WIDTH; _x < TRIMMING_WIDTH + SIZE_WIDHT; _x += distance ) {
_c = _bmd.getPixel( _x, _y );
if (_c != 0xFFFFFF) {
_a = (_y == 0)?0:_x - W - _pre;
if (_a > distance || _a < - distance) {
_c = (color)?color:rgb2argb(_c, 1);
_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
}
_pre = _x - W;
}
}
}
for ( _x = TRIMMING_WIDTH; _x < TRIMMING_WIDTH + SIZE_WIDHT; _x += distance ) {
for ( _y = TRIMMING_HEIGHT; _y < TRIMMING_HEIGHT + SIZE_HEIGHT; _y += distance ) {
_c = _bmd.getPixel( _x, _y );
if (_c != 0xFFFFFF) {
_a = (_x == 0)?0:_y - H - _pre;
if(_a > distance || _a < - distance) {
_c = (color)?color:rgb2argb(_c, 1);
_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
}
_pre = _y - H;
}
}
}
for ( _y = TRIMMING_HEIGHT + SIZE_HEIGHT; _y > TRIMMING_HEIGHT; _y -= distance ) {
for ( _x = TRIMMING_WIDTH + SIZE_WIDHT; _x > TRIMMING_WIDTH; _x -= distance ) {
_c = _bmd.getPixel( _x, _y );
if (_c != 0xFFFFFF) {
_a = (_y == TRIMMING_HEIGHT + SIZE_HEIGHT)?0:_x - W - _pre;
if(_a > distance || _a < - distance) {
_c = (color)?color:rgb2argb(_c, 1);
_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
}
_pre = _x - W;
}
}
}
for ( _x = TRIMMING_WIDTH + SIZE_WIDHT; _x > TRIMMING_WIDTH; _x -= distance ) {
for ( _y = TRIMMING_HEIGHT + SIZE_HEIGHT; _y > TRIMMING_HEIGHT; _y -= distance ) {
_c = _bmd.getPixel( _x, _y );
if (_c != 0xFFFFFF) {
_a = (_x == TRIMMING_WIDTH + SIZE_WIDHT)?0:_y - H - _pre;
if(_a > distance || _a < - distance) {
_c = (color)?color:rgb2argb(_c, 1);
_pixels.addPixel3D(new Pixel3D(_c, _x - W, _y - H, depth));
}
_pre = _y - H;
}
}
}
}
//========================================================================
// RGBをARGBに変換する
//========================================================================
private function rgb2argb(rgb:uint, alpha:Number):uint {
return ((alpha * 0xff) << 24) + rgb;
}
}
}
