필터 작성 및 적용

Flash Player 9 이상, Adobe AIR 1.0 이상

필터를 사용하면 비트맵 및 표시 객체에 그림자, 경사 및 흐림 효과 등 다양한 효과를 적용할 수 있습니다. 각 필터는 클래스로 정의되므로 필터를 적용하면 필터 객체의 인스턴스가 기타 다른 객체가 생성되는 것과 마찬가지 방식으로 만들어집니다. 일단 필터 객체를 만든 후에는 해당 필터를 객체의 filters 속성이나, BitmapData 객체의 경우 applyFilter() 메서드를 사용하여 간단하게 표시 객체에 적용할 수 있습니다.

필터 만들기

필터 객체를 만들려면 선택한 필터 클래스의 생성자 메서드를 호출하면 됩니다. 예를 들어 DropShadowFilter 객체를 만들려면 다음 코드를 사용하십시오.

import flash.filters.DropShadowFilter; 
var myFilter:DropShadowFilter = new DropShadowFilter();

여기에 표시되어 있지는 않지만 모든 필터 클래스 생성자 등의 DropShadowFilter() 생성자는 필터 효과 모양 사용자 정의에 사용할 수 있는 여러 선택적 매개 변수를 사용합니다.

필터 적용

생성한 필터 객체는 표시 객체 또는 BitmapData 객체에 적용할 수 있습니다. 필터 적용 방법은 필터를 적용하는 객체에 따라 달라집니다.

표시 객체에 필터 적용

표시 객체에 필터 효과를 적용하는 경우에는 filters 속성을 통해 적용합니다. 표시 객체의 filters 속성은 Array 인스턴스이며, 그 요소는 표시 객체에 적용된 필터 객체입니다. 표시 객체에 단일 필터를 적용하려면 다음과 같이 필터 인스턴스를 만들고 이를 Array 인스턴스에 추가한 다음 표시 객체의 filters 속성에 Array 객체를 지정합니다.

import flash.display.Bitmap; 
import flash.display.BitmapData; 
import flash.filters.DropShadowFilter; 
 
// Create a bitmapData object and render it to screen 
var myBitmapData:BitmapData = new BitmapData(100,100,false,0xFFFF3300); 
var myDisplayObject:Bitmap = new Bitmap(myBitmapData); 
addChild(myDisplayObject); 
 
// Create a DropShadowFilter instance. 
var dropShadow:DropShadowFilter = new DropShadowFilter(); 
 
// Create the filters array, adding the filter to the array by passing it as  
// a parameter to the Array() constructor. 
var filtersArray:Array = new Array(dropShadow); 
 
// Assign the filters array to the display object to apply the filter. 
myDisplayObject.filters = filtersArray;

객체에 여러 필터를 지정하려면 filters 속성에 Array 인스턴스를 지정하기 전에 먼저 모든 필터를 해당 인스턴스에 추가합니다. Array 생성자에 여러 객체를 매개 변수로 전달하면 해당 객체를 Array에 추가할 수 있습니다. 예를 들어 다음 코드는 이전에 만든 표시 객체에 경사 필터 및 광선 필터를 적용합니다.

import flash.filters.BevelFilter; 
import flash.filters.GlowFilter; 
 
// Create the filters and add them to an array. 
var bevel:BevelFilter = new BevelFilter(); 
var glow:GlowFilter = new GlowFilter(); 
var filtersArray:Array = new Array(bevel, glow); 
 
// Assign the filters array to the display object to apply the filter. 
myDisplayObject.filters = filtersArray;

필터를 포함하는 배열을 만드는 경우에는 이전 예제와 같이 new Array() 생성자를 사용하여 만들거나 Array 리터럴 구문을 사용하여 해당 필터를 대괄호( [] )로 묶습니다. 다음 코드 행을 예로 들어 보겠습니다.

var filters:Array = new Array(dropShadow, blur); 

위 코드 행은 아래 코드 행과 동일한 작업을 수행합니다.

var filters:Array = [dropShadow, blur];

표시 객체에 여러 개의 필터를 적용할 경우 필터는 누적형의 순차적인 방식으로 적용됩니다. 예를 들어 두 개의 요소가 있는 필터 배열의 경우 먼저 경사 필터 그 다음으로 그림자 필터가 추가되며, 그림자 필터는 경사 필터와 표시 객체 모두에 적용됩니다. 그 이유는 그림자 필터가 필터 배열에서 두 번째 위치에 있기 때문입니다. 비 누적 방식으로 필터를 적용하려면 표시 객체의 새 복사본에 각각의 필터를 적용해야 합니다.

표시 객체에 한 개 또는 소수의 필터만 지정하려는 경우 필터 인스턴스를 만든 다음 단일 명령문을 사용하여 객체에 해당 인스턴스를 지정할 수 있습니다. 예를 들어 다음 코드 행은 흐림 필터를 myDisplayObject 라는 표시 객체에 적용합니다.

myDisplayObject.filters = [new BlurFilter()];

이전 코드는 Array 리터럴 구문(각괄호)을 사용하여 Array 인스턴스를 만들고 Array의 요소로 BlurFilter 인스턴스를 만든 다음 해당 Array를 myDisplayObject 라는 표시 객체의 filters 속성에 지정합니다.

표시 객체에서 필터 제거

표시 객체에서 모든 필터를 제거하려면 다음과 같이 단순히 filters 속성에 null 값을 지정하면 됩니다.

myDisplayObject.filters = null;

객체에 여러 객체를 적용한 경우 하나의 필터만 제거하려면 여러 단계를 거쳐 filters 속성 배열을 변경해야 합니다. 자세한 내용은 필터 작업의 잠재적 문제점 을 참조하십시오.

BitmapData 객체에 필터 적용

BitmapData 객체에 필터를 적용하려면 BitmapData 객체의 applyFilter() 메서드를 사용해야 합니다.

var rect:Rectangle = new Rectangle(); 
var origin:Point = new Point(); 
myBitmapData.applyFilter(sourceBitmapData, rect, origin, new BlurFilter());

applyFilter() 메서드는 필터를 BitmapData 객체에 적용하여 필터링된 새 이미지를 생성합니다. 이 메서드는 원본 소스 이미지를 수정하지 않는 대신 소스 이미지에 적용된 필터 결과가 applyFilter() 메서드를 호출하는 BitmapData 인스턴스에 저장됩니다.

필터 작동 방법

표시 객체 필터링은 원본 객체의 복사본을 투명 비트맵으로 캐싱하는 방식으로 작동됩니다.

표시 객체에 필터를 적용한 후에는 런타임에서 해당 객체에 유효한 필터 목록이 있는 한 해당 객체를 비트맵으로 캐시합니다. 이 소스 비트맵은 이후에 적용되는 모든 필터 효과의 원본 이미지로 사용됩니다.

일반적으로 각 표시 객체에는 두 개의 비트맵이 포함되어 있는데, 한 개는 필터링되지 않은 원본 소스 표시 객체에 대한 비트맵이고 다른 한 개는 필터링 이후의 최종 이미지에 대한 비트맵입니다. 최종 이미지는 렌더링 시 사용됩니다. 표시 객체가 변경되지 않으면 업데이트할 필요가 없습니다.

필터 작업의 잠재적 문제점

필터를 사용하여 작업할 경우 혼동하거나 문제가 발생되지 않도록 유념해야 할 몇 가지 사항이 있습니다.

필터 및 비트맵 캐싱

표시 객체에 필터를 적용하기 위해서는 해당 객체에 대한 비트맵 캐싱이 활성화되어야 합니다. cacheAsBitmap 속성이 false 로 설정된 표시 객체에 필터를 적용하는 경우 해당 객체의 cacheAsBitmap 속성은 자동으로 true 로 설정됩니다. 나중에 표시 객체에서 모든 필터를 제거하면 cacheAsBitmap 속성이 마지막으로 설정된 값으로 다시 설정됩니다.

런타임에 필터 변경

표시 객체에 이미 하나 이상의 필터가 적용된 경우에는 filters 속성 배열에 다른 필터를 추가하거나 제거하여 필터 세트를 변경할 수 없습니다. 대신 적용되는 필터 세트에 추가하거나 변경하려면 개별 배열을 변경한 다음 객체에 적용할 필터에 대한 표시 객체의 필터 속성에 해당 배열을 할당합니다. 이 작업을 수행하는 가장 간단한 방법은 filters 속성 배열을 Array 변수로 읽어온 다음 이 임시 배열을 수정하는 것입니다. 표시 객체의 filters 속성에 이 배열을 다시 할당합니다. 보다 복잡한 경우 별도의 마스터 필터 배열을 유지해야 할 수도 있습니다. 마스터 필터 배열을 변경한 다음 각 변경 후에 표시 객체의 filters 속성에 마스터 배열을 다시 할당합니다.

다른 필터 추가

다음 코드에서는 한 개 이상의 필터가 이미 적용되어 있는 표시 객체에 다른 필터를 추가하는 프로세스를 보여 줍니다. 처음에는 광선 필터가 myDisplayObject 라는 표시 객체에 적용되고 나중에 해당 표시 객체를 클릭하면 addFilters() 함수가 호출됩니다. 이 함수에서 다음과 같이 두 개의 추가 필터가 myDisplayObject 에 적용됩니다.

import flash.events.MouseEvent; 
import flash.filters.*; 
 
myDisplayObject.filters = [new GlowFilter()]; 
 
function addFilters(event:MouseEvent):void 
{ 
    // Make a copy of the filters array. 
    var filtersCopy:Array = myDisplayObject.filters; 
 
    // Make desired changes to the filters (in this case, adding filters). 
    filtersCopy.push(new BlurFilter()); 
    filtersCopy.push(new DropShadowFilter()); 
 
    // Apply the changes by reassigning the array to the filters property. 
    myDisplayObject.filters = filtersCopy; 
} 
 
myDisplayObject.addEventListener(MouseEvent.CLICK, addFilters);

필터 세트에서 필터 한 개 제거

표시 객체에 여러 개의 필터가 적용되어 있고 다른 필터는 계속 객체에 적용하는 동시에 필터 중 한 개를 제거하려면 임시 배열에 필터를 복사하고 해당 배열에서 불필요한 필터를 제거한 다음 표시 객체의 filters 속성에 임시 배열을 다시 할당합니다. 임의 배열에서 요소를 한 개 이상 제거하는 여러 가지 방법은 값 가져오기 및 배열 요소 제거 에 설명되어 있습니다.

가장 간단한 경우는 객체의 맨 위에 있는 필터(객체에 마지막으로 적용된 필터)를 제거하는 것입니다. Array 클래스의 pop() 메서드를 사용하여 배열에서 필터를 제거합니다.

// Example of removing the top-most filter from a display object  
// named "filteredObject". 
 
var tempFilters:Array = filteredObject.filters; 
 
// Remove the last element from the Array (the top-most filter). 
tempFilters.pop(); 
 
// Apply the new set of filters to the display object. 
filteredObject.filters = tempFilters;

마찬가지로, 맨 아래에 있는 필터(객체에 적용된 첫 번째 필터)를 제거하려면 동일한 코드를 사용하고 Array 클래스의 shift() 메서드로 pop() 메서드를 대체합니다.

필터 배열의 가운데에서 필터를 제거하려면(배열에 필터가 세 개 이상 있다고 가정) splice() 메서드를 사용할 수 있습니다. 제거할 필터의 인덱스(배열에서의 위치)를 알고 있어야 합니다. 예를 들어, 다음 코드는 표시 객체에서 두 번째 필터(인덱스 1의 필터)를 제거합니다.

// Example of removing a filter from the middle of a stack of filters 
// applied to a display object named "filteredObject". 
 
var tempFilters:Array = filteredObject.filters; 
 
// Remove the second filter from the array. It's the item at index 1  
// because Array indexes start from 0. 
// The first "1" indicates the index of the filter to remove; the  
// second "1" indicates how many elements to remove. 
tempFilters.splice(1, 1); 
 
// Apply the new set of filters to the display object. 
filteredObject.filters = tempFilters;

필터의 인덱스 확인

필터의 인덱스를 확인하려면 배열에서 제거할 필터를 알고 있어야 합니다. 응용 프로그램의 디자인 방법에 의해 제거할 필터의 인덱스를 알고 있거나 계산해야 합니다.

제거할 필터가 항상 필터 세트의 동일한 위치에 있도록 응용 프로그램을 디자인하는 것이 좋습니다. 예를 들어 회선 필터와 그림자 필터가 이 순서대로 적용되어 있는 단일 표시 객체가 있고 그림자 필터만 제거하고 회선 필터를 유지하려는 경우 필터가 알려진 위치(맨 위 필터)에 있기 때문에 사용할 Array 메서드(이 경우 그림자 필터를 제거하기 위해 Array.pop() 사용)를 미리 알 수 있습니다.

제거할 필터가 항상 특정 유형이지만 필터 세트에서 항상 동일한 위치에 있는 것이 아니면 배열에서 각 필터의 데이터 유형을 검사하여 제거할 필터를 확인할 수 있습니다. 예를 들어, 다음 코드는 필터 세트 중 광선 필터인 필터를 확인하고 해당 필터를 세트에서 제거합니다.

// Example of removing a glow filter from a set of filters, where the 
//filter you want to remove is the only GlowFilter instance applied  
// to the filtered object. 
 
var tempFilters:Array = filteredObject.filters; 
 
// Loop through the filters to find the index of the GlowFilter instance. 
var glowIndex:int; 
var numFilters:int = tempFilters.length; 
for (var i:int = 0; i < numFilters; i++) 
{ 
    if (tempFilters[i] is GlowFilter) 
    { 
        glowIndex = i; 
        break; 
    } 
} 
 
// Remove the glow filter from the array. 
tempFilters.splice(glowIndex, 1); 
 
// Apply the new set of filters to the display object. 
filteredObject.filters = tempFilters;

제거할 필터가 런타임에 선택되는 경우처럼 보다 복잡한 경우에서는 마스터 필터 목록으로 동작하는 별도의 필터 배열 영구 복사본을 유지하는 것이 좋습니다. 언제든지 필터 세트를 변경하고 마스터 목록을 변경한 다음 해당 필터 배열을 표시 객체의 filters 속성으로 적용할 수 있습니다.

예를 들어, 다음 코드 샘플에서는 여러 개의 회선 필터가 표시 객체에 적용되어 다양한 시각적 효과를 만든 다음, 응용 프로그램의 이후 지점에서 이러한 필터 중 한 개가 제거되고 다른 필터는 유지됩니다. 이 경우 코드는 제거할 필터에 대한 참조는 물론 필터 배열의 마스터 복사본을 유지합니다. 특정 필터를 찾아서 제거하는 방법은 필터 배열의 임시 복사본을 만드는 대신 마스터 복사본을 조작한 다음 표시 객체에 적용한다는 점을 제외하고 이전 방법과 유사합니다.

// Example of removing a filter from a set of  
// filters, where there may be more than one  
// of that type of filter applied to the filtered  
// object, and you only want to remove one. 
 
// A master list of filters is stored in a separate, 
// persistent Array variable. 
var masterFilterList:Array; 
 
// At some point, you store a reference to the filter you 
// want to remove. 
var filterToRemove:ConvolutionFilter; 
 
// ... assume the filters have been added to masterFilterList, 
// which is then assigned as the filteredObject.filters: 
filteredObject.filters = masterFilterList; 
 
// ... later, when it's time to remove the filter, this code gets called: 
 
// Loop through the filters to find the index of masterFilterList. 
var removeIndex:int = -1; 
var numFilters:int = masterFilterList.length; 
for (var i:int = 0; i < numFilters; i++) 
{ 
    if (masterFilterList[i] == filterToRemove) 
    { 
        removeIndex = i; 
        break; 
    } 
} 
 
if (removeIndex >= 0) 
{ 
    // Remove the filter from the array. 
    masterFilterList.splice(removeIndex, 1); 
 
    // Apply the new set of filters to the display object. 
    filteredObject.filters = masterFilterList; 
}

이 방법에서 필터 배열의 항목에 대해 저장된 필터 참조를 비교하여 제거할 필터를 확인하는 경우 반드시 별도의 필터 배열 복사본을 유지해야 합니다. 표시 객체의 filters 속성에서 복사된 임시 배열의 요소에 대해 저장된 필터 참조를 비교하는 경우에는 코드가 작동하지 않습니다. 이것은 filters 속성에 배열을 할당할 때 런타임에서 내부적으로 배열에 있는 각 필터 객체의 복사본이 만들어지기 때문입니다. 원본 객체 대신 이러한 복사본이 표시 객체에 적용되며, filters 속성을 임시 배열로 읽어올 때 원본 필터 객체에 대한 참조가 아니라 복사한 필터 객체에 대한 참조가 임시 배열에 포함됩니다. 따라서 앞의 예제에서 임시 필터 배열의 필터와 비교하여 filterToRemove 의 인덱스를 확인하려고 하면 일치 항목이 없습니다.

필터 및 객체 변형

표시 객체의 경계 상자 사각형 외부의 필터링되지 않은 영역(예: 그림자)은 인스턴스가 다른 인스턴스와 겹치거나 교차하는지 여부를 판단하는 히트 감지를 목적으로 하는 표면의 일부로 간주됩니다. DisplayObject 클래스의 히트 감지 메서드는 벡터에 기반을 두기 때문에 비트맵 결과에 대해서는 히트 감지를 수행할 수 없습니다. 예를 들어, 버튼 인스턴스에 경사 필터를 적용하는 경우 경사가 적용된 인스턴스 부분에 대해서는 히트 감지를 사용할 수 없습니다.

필터에서는 크기 조절, 회전 및 기울이기를 지원하지 않습니다. 필터링된 표시 객체 자체의 크기가 조절되는 경우( scaleX scaleY 가 100%가 아닌 경우)에는 인스턴스에 필터 효과가 적용될 때 크기가 조절되지 않습니다. 다시 말해서 인스턴스의 원래 모양에만 회전, 크기 조절 또는 기울이기가 수행되며, 필터가 적용된 인스턴스에는 회전, 크기 조절 또는 기울이기가 수행되지 않습니다.

실제 효과 또는 중첩 인스턴스를 만드는 필터를 사용하여 인스턴스에 애니메이션을 적용하고 BitmapData 클래스를 사용하여 이 효과를 나타내도록 필터에 애니메이션을 적용할 수 있습니다.

필터 및 비트맵 객체

BitmapData 객체에 필터를 적용하면 cacheAsBitmap 속성이 자동으로 true 로 설정됩니다. 실제로는 이런 방식을 사용하여 필터가 원본이 아닌 객체의 복사본에 적용됩니다.

그런 다음 이 복사본은 가장 가까운 픽셀과 최대한 가깝게 기본 디스플레이의 원본 객체 위에 배치됩니다. 원본 비트맵 경계가 변경되면 필터링된 비트맵 복사본은 확장되거나 왜곡되지 않고 원본에서 다시 만들어집니다.

표시 객체의 모든 필터를 지우면 cacheAsBitmap 속성이 필터 적용 이전 상태로 재설정됩니다.