Exempel på filtrering av visningsobjekt: Filter Workbench

Flash Player 9 och senare, Adobe AIR 1.0 och senare

I Filter Workbench finns ett användargränssnitt som du kan använda för att tillämpa olika filter på bilder och annat visuellt innehåll och se den kod som kan användas för att skapa samma effekt med ActionScript. Förutom ett verktyg för experimentering med filter, demonstrerar det här programmet följande tekniker:

  • Skapa instanser av olika filter

  • Tillämpa flera filter på ett visningsobjekt

Programfilerna för det här exemplet finns på www.adobe.com/go/learn_programmingAS3samples_flash_se. Programfilerna för Filter Workbench finns i mappen Samples/FilterWorkbench. Programmet består av följande filer:

Fil

Beskrivning

com/example/programmingas3/filterWorkbench/FilterWorkbenchController.as

Den klass som innehåller programmets huvudsakliga funktionalitet, inklusive växling av vilket innehåll filter tillämpas på och tillämpning av filter på innehåll.

com/example/programmingas3/filterWorkbench/IFilterFactory.as

Ett gränssnitt som definierar vanliga metoder som implementeras av var och en av filterfabriksklasserna. I gränssnittet definieras de funktioner som används i klassen FilterWorkbenchController för att interagera med de enskilda filterfabriksklasserna.

i mappen com/example/programmingas3/filterWorkbench/:

BevelFactory.as

BlurFactory.as

ColorMatrixFactory.as

ConvolutionFactory.as

DropShadowFactory.as

GlowFactory.as

GradientBevelFactory.as

GradientGlowFactory.as

En uppsättning klasser, som var och en implementerar gränssnittet IFilterFactory. Var och en av dessa klasser innehåller funktionaliteten för att skapa och ställa in värden för en viss typ av filter. På filteregenskapspanelerna i programmet används dessa fabriksklasser för att skapa instanser av motsvarande filter. Instanserna hämtas av klassen FilterWorkbenchController och tillämpas på bildinnehållet.

com/example/programmingas3/filterWorkbench/IFilterPanel.as

Gränssnitt som definierar vanliga metoder för implementering av klasser som definierar användargränssnittspanelerna som används för att ändra filtervärden i programmet.

com/example/programmingas3/filterWorkbench/ColorStringFormatter.as

En verktygsklass som innehåller en metod som konverterar ett numeriskt färgvärde till ett hexadecimalt String-format

com/example/programmingas3/filterWorkbench/GradientColor.as

En klass som fungerar som ett värdeobjekt och kombinerar de tre värdena (color, alpha och ratio) som tillhör varje färg i GradientBevelFilter och GradientGlowFilter till ett enda objekt

Användargränssnitt (Flex)

FilterWorkbench.mxml

Huvudfilen som definierar användargränssnittet för programmet.

flexapp/FilterWorkbench.as

En klass som innehåller funktionaliteten för huvudprogrammets användargränssnitt. Klassen används som klass med bakomliggande kod för MXML-programfilen.

I mappen flexapp/filterPanels:

BevelPanel.mxml

BlurPanel.mxml

ColorMatrixPanel.mxml

ConvolutionPanel.mxml

DropShadowPanel.mxml

GlowPanel.mxml

GradientBevelPanel.mxml

GradientGlowPanel.mxml

En uppsättning MXML-komponenter som innehåller funktionaliteten för varje panel som används för att ställa in alternativ för ett enda filter.

flexapp/ImageContainer.as

Ett visningsobjekt som fungerar som behållare för den inlästa bilden på skärmen

flexapp/controls/BGColorCellRenderer.as

Anpassad cellrenderare som används för att ändra bakgrundsfärg för en cell i komponenten DataGrid

flexapp/controls/QualityComboBox.as

Anpassad kontroll som definierar en kombinationsruta som kan användas för kvalitetsinställningen på olika filterpaneler.

flexapp/controls/TypeComboBox.as

Anpassad kontroll som definierar en kombinationsruta som kan användas för typinställningen på olika filterpaneler.

Användargränssnitt (Flash)

FilterWorkbench.fla

Huvudfilen som definierar användargränssnittet för programmet.

flashapp/FilterWorkbench.as

En klass som innehåller funktionaliteten för huvudprogrammets användargränssnitt. Klassen används som dokumentklass för FLA-programfilen.

I mappen flashapp/filterPanels:

BevelPanel.as

BlurPanel.as

ColorMatrixPanel.as

ConvolutionPanel.as

DropShadowPanel.as

GlowPanel.as

GradientBevelPanel.as

GradientGlowPanel.as

En uppsättning klasser som innehåller funktionaliteten för varje panel som används för att ställa in alternativ för ett enda filter.

För varje klass finns också en associerad MovieClip-symbol i biblioteket i FLA-huvudfilen. Symbolens namn är samma som klassens (symbolen BlurPanel är till exempel kopplad till klassen som definieras i BlurPanel.as). Komponenterna som utgör användargränssnittet placeras och namnges i dessa symboler.

flashapp/ImageContainer.as

Ett visningsobjekt som fungerar som behållare för den inlästa bilden på skärmen

flashapp/BGColorCellRenderer.as

Anpassad cellrenderare som används för att ändra bakgrundsfärg för en cell i komponenten DataGrid

flashapp/ButtonCellRenderer.as

En anpassad cellrenderare som används för att inkludera en knappkomponent i en cell i komponenten DataGrid

Filtrerat bildinnehåll

com/example/programmingas3/filterWorkbench/ImageType.as

Den här klassen fungerar som ett värdeobjekt som innehåller typ och URL för en enda bildfil som programmet kan läsa in och tillämpa filter på. Klassen innehåller också en uppsättning konstanter som representerar de faktiska bildfilerna.

images/sampleAnimation.swf,

images/sampleImage1.jpg,

images/sampleImage2.jpg

Bilder och annat visuellt innehåll som filtren tillämpas på i programmet.

Experimentera med ActionScript-filter

Programmet Filter Workbench är utformat för att hjälpa dig att experimentera med olika filtereffekter och generera relevant ActionScript-kod för den effekten. Programmet gör att du kan välja på tre olika filer med visuellt innehåll, inklusive bitmappsbilder och en animering som har skapats i Flash, och tillämpa åtta olika ActionScript-filter på den valda bilden, antingen var för sig eller i kombination med andra filter. Programmet innehåller följande filter:

  • Avfasning (flash.filters.BevelFilter)

  • Oskärpa (flash.filters.BlurFilter)

  • Färgmatris (flash.filters.ColorMatrixFilter)

  • Faltning (flash.filters.ConvolutionFilter)

  • Skugga (flash.filters.DropShadowFilter)

  • Glöd (flash.filters.GlowFilter)

  • Övertonad avfasning (flash.filters.GradientBevelFilter)

  • Övertonad glöd (flash.filters.GradientGlowFilter)

När en användare har valt en bild och ett filter att tillämpa på den bilden visar programmet en panel med kontroller med vilka användaren kan ställa in det valda filtrets egenskaper. I följande bild visas programmet med avfasningsfiltret valt:

När användaren ändrar filteregenskaperna uppdateras förhandsvisningen i realtid. Användaren kan också tillämpa flera filter genom att anpassa ett filter, klicka på Tillämpa, anpassa ett filter till, klicka på Tillämpa igen, o.s.v.

Det finns några funktioner och begränsningar på programmets filterpaneler:

  • Färgmatrisfiltret innehåller en uppsättning kontroller som direkt styr bildegenskaper som intensitet, kontraster, mättnad och nyans. Dessutom går det att ange anpassade färgmatrisvärden.

  • Faltningsfiltret, som bara finns om ActionScript används, innehåller en uppsättning vanliga faltningsmatrisvärden. Det går också att ange egna värden. Till skillnad från klassen ConvolutionFilter, där en matris av valfri storlek kan användas, används en fast 3 x 3-matris i Filter Workbench eftersom det är den vanligaste filterstorleken.

  • Förskjutningsfiltret och skuggningsfiltret, som bara finns i ActionScript, finns inte i Filter Workbench.

Skapa filterinstanser

I Filter Workbench finns en uppsättning klasser, en för varje tillgängligt filter. Klasserna används på de olika panelerna för att skapa filtren. När en användare väljer ett filter skapas en instans av filterfabriksklassen av den ActionScript-kod som är kopplad till den filterpanelen. (Klasserna kallas fabriksklasser eftersom deras syfte är att skapa instanser av andra objekt, på ungefär samma sätt som en fabrik skapar enskilda produkter.)

Varje gång en användare ändrar ett egenskapsvärde på panelen anropas motsvarande metod i fabriksklassen av panelkoden. Varje fabriksklass innehåller specifika metoder som används av panelen för att skapa motsvarande filterinstans. Om användaren till exempel väljer oskärpefiltret skapas en BlurFactory-instans. I klassen BlurFactory finns metoden modifyFilter() som tar tre parametrar: blurX, blurY och quality. Tillsammans används de för att skapa BlurFilter-instansen:

private var _filter:BlurFilter; 
 
public function modifyFilter(blurX:Number = 4, blurY:Number = 4, quality:int = 1):void 
{ 
    _filter = new BlurFilter(blurX, blurY, quality); 
    dispatchEvent(new Event(Event.CHANGE)); 
}

Om användaren i stället väljer faltningsfiltret, får han eller hon ett filter med mycket större flexibilitet och därmed fler egenskaper att ställa in. I klassen ConvolutionFactory anropas följande kod när användaren väljer ett annat värde på filterpanelen:

private var _filter:ConvolutionFilter; 
 
public function modifyFilter(matrixX:Number = 0,  
                                                matrixY:Number = 0,  
                                                matrix:Array = null,  
                                                divisor:Number = 1.0,  
                                                bias:Number = 0.0,  
                                                preserveAlpha:Boolean = true,  
                                                clamp:Boolean = true,  
                                                color:uint = 0,  
                                                alpha:Number = 0.0):void 
{ 
    _filter = new ConvolutionFilter(matrixX, matrixY, matrix, divisor, bias, preserveAlpha, clamp, color, alpha); 
    dispatchEvent(new Event(Event.CHANGE)); 
}

Observera, att varje gång filtervärdena ändras, skickas en Event.CHANGE-händelse för att meddela avlyssnarna att filtrets värden har ändrats. Klassen FilterWorkbenchController, som är den klass som faktiskt tillämpar filtren på det filtrerade innehållet, avlyssnar den händelsen för att veta när den ska hämta en ny version av filtret och tillämpa den på det filtrerade innehållet.

Klassen FilterWorkbenchController behöver inte de specifika detaljerna i varje filterfabriksklass. Den behöver bara veta att filtret har ändrats och kunna komma åt en kopia av filtret. För att detta ska fungera innehåller programmet ett gränssnitt, IFilterFactory, som definierar vilket beteende en filterfabriksklass behöver ha för att programmets FilterWorkbenchController-instans ska kunna utföra sin uppgift. IFilterFactory definierar den getFilter()-metod som används i klassen FilterWorkbenchController:

function getFilter():BitmapFilter;

Observera att gränssnittsmetoden getFilter() definierar att den returnerar en BitmapFilter-instans och inte en viss typ av filter. Klassen BitmapFilter definierar inte en viss typ av filter. I stället är den en basklass som alla filterklasser bygger på. Varje filterfabriksklass definierar en viss implementering av metoden getFilter(). I den returneras en referens till filterobjektet som skapats av filterfabriksklassen. Här följer till exempel en förkortad version av källkoden för klassen ConvolutionFactory:

public class ConvolutionFactory extends EventDispatcher implements IFilterFactory 
{ 
    // ------- Private vars ------- 
    private var _filter:ConvolutionFilter; 
    ... 
    // ------- IFilterFactory implementation ------- 
    public function getFilter():BitmapFilter 
    { 
        return _filter; 
    } 
    ... 
}

I klassen ConvolutionFactorys implementering av metoden getFilter() returneras en ConvolutionFilter-instans, med det registreras inte nödvändigtvis av alla objekt som anropar getFilter(). Enligt den definition av metoden getFilter() som ConvolutionFactory följer måste alla BitmapFilter-instanser returneras. Det kan vara en instans av vilken som helst av ActionScript-filterklasserna.

Tillämpa filter på visningsobjekt

Som förklarats i tidigare används en instans av klassen FilterWorkbenchController (kallas hädanefter ”kontrollenhetsinstansen”) i programmet Filter Workbench. Det är kontrollenhetsinstansen som faktiskt tillämpar filter på det valda visningsobjektet. Innan kontrollenhetsinstansen kan tillämpa ett filter måste den ha information om vilken bild eller vilket visuellt innehåll filtret ska tillämpas på. När användaren väljer en bild anropas metoden setFilterTarget() i klassen FilterWorkbenchController och en av konstanterna som definierats i klassen ImageType skickas som parameter:

public function setFilterTarget(targetType:ImageType):void 
{ 
    ... 
    _loader = new Loader(); 
    ... 
    _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, targetLoadComplete); 
    ... 
}

Med den informationen läser kontrollenhetsinstansen in den angivna filen och sparar den i en instansvariabel med namnet _currentTarget när den har lästs in:

private var _currentTarget:DisplayObject; 
 
private function targetLoadComplete(event:Event):void 
{ 
    ... 
    _currentTarget = _loader.content; 
    ... 
}

När användaren väljer ett filter, anropar programmet kontrollenhetsinstansens setFilter()-metod och skickar en referens till det relevanta filterfabriksobjektet till kontrollenhetsinstansen. Referensen sparas sedan i en instansvariabel med namnet _filterFactory.

private var _filterFactory:IFilterFactory; 
 
public function setFilter(factory:IFilterFactory):void 
{ 
    ... 
     
    _filterFactory = factory; 
    _filterFactory.addEventListener(Event.CHANGE, filterChange); 
}

Observera, att enligt beskrivningen ovan vet inte kontrollenhetsinstansen vilken specifik datatyp filterfabriksinstansen har. Den vet bara att objektet implementerar IFilterFactory-instansen, vilket innebär att den har en getFilter()-metod och att händelsen change (Event.CHANGE) skickas när filtret ändras.

När användaren ändrar filtrets egenskaper på filterpanelen, registrerar kontrollenhetsinstansen att filtret har ändrats eftersom filterfabriksinstansens change-händelse anropar kontrollenhetsinstansens filterChange()-metod. Den metoden anropar i sin tur metoden applyTemporaryFilter():

private function filterChange(event:Event):void 
{ 
    applyTemporaryFilter(); 
} 
 
private function applyTemporaryFilter():void 
{ 
    var currentFilter:BitmapFilter = _filterFactory.getFilter(); 
     
    // Add the current filter to the set temporarily 
    _currentFilters.push(currentFilter); 
     
    // Refresh the filter set of the filter target 
    _currentTarget.filters = _currentFilters; 
     
    // Remove the current filter from the set 
    // (This doesn't remove it from the filter target, since  
    // the target uses a copy of the filters array internally.) 
    _currentFilters.pop(); 
}

Arbetet med att tillämpa filtret på visningsobjektet görs i metoden applyTemporaryFilter(). Först får kontrollenheten en referens till filterobjektet genom att filterfabrikinstansens getFilter()-metod anropas.

var currentFilter:BitmapFilter = _filterFactory.getFilter();

Kontrollenhetsinstansen har en Array-instansvariabel som heter _currentFilters. I den sparas alla filter som har tillämpats på visningsobjektet. Nästa steg är att lägga till det nyuppdaterade filtret i den arrayen:

_currentFilters.push(currentFilter);

Sedan tilldelar koden filterarrayen till visningsobjektets filters-egenskap som tillämpar filtren på bilden:

_currentTarget.filters = _currentFilters;

Slutligen, eftersom det senast tillagda filtret fortfarande är ”arbetsfiltret” ska det inte tillämpas permanent på visningsfiltret. Därför tas det bort från arrayen _currentFilters:

_currentFilters.pop();

Att filtret tas bort från arrayen påverkar inte det filtrerade visningsobjektet eftersom ett visningsobjekt skapar en kopia av filterarrayen när det tilldelas till egenskapen filters. I visningsobjektet används den interna arrayen i stället för den ursprungliga. Det innebär att ändringar som görs i en filterarray inte påverkar visningsobjektet förrän arrayen åter tilldelas visningsobjektets filters-egenskap.