Confronto dei filtri in Flash

In questo tutorial creeremo un programma di filtri che consentirà all'utente di applicare diversi filtri a un'immagine, modificare i livelli di intensità e confrontare le immagini originali e filtrate. Useremo anche componenti per i nostri controlli.




Breve panoramica

Ci saranno tre livelli: uno per ActionScript, un altro per il testo e i componenti e l'ultimo per l'immagine. Il programma compilato conterrà due immagini poiché ne verrà creato uno in fase di esecuzione. Alla versione di runtime verranno applicati dei filtri. Inoltre, verrà creata una maschera in fase di esecuzione che verrà utilizzata per mostrare / nascondere parti dell'immagine filtrata.

Suppongo che tu abbia già una conoscenza di base di Flash e ActionScript 3.0. Tuttavia, cercherò comunque di mantenere ogni passaggio il più chiaro possibile.

Nota: durante questo tutorial userò riferimenti deboli quando aggiungo listener di eventi. Per ulteriori informazioni sui riferimenti deboli, fare riferimento a questo post del blog.

Passo 1

Crea un nuovo documento ActionScript 3.0. Imposta la dimensione dello stage su 600 x 500 px. Ho scelto questa dimensione dal momento che l'immagine che utilizzerò si adatterà comodamente a queste dimensioni.

Passo 2

Crea i tre livelli precedentemente citati (vale a dire "azioni", "testo e componenti" e "immagine (originale)"). Blocca il livello "azioni" poiché non aggiungerai nulla a quel livello oltre a ActionScript.

Passaggio 3

Seleziona il livello "testo e componenti" e aggiungi il testo statico "Filtro" e "Intensità" all'angolo in alto a sinistra.

Passaggio 4

Vai al pannello Componenti e trascina cinque pulsanti e due cursori sul palco. Puoi fondamentalmente metterli fuori come preferisci.

Assegna ai pulsanti valori di "Predefinito", "Sfocatura", "Rilievo", "Luminosità" e "Negativo". Quindi dai loro nomi di istanza di "default_btn", "blur_btn", "emboss_btn", "brightness_btn" e "negative_btn".

Assegna al cursore dell'intensità un nome di istanza di "intensity_sld", quindi assegna un nome al dispositivo di scorrimento della maschera "mask_sld".

Nota: non è troppo importante la posizione del cursore della maschera poiché utilizzeremo ActionScript per riposizionarlo in un secondo momento.

Terminologia: in questo tutorial posso riferirmi a "mask slider" o "mask_sld" in modo intercambiabile. Lo stesso vale per "slider intensità" e "intensity_sld".

Passaggio 5

Ora puoi bloccare il livello "testo e componenti". Quindi, selezionare il livello "immagine (originale)" e importare un'immagine che si desidera utilizzare. Userò una foto di un dente di leone.

Passaggio 6

Seleziona l'immagine e convertila in un simbolo di clip filmato. L'ho chiamato "dente di leone", ma può essere qualsiasi cosa tu voglia. Assicurati che il punto di registrazione sia nell'angolo in alto a sinistra. Vai nella vista "Avanzate" e seleziona "Esporta per ActionScript". L'opzione "Esporta nel frame 1" dovrebbe essere automaticamente controllata. Per la classe, inserisci "PhotoDandelion" e lascia la classe base come "flash.display.MovieClip".

Passaggio 7

Dare la nuova immagine Movie Clip il nome dell'istanza "photoOriginal". Ora puoi bloccare il livello "immagine (originale)".

Passaggio 8 - Nozioni di base sui filtri

Flash ti consente di applicare filtri simili a quelli di Photoshop. È possibile applicare i filtri dal pannello Proprietà o tramite ActionScript. Ecco alcuni dei filtri base forniti da Flash: smussatura, sfocatura, ombreggiatura, bagliore, ecc.

Usando ActionScript possiamo applicare un filtro a qualsiasi DisplayObject attraverso la sua proprietà "filters". Il valore assegnato alla proprietà "filters" deve essere una matrice. Puoi anche applicare più di un filtro.

 // Applicazione di un filtro sfocatura a DisplayObject. var bFiltro: BlurFilter = new BlurFilter (); var arrFilters: Array = [bFilter]; displayObj.filters = arrFilters;

Passaggio 9 - Filtri di convoluzione

Flash supporta anche i filtri di convoluzione che possono eseguire effetti più avanzati come luminosità, rilevamento dei bordi, rilievo, ecc.

I filtri di convoluzione possono essere applicati solo tramite ActionScript e richiedono anche l'uso di matrici che descrivono come devono essere effettuati i colori per ciascun pixel. La matrice deve essere in un array.

 // Default var matrixDefault: Array = [0, 0, 0, 0, 1, 0, 0, 0, 0]; // Brighter var matrixBrighter: Array = [0, 0, 0, 0, 2, 0, 0, 0, 0]; // Darker var matrixDarker: Array = [0, 0, 0, 0, 0.5, 0, 0, 0, 0]; // Emboss var matrixEmboss: Array = [-1, -1, 0, -1, 1, 1, 0, 1, 1];

Il valore centrale è il pixel corrente e i valori circostanti sono i pixel adiacenti. Il valore predefinito è 1; aumentando questo valore, l'immagine risulterà più luminosa. Diminuendo lo farà diventare più scuro. Avere valori negativi in ​​alto a sinistra e valori positivi in ​​basso a destra (o viceversa) crea un effetto rilievo.

Utilizzando ActionScript, possiamo applicare un filtro di convoluzione in questo modo:

 // La seguente matrice illuminerà l'immagine. var matrixBrighter: Array = [0, 0, 0, 0, 2, 0, 0, 0, 0]; var matrixCol: Number = 3; // Numero di colonne var matrixRow: Number = 3; // Numero di righe var cvFilter: ConvolutionFilter = new ConvolutionFilter (matrixCol, matrixRow, matrixBrighter); var arrFilters: Array = [cvFilter]; displayObj.filters = arrFilters;

Per ulteriori informazioni sul filtro Convolution, fare riferimento a questo articolo Adobe Flash.

Passaggio 10

Ora scriveremo il codice ActionScript. Seleziona il primo fotogramma del livello "azioni" e vai nel pannello Azioni.

Passaggio 11

Normalmente mi piace mantenere il testo coerente nell'intero programma. Quindi, ecco il codice per l'impostazione del testo (Verdana) per tutti i componenti a livello globale.

 importare fl.managers.StyleManager; formato var: TextFormat = new TextFormat ("Verdana", 10, 0x000000); StyleManager.setStyle ("textFormat", formato);

Passaggio 12

Ora creiamo una copia della foto (per l'applicazione dei filtri) e la posizioniamo nella stessa posizione della foto originale. Userò la versione B, dal momento che voglio applicare una maschera dopo il filtro. Con la versione A, se si applica un filtro sfocatura si potrebbe notare che la sfocatura supera la maschera. Questo perché il filtro applica il suo effetto dopo la maschera.

In seguito maschereremo "photoWrapper" e applicheremo solo i filtri a "photoEffected".

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

Passaggio 13

Quindi crea la linea che separerà la foto filtrata e originale. Useremo una forma per disegnare una linea. Posiziona la linea nella metà inferiore della foto, quindi disegna la linea dal basso verso l'alto.

 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);

Passaggio 14

Ricorderai che abbiamo un cursore maschera. Usando ActionScript, possiamo posizionarlo sotto la foto e allungarlo in modo che la sua larghezza sia uguale alla larghezza della foto. Impostando i valori "massimo" e "larghezza" sulla larghezza della foto, è possibile creare un rapporto 1: 1. Non avremo quindi bisogno di creare alcuna conversione di scala in seguito. Inoltre, centreremo la freccia nel cursore.

 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;

Passaggio 15

Ora creiamo la funzione e assegniamo l'evento per il cursore della maschera. Vogliamo che "comparisonLine" segua il cursore della maschera. La larghezza di "photoMask" dovrebbe cambiare in base al cursore della maschera ogni volta che viene trascinato. So che non abbiamo ancora affrontato "photoMask", ma questo è il prossimo passo.

 importare 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);

Passaggio 16

Come accennato in precedenza, "photoMask" verrà utilizzato per mascherare "photoWrapper" anziché "photoEffected". Dal momento che sarà una maschera rettangolare, useremo una forma. Imposta la posizione e la dimensione del rettangolo come "fotoOriginale". Assicurati di riempire la forma con un colore (questo può essere qualsiasi colore) altrimenti la maschera potrebbe non funzionare come previsto. Quindi imposta "foto maschera" come maschera di PhotoWrapper e la larghezza della maschera al "valore" del cursore della maschera.

 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 (fotomaschera); photoWrapper.mask = photoMask; photoMask.width = mask_sld.value;

Passaggio 17

Abbiamo bisogno di un modo per memorizzare l'ultimo pulsante premuto, che verrà archiviato in "activeFilter". Questo sarà usato in seguito dal cursore di intensità.

 var activeFilter: Button;

Passaggio 18

Successivamente passeremo al cursore di intensità. Definiamo la funzione "intensityChange" che verrà chiamata ogni volta che viene trascinato il cursore dell'intensità. La funzione invierà un evento (ad esempio il clic del mouse) in base all'ultimo pulsante premuto. Assegneremo anche l'evento e inizialmente disabiliteremo il cursore.

 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;

Passaggio 19

Ora definiamo le funzioni del filtro. Le funzioni di filtro "default" e "negative" sono simili in quanto entrambi disabilitano il cursore di intensità e quindi non hanno bisogno di aggiornare le proprietà del cursore. Per "sfocatura", "rilievo" e "luminosità", tutti devono riattivare il cursore dell'intensità. Inoltre, usano la proprietà "valore" per determinare l'intensità del filtro. Inoltre, ogni filtro ha il suo valore "massimo" unico, quindi è necessario ricalcolare lo "snapInterval". Anche la proprietà "valore" viene ricalcolata poiché vorrei che il cursore si ripristinasse a metà tra il minimo e il massimo. Abbiamo solo bisogno di impostare le proprietà del cursore di intensità quando "activeFilter" non è uguale al target corrente.

 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 as Button; 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 as Button; 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 as Button; 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 matrixBrightness: 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 as Button; 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 as Button; intensity_sld.enabled = false; 

Nota: per il filtro "negativo", ho utilizzato un ColorMatrixFilter che utilizza una matrice 4 per 5 per applicare le trasformazioni del colore. Per ulteriori informazioni su ColorMatrixFilter, consultare questo articolo di Adobe Flash.

Passaggio 20

Ora assegniamo ognuno dei pulsanti alle loro funzioni corrispondenti.

 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);

Step 21 - Codice finale

Ho creato tre funzioni extra: "applyConvolutionFilter", "activeFilterAndIntensityOnOff" e "setSliderProperties". Il loro scopo è di ridurre la codifica ripetitiva nelle funzioni del filtro.

Il tuo codice completo finale dovrebbe essere simile a questo ...

 importare fl.events.SliderEvent; importare fl.managers.StyleManager; formato var: TextFormat = new TextFormat ("Verdana", 10, 0x000000); StyleManager.setStyle ("textFormat", formato); var photoWrapper: Sprite = new 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 (fotomaschera); 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 as 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 matrixBrightness: 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 as 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);

Nota: puoi anche andare oltre ciò che ho fatto, ad esempio implementando una funzione centrale che comprende tutti i filtri. Quindi utilizzare "if else se" o "switch" per eseguire il codice necessario per il filtro corrispondente.

Conclusione

Ci sono molte cose che puoi fare con i filtri, ho semplicemente dato una breve introduzione. I filtri di base in Flash sono abbastanza buoni in quanto ci sono abbastanza parametri con cui giocare. Se non riesci a trovare ciò che stai cercando, prova alcuni degli altri filtri come ColorMatrixFilter, ConvolutionFilter, DisplacementMapFilter, ecc. Potresti essere sorpreso da ciò che trovi. Continua a sperimentare e, soprattutto, divertiti!

Grazie per aver dedicato del tempo a vedere questo tutorial. Spero che tu l'abbia trovato utile.