Manipulere visuelle effekter med ColorMatrixFilter og ConvolutionFilter

ColorMatrixFilter og ConvolutionFilter kan brukes til å visuelt transformere Flash-objektene dine. I denne artikkelen vil jeg vise deg hvor lett de skal manipulere, ved hjelp av et kult verktøy jeg bygget for enkel eksperimentering.




Introduksjon

Har dere noen gang eksperimentert med Flashs ColorMatrix og Convolution-filtre? Jeg graver rundt i et forsøk på å finne noen interessante ting du kan gjøre med Flash, og jeg støter på dem. Å eksperimentere med dem kan levere noen flotte resultater.

Jeg har skrevet en EffectsTester for å gjøre det enkelt å eksperimentere med dem. Sjekk ut disse camshots jeg tok mens jeg spilte med det:

Nå, hvis du finner det interessant, la meg gå deg gjennom hva disse to filtrene handler om.

Fargematrisfilteret

Fargematrisfilteret brukes til å manipulere fargen til et displayobjekt.

La meg forklare nøyaktig beregning utført av ColorMatrixFilter. Hver piksel i et bilde er en blanding av rød, grønn og blå. Disse primære farger, når kombinert, kan gjøre noen annen farge:

Bilde fra Wikimedia Commons. Takk til Mike Horvath og jacobolus.

Mengden rød i en piksel kan variere fra null (ingen rød i det hele tatt) til 255. Samme for grønn og blå. Så fra bildet over kan du se at en ren gul piksel har rødt = 255 og grønt = 255. Hvitt har rødt, grønt og blått alt satt til 255. Sort har alle tre sett til null.

Fargematrixfilteret ser på hver piksel i et kildebilde og endrer dem basert på hvor mye rødt, blått og grønt er i pikselet. Du ender med et helt nytt bilde; de destinasjonsbilde.

Slik fungerer det

La oss først konsentrere oss om disse tre verdiene:

La oss merke disse verdiene en [0], en [1] og en [2] igjen. Nå tenk bare på en enkelt piksel i hele kildebildet (den øverst til venstre vil gjøre). La oss kalle mengden rød i det srcR, mengden grønn srcG og mengden blå srcB.

Spørsmålet er: hvor mye rød vil være i den pixel av målbildet, Destr? Flash bruker denne beregningen:

 destR = (a [0] * srcR) + (a [1] * srcG) + (a [2] * srcB);

Her kan du se at a [0] er 1, mens en [1] og en [2] begge er null, så:

 destR = (1 * srcR) + (0 * srcG) + (0 * srcB); // som betyr ... destR = srcR;

Det er ingen endring! Men hva om vi endret en [0] til null og en [1] til 1? Deretter:

 destR = (0 * srcR) + (1 * srcG) + (0 * srcB); // som betyr ... destR = srcG;

... mengden rød i destinasjonspikselet vil være lik mengden av grønn i kilden pixel! Videre, hvis du endret andre rad for å lese "1 0 0", da vil mengden grønt i destinasjonspiksel være lik mengden rød i kildepikselet; du ville ha byttet dem over og din oransje fisk ville bli grønn:

Du lurer nok på om EN kolonne og rad og om offset kolonne. Vel, A står for alfa, noe som betyr gjennomsiktighet. A-verdiene har mye samme effekt som R G B-verdiene, men siden ingen av disse eksemplene er gjennomsiktige, er det vanskelig å demonstrere. Offset-kolonnen lar deg enkelt øke eller redusere mengden rød, blå eller grønn i destinasjonspiksel: skriv -255 i kolonnen Offset-kolonne R og du vil se at det ikke lenger er noe rødt på bildet.

Eksperiment

Jeg skjønner at det er vanskelig å forstå dette bare ved å lese om det, så vi skal se på noen kule eksempeleffekter. Det er mye morsomt, uansett. Men først, for nysgjerrige, her er den faktiske matematiske formelen Flash bruker:

 destR = (a [0] * srcR) + (a [1] * srcG) + (a [2] * srcB) + (a [3] * srcA) + a [4]; destG = (a [5] * srcR) + (a [6] * srcG) + (a [7] * srcB) + (a [8] * srcA) + a [9]; destB = (a [10] * srcR) + (a [11] * srcG) + (a [12] * srcB) + (a [13] * srcA) + a [14]; destA = (a [15] * srcR) + (a [16] * srcG) + (a [17] * srcB) + (a [18] * srcA) + a [19];

(Hver av verdiene du ser i 5x4-matrisen, kan variere mellom -255 og 255.)

Ta en titt på "Fargekart" -eksempelbilde:

La oss si at du vil fjerne all rød farge fra bildet. Bare sett alle verdiene i R-raden til null:

Dette betyr:

 destR = (0 * srcR) + (0 * srcG) + (0 * srcB) + (0 * srcA) + 0; // som betyr: destR = 0 + 0 + 0 + 0 + 0; // så: destR = 0;

La oss si at du vil legge til litt mer grønt der det tidligere var rødt. Sett "1" på inngang 0x1, så G-raden leser "1 1 0 0 0":

La oss nå oppnå noe veldig rart ved å endre G-raden til "0 -1 0 0 50":

Hva skjedde nå? For eksempel, hvis noen tilfeldig piksel du hadde grønn = 30, ble den multiplisert med '-1' og etterpå ble 50 lagt til, så resultatet ville være: (30 * -1) + 50 = 20.

Derfor en type terskel er opprettet: for hver piksel med en grønn verdi som er større enn 50, blir den transformerte pikselen helt slått av. Hvorfor? Vel, anta at pikselets grønne kanal har en verdi på 51:

 destG = (0 * srcR) + (-1 * srcG) + (0 * srcB) + (0 * srcA) + 50; // husk srcG = 51: destG = 0 + (-51) + 0 + 0 + 50; // så: destG = - 51 + 50; // så: destG = -1; // men en piksel kan ikke ha en negativ mengde grønt, så dette er bare satt til null: destG = 0;

Prøv nå dette:

Alle piksler med grønne verdier større enn 50 blir slått av, og de med grønne verdier under 50 har økt alle tre fargekanaler. Dette gjør at du kan se områder av bildet som bare har en liten mengde grønn, som med fiskbildet:

x

Her er bare pikslene med en mengde grønn mindre enn 50. Jo mørkere piksel, jo mer grønn er det i det opprinnelige bildet. Det er grunnprinsippet uansett. Jeg vet at det kan virke komplisert først, men lek med det, og du får det til slutt :)

gråtoner

OK, la oss gå for noe standard: et gråtonebilde. Endre matrisen din slik:

Du har en gråtoner. Hyggelig :)

Inverterte farger

La oss oppnå en annen populær fargestatus: Inverterte farger.

For å invertere fargene må vi gjøre det slik at hver piksel med en rød verdi på 255 har en rød verdi på null og omvendt. Samme for de to andre farger. Så vi må lage Flash-koden som ser slik ut:

 destR = 255 - srcR; destG = 255 - srcG; destB = 255 - srcB;

Men det er enkelt! Alt vi trenger å gjøre er å sette matrisen slik:

Tada! Elektrisk fisk:

Flere effekter

De fleste eksotiske effekter som kan oppnås av ColorMatrixFilter, gjøres ved å sette en negativ verdi for en farge og en positiv verdi for offset - eller omvendt. Sett "-1" fra 0x3 til 2x3 (alfaene) og 255 for kompensasjon av alfa (4x3).
Wow, nå vet jeg nå hvordan de gjorde Terminator 2 :)

Ærlig, jeg er ikke helt sikker på hva jeg nettopp gjorde - beregninger blir veldig vanskelig å spore etter en stund.

Selv om det er mulig å forstå hvordan ColorMatrixFilter fungerer fra et matematisk synspunkt, vil det realistisk være et spørsmål om å leke med det. Du kan aldri være helt sikker på hva som skal komme opp når du legger noen spesifikke verdier. Derfor laget jeg denne EffectsTester. Så spill rundt. Gjør deg selv metallisk grønn, eller rød, eller fargeløs.

Real World Application

Når du har en effekt du liker, kan du bruke den til noen DisplayObject (MovieClip, Sprite, Bitmap ...) i din egen kode som dette:

 // første importere ColorMatrixFilter oppe på toppen av koden din: importer flash.filters.ColorMatrixFilter; // ... senere: var filtre: Array = new Array (); // for alt etter "= nytt", kopier og lim inn fra "Grab The Code" -boksen i EffectsTester: var cmf: ColorMatrixFilter = ny ColorMatrixFilter (ny array (-1,0,0,0,255,0, -1,0 , 0,255,0,0, -1,0,255,0,0,0,1,0)); // De neste to linjene gjelder filteret til visningsobjektet: filters.push (cmf); myDisplayObject.filters = filtre;

La oss nå se på convolution filteret.

Konvoluttfilteret

Fra Adobes klassereferanse:

En konvolusjon kombinerer piksler i inngangsbildet med nabobillingene for å produsere et bilde. Et stort utvalg av bildeeffekter kan oppnås gjennom konvolusjoner, inkludert uskarphet, kantdeteksjon, skarphet, preging og skråning.

Konvolutionfiltret løper gjennom alle piksler av et skjermobjekt. For hver av dem bruker den senterverdien i matrisen når verdien av den nåværende pixel blir manipulert. For eksempel, i en 3 x 3 matrise, er senterverdien på (1, 1). Det multipliserer deretter verdiene fra matrisen ved de omkringliggende piksler og legger til de resulterende verdiene for alle piksler for å få verdien for den resulterende senterpiksel.

Å forstå den nøyaktige matematikken under konvoluttmatrisen er verdt en helt ny artikkel, så jeg vil ikke dekke alt dette her. Hvis du vil komme inn på det, sjekk ut dette innlegget på adobe.com.

En enkel lek med verdiene vil etter hvert gi deg alle mulige effekter du kan oppnå. Og det blir morsomt :) Så la oss se hva vi kan gjøre!

Eksperiment

Konfusjonsfiltret bruker en matrise, akkurat som fargematriksfilteret. Igjen, varierer verdiene mellom -255 og 255. Og igjen oppnår du de fleste interessante effekter når du kombinerer negative verdier med positive.

La meg dele med deg mine observasjoner av hvordan denne tingen fungerer. Prøv å øke noen tilfeldig verdi fra matrisen. Uansett hva du velger, vil det lyse bildet; Hvis du vil at bildet skal forbli ved normal lysstyrke, må du kontrollere at verdien av "divisor" er lik summen av alle verdiene i matrisen.

Nå, hvis du prøver å senke en tilfeldig verdi under null mens du holder minst en annen over null, får du noe på det. Det påvirker kantene dine:

Her er en fin en: Vil du se ut som en soldat? :) Prøv disse verdiene:

Senk nå "divisor" verdien til "-1" for å bli soldat på oppdrag om natten.

Mange ting kan oppnås hvis du holder museknappen litt mer :) Lavere og heve noen verdier til ekstremer. Ikke glem å justere "divisor" - det er avgjørende. Forstør matrisen din. Gjør det 5x5, for eksempel.

Real World Application

For å bruke effekten i din egen kode, bruk filtre objekt, akkurat som du gjorde for ColorMatrixFilter:

 // første import ConvolutionFilter oppe på toppen av koden din: importer flash.filters.ConvolutionFilter; // ... senere: var filtre: Array = new Array (); // for alt etter "= nytt", kopier og lim inn fra "Grab The Code" -boksen i EffectsTester: var cf: ConvolutionFilter = ny ConvolutionFilter (3,3, ny Array (1,0, -10, -2,3 , 1,6,1, -1), 0); // De neste to linjene gjelder filteret til visningsobjektet: filters.push (cf); myDisplayObject.filters = filtre;

Til slutt: Prøv å kombinere begge filtre.

 // Først importerer du filterklassene øverst på koden din: importer flash.filters.ColorMatrixFilter; importer flash.filters.ConvolutionFilter; // ... senere: var filtre: Array = new Array (); // for alt etter "= nytt", kopier og lim inn fra "Grab The Code" -boksen i EffectsTester: var cmf: ColorMatrixFilter = ny ColorMatrixFilter (ny array (-1,0,0,0,255,0, -1,0 , 0,255,0,0, -1,0,255,0,0,0,1,0)); var cf: ConvolutionFilter = ny KonvolutionFilter (3,3, ny Array (1,0, -10, -2,3,1,6,1, -1), 0); // De neste tre linjene gjelder filtre til skjermobjektet: filters.push (cf); filters.push (cmf); myDisplayObject.filters = filtre;

Ha det gøy å leke med disse filtrene og legg inn eventuelle resultater du får i kommentarene! Takk for at du leste.