Specialeffekter och spelutveckling
i Java(TM) - Hur man hanterar pixels
av Anibal Wainstein
7.0 Hur man hanterar pixels
Äntligen
är vi redo för att ge oss in på bildbehandlingsområdet.
Det är bildbehandling realtid som ger Java applets möjligheten
att bli avancerade specialeffekter såsom bildtoningar,
explosioner, 3D-miljöer m.m. Med realtid menas
att effekten eller animationen räknas ut innan
varje bildruta visas. Detta kräver förstås
att man har en någorlunda snabb dator för att det
skall gå snabbt. Normalt så räcker en Pentium
100 väl för att köra den här typen av
specialeffekter. Det finns två sätt att göra
bildbehandling i Java, den som vi kommer att använda
är samma teknik som använts i flera år av
appletföretag som Demicron
och Anfy Java (jag
använder det också för de flesta av mina
egna applets). Huvudverktygen för den här tekniken
är klasserna MemoryImageSource och PixelGrabber. Den
andra tekniken, att använda Java's filterklasser, är
för långsam och ineffektiv för att vara till
nytta när man gör specialeffekter i realtid. Filterklasserna
kommer jag därför inte att nämna, förresten
har vi inte gått igenom objektorientering ännu.
PROBLEM
PÅ MACINTOSH! Om du använder en Macintosh för
att läsa det här kapitlet så försäkra
dig om att du använder Internet Explorer som webbläsare.
Netscape's Java VM är för buggad för att köra
den här typen av Java applets (den har alltid varit det).
I Netscape 6.0 för Macintosh skall det gå att byta
till en annan Java motor. Byt i så fall till Apple's
egen Java motor (Macintosh Runtime for Java), den ger dessutom
din webbläsare en kapacitet som matchar Netscape och
Internet Explorer i PC Windows-miljö. Internet Explorer's
Java motor är slöare.
PROBLEM
PÅ PC! Om du använder Netscape version 3.0
för Windows så byt till en senare version. Netscape
version 3.0 har en minnesbug som gör att createImage()
kombinerat med MemoryImageSource klassen leder till minnesläckor.
Byt till Netscape version 3.01 eller senare. Ibland kan en
upplösning på 32 bitar i Windows leda till konstiga
buggar i nya webläsare, detta händer i Internet
Explorer (versioner 4.0 till 5.0) och Netscape (versioner
4.0 till 4.5). Använd 16 miljoner färger istället
(24 bitars upplösning), slutresultatet blir detsamma
i Java applets. Jag rekommenderar att du använder Netscape
3.01 när du programmerar Java applets, den är normen
för den perfekta Java-webbläsaren, även om
den är mycket slöare än de nyare läsarna.
Den närmaste i perfektion är Internet Explorer 4.1.
7.0.1 Vad innehåller
ett pixelvärde?
I
avsnitt 2.0.1
så gick vi igenom hur man blandar till färger och
hur RGB fungerar. Som jag har sagt tidigare så består
appletskärmen av pixlar. Dessa pixlar ska man kunna manipulera.
Ett pixelvärde är ett int-värde som består
av fyra bytes. Tre av dem är RGB-komponenterna som vi
redan känner till men den fjärde byten är den
s.k. alfakanalen. Alfakanalen används inom grafikprogrammering
för att indikera hur transparent en pixel skall
vara. En delvis transparent pixel kommer att låta en
del av bakgrunden lysa igenom. T.ex. om du skall göra
en animation av ett spöke, så kan det vara bra
att ha 50% transparens på spökets bild, så
att det blir en mer realistiskt effekt. I Java 1.02 så
kan man bara ha 100% transparens (pixeln är osynlig),
eller 0% transparens (pixeln är solid). Men delvis transparens
kan simuleras genom färgblandning. Senare webbläsare
stöder delvis transparens på alfakanalen. För
er som jobbar med HTML, kan det vara lättare att förstå
om jag säger att i transparenta GIF89 bilder så
är värdet för alfa-kanalen "255"
i det synliga området, och "0" i det osynliga
området av bilden. Låt oss titta närmare
på int-värdet:
FF |
FF |
FF |
FF |
Alfa |
Röd |
Grön |
Blå |
En
32 bitars int-värde representerar ett pixelvärde
som innehåller 8 hexadecimala tal och fyra färgkomponenter.
Varje komponent i färgvärdet består alltså
av två hexadecimala tal.
Tabellen
ovan representerar en pixel. Du kanske undrar vad "FF"
är för något. Det är det hexadecimala
motsvarigheten av 255, som är maxvärdet för
en byte. En hexadecimalt tal har basen 16, vilket betyder
att det finns 16 tal istället för 10. Talen 10,
11, 12, 13, 14 och 15 motsvaras av A, B, C, D, E och F. För
varje skift åt vänster av ett av dessa tal motsvarar
en multiplikation med 16 i det decimala talsystemet. Så
här konverterar man värdet av "FF" till
ett decimalt tal:
Observera att "F" betyder 15
FF = (F*16)+F = (15*16)+15 = 255 Ett
annat exempel:
Observera att "A" betyder 10 och "E" betyder 14)
E28A = (E*16*16*16)+(2*16*16)+(8*16)+A = 57994 Så
varför bör man använda hexadecimala tal när
man håller på med pixelbehandling? Det är
faktiskt mycket lättare att arbeta med dem, eftersom
pixelvärdets tal delas upp i fyra grupper som då
exakt representerar de fyra komponenterna. Du kan t.ex. ändra
på blåkomponenten i färgvärdet genom
att manipulera de två första talen. Du får
mindre kod och det är lättare att se vad färgen
är. Ett exempel:
I pixelvärdet FF030303 kan du genast se att det
motsvarar ett alfa-värde på 255 samt ett värde på 3
för både rött, grönt och blått. Decimalt så är
värdet 4278387459, där det är BETYDLIGT svårare att läsa
av färgvärderna.
Jag
kommer inte att gå igenom mer om hexadecimala tal i
den här kursen. Om du inte är så hemma på
det kan du använda Windows räknaren i avancerad
läge (scientific mode) för att kunna konvertera
mellan decimala- och hexadecimala tal. Jag brukar själv
använda det. I Java skriver man hexadecimala färgvärden
på följande sätt:
int redvalue = 0xff0000;
int greenvalue = 0xff00;
int bluevalue = 0xff;
Observera
att alfa-kanalen i värdena ovan är 0. Om man skall
använda dessa som färgpixelvärden som man vill
skall SYNAS så bör man lägga till ett fullt
värde på alfa kanalen (FF):
int redvalue = 0xffff0000;
int greenvalue = 0xff00ff00;
int bluevalue = 0xff0000ff;
Anta
nu att vi har fyra int-variabler: "a", "r",
"g" och "b". Dessa variabler representerar
alfa-kanalen och färgkomponenterna samt har värden
mellan 0 och 255. Hur bygger man upp ett färgvärde
med dessa variabler? Jo, så här:
int colorvalue = a*256*256*256 + r*256*256 + g*256 + b;
Som
du ser multiplicerar vi varje komponent ett antal gånger
med 256 så att värdet hamnar på rätt
"plats" i färgvärdet. Hur många
färgvärden innehåller appletskärmen,
egentligen? Ja, hur stor skärm har DU specifierat i resize()
metoden? Om du har specifierat en skärm med bredden 200
och höjden 300 så har du 200x300 = 60000 färgvärden
att hålla reda på (dvs 60000 int-värden).
Att behandla alla dessa pixlar kan ta tid. Nu vet du en av
orsakerna till varför bildbehandling kan vara processorkrävande.
Nästa sida >>
|