Filters vergelijken in Flash

In deze zelfstudie maken we een filterprogramma waarmee de gebruiker verschillende filters op een afbeelding kan toepassen, intensiteitsniveaus kan wijzigen en de originele en gefilterde afbeeldingen kan vergelijken. We zullen ook componenten gebruiken voor onze controles.




Kort overzicht

Er zijn drie lagen: één voor ActionScript, één voor de tekst en componenten en de laatste voor de afbeelding. Het gecompileerde programma zal twee afbeeldingen bevatten, omdat er een wordt gemaakt tijdens runtime. In de runtime-versie worden filters toegepast. Bovendien wordt tijdens de uitvoering een masker gemaakt dat wordt gebruikt om delen van de gefilterde afbeelding weer te geven / te verbergen.

Ik ga ervan uit dat je al een basiskennis hebt van Flash en ActionScript 3.0. Ik zal echter nog steeds proberen elke stap zo duidelijk mogelijk te houden.

Opmerking: gedurende deze tutorial gebruik ik zwakke verwijzingen bij het toevoegen van gebeurtenislisteners. Raadpleeg deze blogpost voor meer informatie over zwakke verwijzingen.

Stap 1

Maak een nieuw ActionScript 3.0-document. Stel de Stage-maat in op 600 x 500 px. Ik heb voor deze grootte gekozen omdat de afbeelding die ik ga gebruiken, comfortabel in deze dimensies past.

Stap 2

Maak de drie eerder genoemde lagen (namelijk "acties", "tekst en componenten" en "afbeelding (origineel)"). Vergrendel de laag 'acties', omdat u niets anders aan die laag toevoegt, behalve ActionScript.

Stap 3

Selecteer de laag 'tekst en componenten' en voeg de statische tekst 'Filter' en 'Intensiteit' toe aan de linkerbovenhoek.

Stap 4

Ga naar het deelvenster Componenten en sleep vijf knoppen en twee schuifregelaars naar het werkgebied. Je kunt ze in principe zelf neerleggen zoals je wilt.

Geef de knoppen de labelwaarden "Default", "Blur", "Emboss", "Brightness" en "Negative". Geef ze vervolgens de instantienamen 'default_btn', 'blur_btn', 'emboss_btn', 'brightness_btn' en 'negative_btn'.

Geef de schuifregelaar voor de intensiteit een instantienaam van "intensity_sld" en geef de maskerschuifregelaar "mask_sld" de naam..

Opmerking: het is niet zo belangrijk waar u de schuifregelaar voor het masker plaatst, omdat we ActionScript gebruiken om deze later te verplaatsen.

Terminologie: gedurende deze tutorial kan ik "mask slider" of "mask_sld" door elkaar gebruiken. Hetzelfde geldt voor "intensiteitslid" en "intensiteit_sld".

Stap 5

U kunt nu de laag 'tekst en componenten' vergrendelen. Selecteer vervolgens de laag "afbeelding (origineel)" en importeer een afbeelding die u wilt gebruiken. Ik ga een foto van een paardenbloem gebruiken.

Stap 6

Selecteer de afbeelding en converteer deze naar een filmclipsymbool. Ik heb het "paardenbloem" genoemd, maar het kan alles zijn wat je maar wilt. Zorg ervoor dat het registratiepunt zich in de linkerbovenhoek bevindt. Ga naar de weergave "Geavanceerd" en vink "Exporteren naar ActionScript" aan. De "Exporteer in frame 1" moet automatisch worden gecontroleerd. Voer voor de klas "PhotoDandelion" in en verlaat de basisklasse als "flash.display.MovieClip".

Stap 7

Geef de nieuwe afbeelding Movie Clip de instantienaam "photoOriginal". U kunt nu de laag "afbeelding (origineel)" vergrendelen.

Stap 8 - Grondbeginselen van de filter

Met Flash kunt u filters toepassen die lijken op die in Photoshop. U kunt filters toepassen vanuit het venster Eigenschappen of via ActionScript. Hier zijn enkele van de basisfilters die Flash biedt: afschuining, vervaging, slagschaduw, gloed, enz.

Met ActionScript kunnen we een filter toepassen op elk DisplayObject via de eigenschap "filters". De waarde die is toegewezen aan de eigenschap "filters" moet een array zijn. U kunt ook meer dan één filter toepassen.

 // Een wazig filter toepassen op een DisplayObject. var bFilter: BlurFilter = new BlurFilter (); var arrFilters: Array = [bFilter]; displayObj.filters = arrFilters;

Stap 9 - Convolutiefilters

Flash ondersteunt ook convolutiefilters die meer geavanceerde effecten kunnen uitvoeren, zoals helderheid, randdetectie, reliëfdruk, enz.

Convolutiefilters kunnen alleen worden toegepast via ActionScript en vereisen ook het gebruik van matrices die beschrijven hoe de kleuren voor elke pixel moeten worden geëffectueerd. De matrix moet in een array zijn.

 // Standaard var matrixDefault: Array = [0, 0, 0, 0, 1, 0, 0, 0, 0]; // Helderdere var-matrix Lichter: Array = [0, 0, 0, 0, 2, 0, 0, 0, 0]; // Darker var matrixDarker: Array = [0, 0, 0, 0, 0.5, 0, 0, 0, 0]; // Reliëf var matrixEmboss: Array = [-1, -1, 0, -1, 1, 1, 0, 1, 1];

De middelste waarde is de huidige pixel en de omringende waarden zijn de aangrenzende pixels. De standaardwaarde is 1; als u deze waarde verhoogt, wordt de afbeelding helderder. Als u dit verlaagt, wordt het donkerder. Als u negatieve waarden linksboven en positieve waarden rechtsonder (of omgekeerd) hebt, ontstaat er een reliëfeffect.

Met ActionScript kunnen we een convolutiefilter toepassen zoals:

 // De volgende matrix zal de afbeelding fleuren. var matrixBrighter: Array = [0, 0, 0, 0, 2, 0, 0, 0, 0]; var matrixCol: Number = 3; // Aantal kolommen var matrixRow: aantal = 3; // Aantal rijen var cvFilter: ConvolutionFilter = nieuwe ConvolutionFilter (matrixCol, matrixRow, matrixBrighter); var arrFilters: Array = [cvFilter]; displayObj.filters = arrFilters;

Raadpleeg dit artikel over Adobe Flash voor meer informatie over het filter Convolution.

Stap 10

Nu gaan we de ActionScript-code schrijven. Selecteer het eerste frame van de laag "acties" en ga naar het deelvenster Handelingen.

Stap 11

Normaal houd ik ervan de tekst consistent te houden in het hele programma. Dus hier is de code voor het instellen van de tekst (Verdana) voor alle componenten wereldwijd.

 import fl.managers.StyleManager; var-indeling: TextFormat = new TextFormat ("Verdana", 10, 0x000000); StyleManager.setStyle ("textFormat", formaat);

Stap 12

Laten we nu een kopie van de foto maken (om filters toe te passen) en deze op dezelfde locatie plaatsen als de originele foto. Ik ga versie B gebruiken, omdat ik na het filter een masker wil aanbrengen. Als u met versie A een vervagingfilter toepast, merkt u mogelijk dat de onscherpte het masker overschrijdt. Dat komt omdat het filter het effect na het masker toepast.

Later maskeren we "photoWrapper" en passen we de filters alleen toe op "photoEffected".

 / * // Versie A var photoEffected: PhotoDandelion = new PhotoDandelion (); photoEffected.x = photoOriginal.x; photoEffected.y = photoOriginal.y; addChild (photoEffected); * / // Versie B var photoWrapper: Sprite = nieuwe Sprite (); photoWrapper.x = photoOriginal.x; photoWrapper.y = photoOriginal.y; var photoEffected: PhotoDandelion = new PhotoDandelion (); photoWrapper.addChild (photoEffected); addChild (photoWrapper);

Stap 13

Maak vervolgens de regel die de gefilterde en originele foto scheidt. We zullen een vorm gebruiken om een ​​lijn te tekenen. Plaats de lijn midden onder in de foto en teken de lijn van onder naar boven.

 var comparisonLine: Shape = new Shape (); comparisonLine.x = photoOriginal.x + photoOriginal.width / 2; comparisonLine.y = photoOriginal.y + photoOriginal.height; comparisonLine.graphics.lineStyle (2, 0x999999, 1, true); comparisonLine.graphics.moveTo (0, 0); comparisonLine.graphics.lineTo (0, -photoOriginal.height); addChild (comparisonLine);

Stap 14

U zult zich herinneren dat we een maskerschuifknop hebben. Met ActionScript kunnen we het onder de foto plaatsen en uitrekken, zodat de breedte gelijk is aan de breedte van de foto. Als u de waarden 'maximum' en 'breedte' instelt op de breedte van de foto, kunt u een verhouding van 1: 1 maken. Daarom hoeven we later geen schaalconversie te maken. Daarnaast centreren we de pijl in de schuifregelaar.

 mask_sld.x = photoOriginal.x; mask_sld.y = photoOriginal.y + photoOriginal.height; mask_sld.minimum = 0; mask_sld.maximum = photoOriginal.width; mask_sld.value = photoOriginal.width / 2; mask_sld.width = photoOriginal.width;

Stap 15

Laten we nu de functie maken en de gebeurtenis toewijzen aan de maskerschuifregelaar. We willen dat de "comparisonLine" de maskerschuif volgt. De breedte van het "fotomasker" moet worden gewijzigd aan de hand van de maskerschuifregelaar wanneer deze wordt gesleept. Ik weet dat we "PhotoMask" nog niet hebben aangepakt, maar dat is de volgende stap.

 import fl.events.SliderEvent; function maskSliderDrag (evt: SliderEvent): void comparisonLine.x = evt.target.value + evt.target.x; photoMask.width = evt.target.value;  mask_sld.addEventListener (SliderEvent.THUMB_DRAG, maskSliderDrag, false, 0, true);

Stap 16

Zoals eerder vermeld, wordt "photoMask" gebruikt om de "photoWrapper" te maskeren in tegenstelling tot "photoEffected". Omdat het een rechthoekig masker gaat worden, gebruiken we een vorm. Stel de positie en afmeting van de rechthoek in op hetzelfde als "photoOriginal". Zorg ervoor dat je de vorm vult met een kleur (dit kan elke kleur zijn) anders werkt het masker mogelijk niet zoals verwacht. Zet vervolgens "photoMask" als het masker van photoWrapper en de breedte van het masker op de "waarde" van de maskerschuifregelaar.

 var photoMask: Shape = new Shape (); photoMask.x = photoOriginal.x; photoMask.y = photoOriginal.y; photoMask.graphics.beginFill (0xff9900); photoMask.graphics.drawRect (0, 0, photoOriginal.width, photoOriginal.height); photoMask.graphics.endFill (); addChild (fotomasker); photoWrapper.mask = photoMask; photoMask.width = mask_sld.value;

Stap 17

We hebben een manier nodig om de laatst ingedrukte knop op te slaan, die we opslaan in "activeFilter". Dit wordt later gebruikt door de schuifregelaar voor intensiteit.

 var activeFilter: Button;

Stap 18

Vervolgens gaan we verder met de schuifregelaar voor intensiteit. We definiëren de functie "intensityChange" die wordt aangeroepen wanneer de schuifregelaar voor intensiteit wordt gesleept. De functie verzendt een gebeurtenis (d.w.z. muisklik) op basis van de laatst ingedrukte knop. We zullen ook de gebeurtenis toewijzen en de schuifregelaar aanvankelijk uitschakelen.

 function intensityChange (evt: SliderEvent): void activeFilter.dispatchEvent (new MouseEvent (MouseEvent.CLICK));  intensity_sld.addEventListener (SliderEvent.THUMB_DRAG, intensityChange, false, 0, true); intensity_sld.enabled = false;

Stap 19

Laten we nu de filterfuncties definiëren. De filterfuncties "standaard" en "negatief" lijken op elkaar omdat ze beide de schuifregelaar voor intensiteit uitschakelen en dus de eigenschappen van de schuifregelaar niet hoeven bij te werken. Voor "vervagen", "embosseren" en "helderheid" moeten ze allemaal de intensiteitschuifregelaar opnieuw inschakelen. Bovendien gebruiken ze de eigenschap "value" om de intensiteit van het filter te bepalen. Bovendien heeft elk filter zijn eigen unieke "maximum" -waarde, dus we moeten de "snapInterval" opnieuw berekenen. De eigenschap "value" wordt ook opnieuw berekend, omdat ik wil dat de schuif halverwege tussen de min en max wordt gereset. We hoeven alleen de eigenschappen van de intensiteitsschuifregelaar in te stellen wanneer het "activeFilter" niet gelijk is aan het huidige doel.

 function default_btnHandler (evt: MouseEvent): void var matrixDefault: Array = [0, 0, 0, 0, 1, 0, 0, 0, 0]; var conv: ConvolutionFilter = new ConvolutionFilter (3, 3, matrixDefault); photoEffected.filters = [conv]; activeFilter = evt.target als knop; intensity_sld.enabled = false;  function blur_btnHandler (evt: MouseEvent): void if (activeFilter! = evt.target) intensity_sld.maximum = 30; intensity_sld.snapInterval = (intensity_sld.maximum - intensity_sld.minimum) / 40; intensity_sld.value = intensity_sld.maximum / 2;  var blurX: Number = intensity_sld.value; var blurY: Number = intensity_sld.value; photoEffected.filters = [new BlurFilter (blurX, blurY, BitmapFilterQuality.HIGH)]; activeFilter = evt.target als knop; intensity_sld.enabled = true;  function emboss_btnHandler (evt: MouseEvent): void if (activeFilter! = evt.target) intensity_sld.maximum = 4; intensity_sld.snapInterval = (intensity_sld.maximum - intensity_sld.minimum) / 40; intensity_sld.value = intensity_sld.maximum / 2;  var matrixEmboss: Array = [-intensity_sld.value, -intensity_sld.value, 0, -intensity_sld.value, 1, intensity_sld.value, 0, intensity_sld.value, intensity_sld.value]; var conv: ConvolutionFilter = new ConvolutionFilter (3, 3, matrixEmboss); photoEffected.filters = [conv]; activeFilter = evt.target als knop; intensity_sld.enabled = true;  function brightness_btnHandler (evt: MouseEvent): void if (activeFilter! = evt.target) intensity_sld.maximum = 6; intensity_sld.snapInterval = (intensity_sld.maximum - intensity_sld.minimum) / 40; intensity_sld.value = intensity_sld.maximum / 2;  var matrix Helderheid: Array = [0, 0, 0, 0, intensity_sld.value, 0, 0, 0, 0]; var conv: ConvolutionFilter = new ConvolutionFilter (3, 3, matrixBrightness); photoEffected.filters = [conv]; activeFilter = evt.target als knop; intensity_sld.enabled = true;  function negative_btnHandler (evt: MouseEvent): void var matrixNegative: ColorMatrixFilter = new ColorMatrixFilter ([- 1, 0, 0, 0, 255, 0, -1, 0, 0, 255, 0, 0, -1, 0 255, 0, 0, 0, 1, 0]); photoEffected.filters = [matrixNegative]; activeFilter = evt.target als knop; intensity_sld.enabled = false; 

Opmerking: voor het "negatieve" filter heb ik een ColorMatrixFilter gebruikt dat een 4 bij 5 matrix gebruikt om kleurtransformaties toe te passen. Raadpleeg dit Adobe Flash-artikel voor meer informatie over de ColorMatrixFilter.

Stap 20

Laten we nu elk van de knoppen toewijzen aan de bijbehorende functies.

 default_btn.addEventListener (MouseEvent.CLICK, default_btnHandler, false, 0, true); blur_btn.addEventListener (MouseEvent.CLICK, blur_btnHandler, false, 0, true); emboss_btn.addEventListener (MouseEvent.CLICK, emboss_btnHandler, false, 0, true); brightness_btn.addEventListener (MouseEvent.CLICK, brightness_btnHandler, false, 0, true); negative_btn.addEventListener (MouseEvent.CLICK, negative_btnHandler, false, 0, true);

Stap 21 - Laatste code

Ik heb drie extra functies gemaakt, namelijk "applyConvolutionFilter", "activeFilterAndIntensityOnOff" en "setSliderProperties". Hun doel is om herhalende codering in de filterfuncties te verminderen.

Je uiteindelijke volledige code moet er ongeveer zo uitzien ...

 import fl.events.SliderEvent; import fl.managers.StyleManager; var-indeling: TextFormat = new TextFormat ("Verdana", 10, 0x000000); StyleManager.setStyle ("textFormat", formaat); var photoWrapper: Sprite = nieuwe Sprite (); photoWrapper.x = photoOriginal.x; photoWrapper.y = photoOriginal.y; var photoEffected: PhotoDandelion = new PhotoDandelion (); photoWrapper.addChild (photoEffected); addChild (photoWrapper); var comparisonLine: Shape = new Shape (); comparisonLine.x = photoOriginal.x + photoOriginal.width / 2; comparisonLine.y = photoOriginal.y + photoOriginal.height; comparisonLine.graphics.lineStyle (2, 0x999999, 1, true); comparisonLine.graphics.moveTo (0, 0); comparisonLine.graphics.lineTo (0, -photoOriginal.height); addChild (comparisonLine); mask_sld.x = photoOriginal.x; mask_sld.y = photoOriginal.y + photoOriginal.height; mask_sld.minimum = 0; mask_sld.maximum = photoOriginal.width; mask_sld.value = photoOriginal.width / 2; mask_sld.width = photoOriginal.width; function maskSliderDrag (evt: SliderEvent): void comparisonLine.x = evt.target.value + evt.target.x; photoMask.width = evt.target.value;  mask_sld.addEventListener (SliderEvent.THUMB_DRAG, maskSliderDrag); var photoMask: Shape = new Shape (); photoMask.x = photoOriginal.x; photoMask.y = photoOriginal.y; photoMask.graphics.beginFill (0xff9900); photoMask.graphics.drawRect (0, 0, photoOriginal.width, photoOriginal.height); photoMask.graphics.endFill (); addChild (fotomasker); photoWrapper.mask = photoMask; photoMask.width = mask_sld.value; var activeFilter: Button; function intensityChange (evt: SliderEvent): void activeFilter.dispatchEvent (new MouseEvent (MouseEvent.CLICK));  intensity_sld.addEventListener (SliderEvent.THUMB_DRAG, intensityChange); intensity_sld.enabled = false; function applyConvolutionFilter (matrix: Array): void var cFilter: ConvolutionFilter = new ConvolutionFilter (3, 3, matrix); photoEffected.filters = [cFilter];  function activeFilterAndIntensityOnOff (btn: Button, intensityOnOff: Boolean): void activeFilter = btn; intensity_sld.enabled = intensityOnOff;  function setSliderProperties (btn: Button, max: Number): void if (activeFilter! = btn) intensity_sld.maximum = max; intensity_sld.snapInterval = (intensity_sld.maximum - intensity_sld.minimum) / 40; intensity_sld.value = intensity_sld.maximum / 2;  function default_btnHandler (evt: MouseEvent): void var matrixDefault: Array = [0, 0, 0, 0, 1, 0, 0, 0, 0]; applyConvolutionFilter (matrixDefault); activeFilterAndIntensityOnOff (evt.target als Button, false);  function blur_btnHandler (evt: MouseEvent): void var btn: Button = evt.target as Button; setSliderProperties (btn, 30); var blurX: Number = intensity_sld.value; var blurY: Number = intensity_sld.value; photoEffected.filters = [new BlurFilter (blurX, blurY, BitmapFilterQuality.HIGH)]; activeFilterAndIntensityOnOff (btn, true);  function emboss_btnHandler (evt: MouseEvent): void var btn: Button = evt.target as Button; setSliderProperties (btn, 4); var matrixEmboss: Array = [-intensity_sld.value, -intensity_sld.value, 0, -intensity_sld.value, 1, intensity_sld.value, 0, intensity_sld.value, intensity_sld.value]; applyConvolutionFilter (matrixEmboss); activeFilterAndIntensityOnOff (btn, true);  function brightness_btnHandler (evt: MouseEvent): void var btn: Button = evt.target as Button; setSliderProperties (btn, 6); var matrix Helderheid: Array = [0, 0, 0, 0, intensity_sld.value, 0, 0, 0, 0]; applyConvolutionFilter (matrixBrightness); activeFilterAndIntensityOnOff (btn, true);  function negative_btnHandler (evt: MouseEvent): void var matrixNegative: ColorMatrixFilter = new ColorMatrixFilter ([- 1, 0, 0, 0, 255, 0, -1, 0, 0, 255, 0, 0, -1, 0 255, 0, 0, 0, 1, 0]); photoEffected.filters = [matrixNegative]; activeFilterAndIntensityOnOff (evt.target als Button, false);  default_btn.addEventListener (MouseEvent.CLICK, default_btnHandler, false, 0, true); blur_btn.addEventListener (MouseEvent.CLICK, blur_btnHandler, false, 0, true); emboss_btn.addEventListener (MouseEvent.CLICK, emboss_btnHandler, false, 0, true); brightness_btn.addEventListener (MouseEvent.CLICK, brightness_btnHandler, false, 0, true); negative_btn.addEventListener (MouseEvent.CLICK, negative_btnHandler, false, 0, true);

Opmerking: je kunt zelfs verder gaan dan wat ik heb gedaan, zoals het implementeren van een centrale functie die alle filters omvat. Gebruik vervolgens een "if else if" of "switch" om de nodige code voor het overeenkomstige filter uit te voeren.

Conclusie

Er zijn veel dingen die je kunt doen met filters, ik heb eenvoudigweg een korte introductie gegeven. De basisfilters in Flash zijn redelijk goed omdat er genoeg parameters zijn om mee te spelen. Als u niet kunt vinden wat u zoekt, probeer dan enkele van de andere filters zoals ColorMatrixFilter, ConvolutionFilter, DisplacementMapFilter, enz. U zult misschien verrast zijn door wat u vindt. Blijf experimenteren en vooral, veel plezier!

Bedankt dat je de tijd hebt genomen om deze tutorial te bekijken. Ik hoop dat je het nuttig hebt gevonden.