개념잡기 :
BitmapData .getPixel (x:int , y:int ):uint
특정 지점(x, y)에서 BitmapData 객체의 RGB 픽셀 값을 나타내는 정수를 반환합니다.
BitmapData .clone ():BitmapData
원본 인스턴스를 내포된 비트맵까지 똑같이 복제한 새 BitmapData 객체를 반환합니다.
BitmapData.getPixel(x,y) 좌표값을 사용해서 파티클 효과를 만들어봤다.
한개의 이미지로 BitmapData.clone()을 사용하여 또 다른 이미지 처리를 할 수 있다는 것을 알아두자.
BitmapData를 사용하여 색상 변화를 표현할때 알게된 것 들이 있다.
1. BitmapData는 Bitmap이라는 디스플레이 객체에 존속된다.
2. 모체인 Bitmap에 색상 필터 효과를 적용하여도 getPixel()은 모체 내의 bitmapData에서 색을 추출한다.
3. 그러므로 색상 변화를 줄때 모체에 색상의 변화가 일어나도 getPixel()은 내부의 원색을 추출하게 된다.
4. 결론적으로 모체 내부의 bitmapData.applyFilter()에 색상을 적용하면 모체 효과 및 변화되는 색을 추출할 수 있다.
5. 모체에 BlendMode 를 사용하여 색상 효과를 적용하면 새로운 느낌을 만들 수 있다.
역시 코드를 다채롭게 변화를 주면서 효과를 넣어봐야 지식과 재미있는 아이디어들이 많이 떠오른다.
개넘 잡기 :
BitmapData .draw (source:IBitmapDrawable , matrix:Matrix = null, colorTransform:flash.geom:ColorTransform = null, blendMode:String = null, clipRect:Rectangle = null, smoothing:Boolean = false):void
: Flash 런타임 벡터 렌더러를 사용하여 비트맵 이미지에 source 표시 객체를 그립니다.
BitmapData .applyFilter (sourceBitmapData:BitmapData , sourceRect:Rectangle , destPoint:Point , filter:BitmapFilter ):void
: 소스 이미지와 filter 객체를 사용하여 필터링된 이미지를 생성합니다.
스테이지의 BitmapData를 생성한 후, Particle BitmapData 객체를 생성하여 반복적으로 좌표 값을 변경하여 BitmapData.draw를 적용하면 된다. BitmapData의 개념을 쉽게 익히기 위한 접근 방법으로 좋은 예라 생각된다.
적용된 코드는 아래와 같다.
package
{
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.events .MouseEvent ;
import flash.filters .BlurFilter ;
import flash.geom .Matrix ;
import flash.geom .Point ;
import flash.geom .Rectangle ;
import flash.utils .getDefinitionByName ;
import net.hires .debug .Stats ;
/**
* @author jin_u
* blog www.jinustudio.com/blog
* email jin_u@jinustudio.com
*/
public class ParticleMovement extends Sprite
{
private var clickBtn:Sprite;
private var btm:Bitmap;
private var btmData:BitmapData;
private var matrix:Matrix;
private var particles:Vector.< Particle> ;
private var maxParticle:int = 300 ;
private var blur:BlurFilter;
private var point:Point;
private var stageWidth:Number = 500 ;
private var stageHeight:Number = 300 ;
private var ratio:Number = 0.004 ;
private var friction:Number = 0.98 ;
public function ParticleMovement( )
{
stage .align = StageAlign.TOP_LEFT ;
stage .scaleMode = StageScaleMode.NO_SCALE ;
this .addEventListener ( Event.ADDED_TO_STAGE , this .onInit ) ;
}
private function onInit( e :Event = null ) :void
{
var ClassRef:Class = getDefinitionByName( "Click" ) as Class ;
this .clickBtn = new ClassRef( ) as Sprite;
this .clickBtn .x = Math .round ( this .stageWidth / 2 ) ;
this .clickBtn .y = Math .round ( this .stageHeight / 2 ) ;
this .addChild ( clickBtn) ;
stage .addEventListener ( MouseEvent.CLICK , this .onClickBtnClick ) ;
}
private function onClickBtnClick( e :MouseEvent = null ) :void
{
stage .removeEventListener ( MouseEvent.CLICK , this .onClickBtnClick ) ;
this .removeChild ( this .clickBtn ) ;
this .setContent ( ) ;
}
private function setContent( ) :void
{
this .particles = new Vector.< Particle> ;
this .matrix = new Matrix( ) ;
this .blur = new BlurFilter( 2 , 2 , 1 )
this .point = new Point( ) ;
this .createCanvas ( ) ;
this .addChild ( new Stats) ;
this .addEventListener ( Event.ENTER_FRAME , this .onStageEnterFrame ) ;
}
private function createCanvas( ) :void
{
this .btmData = new BitmapData( this .stageWidth , this .stageHeight ) ;
this .btm = new Bitmap( this .btmData ) ;
this .addChild ( this .btm ) ;
}
private function onStageEnterFrame( e :Event = null ) :void
{
var particle:Particle = new Particle( Math .random ( ) * 100000 + 1000000 ) ;
particle.x = Math .random ( ) * this .stageWidth ;
particle.y = Math .random ( ) * this .stageHeight ;
this .particles .push ( particle) ;
if ( this .particles .length > this .maxParticle - 1 ) this .particles .shift ( ) ;
this .btmData .applyFilter ( this .btmData , this .btmData .rect , this .point , this .blur ) ;
var index :int = 0 ;
var leng:int = this .particles .length ;
var i:int = 0 ;
for ( ; i < leng; i++)
{
particle = this .particles [ i] as Particle;
particle.mx = ( mouseX - particle.x ) * ratio + particle.mx * friction;
particle.x += particle.mx ;
particle.my = ( mouseY - particle.y ) * ratio + particle.my * friction;
particle.y += particle.my ;
this .matrix .tx = particle.x ;
this .matrix .ty = particle.y ;
this .btmData .draw ( particle, matrix) ;
}
}
}
}
import flash.display .BitmapData ;
class Particle extends BitmapData
{
internal var x:Number = 0 ;
internal var y:Number = 0 ;
internal var mx:Number = 0 ;
internal var my:Number = 0 ;
public function Particle( color :uint = 0 )
{
super ( 1 , 1 , false , color ) ;
}
}
원문 을 보면 알겠지만, 비트맵 데이터 처리에 대한 퍼포먼스를 향상시키는 방법이 존재한다. 기존의 중첩 반복(2중 for문)을 사용하는 것을 Vector Class를 사용하여 처리하고있는 것을 볼 수 있다. 요번 프로젝트에서도 참고해서 사용해 봐야 겠다.
Vector Class 는 한 타입형을 지원하는데 상당히 좋은것은 as3을 하는 사람이라면 아마도 알고 있을 것이다. 퍼포먼스가 상당히 월등하다. 제한적인 것들이 있지만 어디에 사용할 것인지를 판단하여 사용하면 좋다. 값을 넣고 빼고 할때도 잘 판단해야 한다.
아래에 픽셀처리에 대한 글이 있어 참고하면 좋을 듯 싶다.
setVector vs copyPixels
BitmapData, Vectors, ByteArrays and Optimization