Specialeffekter och spelutveckling
i Java(TM) - PixelGrabber klassen
av Anibal Wainstein
7.0.4 PixelGrabber klassen
Nu
vet vi hur man skapar en bild baserat på en array med
pixlar. Men hur fyller man en array med pixlar från
en färdig bild? Detta är ju nödvändigt
för att kunna utföra bildbehandling på inladdade
bilder eller på bildobjekt som har ritats med Graphics-klassen
(som t.ex. texter). Klassen som används för detta
är PixelGrabber klassen. Den finns också i java.awt.image
paketet. Tyvärr har kraftiga buggar i PixelGrabber-klassen
i vissa Java motorer under åren, lett till att den här
typen av effekter har hämmats betydligt. Idag är
det bara Macintosh-versionerna av Netscape (version 3.0 till
4.5) där den här klassen inte fungerar. Anta att
bilden som vi skall ta pixlar från heter "myimage",
den har storleken 320x200 pixlar. Det första vi måste
göra är att skapa klassen. Dess argument är
först bilden, "rektangeln" som skall tas ur
bilden (x,y positionerna samt bredden och höjden "0,0,320,200")
samt offset och scansize argumenten som man brukar sätta
till 0 respektive bredden av den rektangulära biten som
skall hämtas. Att använda PixelGrabber är komplicerat:
//Först skapar man en array som skall kunna rymma
//alla pixlarna i bilden.
int myimagearray[]=new int[320*200];
//Ett PixelGrabber-objekt måste skapas.
PixelGrabber grabber=new PixelGrabber(myimage,0,0,320,200,myimagearray,0,320);
//Metoden grabPixels() kastar ut en exception som vi
//måste fånga.
try
{
grabber.grabPixels();
}
catch(InterruptedException e)
{
System.out.println("Något gick fel!");
};
Arrayen
som man använder för att lagra pixlarna måste
vara tillräckligt stor, annars får man en ArrayOutOfBounds-exception
(Applet-felmeddelande). Efter att du har skapat klassen så
kan du slutligen använda grabPixels() metoden för
att utföra operationen. När du gör det, kommer
arrayen "myimage" att fyllas med bildens pixlar.
7.0.5 Från en grå
bild till en blå bild (Bluecomponent)
För
att illustrera processen vid bildbehandling i Java så
skall vi titta på ett enkelt exempel. I en pixel på
en svartvit bild har alla RGB-komponenterna samma värde.
Detta gäller för alla gråskalor i bilden från
vitt till svart. Nu skall vi leka lite med detta och ta bort
röd- och grönkomponententerna ur en svartvit bild
för att göra bilden blå. För att göra
detta så måste vi först ladda in bilden med
getImage() och MediaTracker som vi brukar göra, för
att senare använda oss av PixelGrabber för att kunna
komma åt dess pixlar och lagra dem i en array. Efter
det behandlar vi arrayen och använder MemoryImageSource
för att skapa en ny bild. Gör en kopia av gradient.java
filen, ändra "public class gradient" till "public
class bluecomponent" och döp om "gradientimage"
till "blueimage" överallt (glöm inte att
göra det i paint() metoden också). Det enda som
du behöver ändra nu, är innehållet i
init() metoden:
public void init()
{
//Ladda in bilden (filnamnet finns i
//parametern "image").
MediaTracker tracker=new MediaTracker(this);
Image grayimage
=getImage(getDocumentBase(),getParameter("image"));
tracker.addImage(grayimage,0);
try {tracker.waitForAll();}
catch(InterruptedException e){}
//Skapa en Dimension-objekt som
//har samma dimensioner som
//den inladdade bilden.
Dimension d
=new Dimension(grayimage.getWidth(this),grayimage.getHeight(this));
//Skapa en array som
//är lika stor som bilden.
int pixels[]=new int[d.width*d.height];
int colorvalue;
//Använd PixelGrabber klassen för att
//lagra pixlarna i arrayen "pixels".
PixelGrabber grabber
=new PixelGrabber(grayimage,0,0,d.width,d.height,pixels,0,d.width);
try {grabber.grabPixels();}
catch(InterruptedException e){};
//FOR-slingan sveper igenom
//bilden från vänster till höger.
for (int x=0; x<d.width; x++) { //FOR-slingan sveper //igenom bilden upp och ner. for (int y=0; y<d.height; y++) { //Genom att utföra en OCH-operation //med 0xff0000ff kommer bara //alfa-kanalen och blåkomponenten //att finnas kvar. pixels[x+y*d.width]=pixels[x+y*d.width]&0xff0000ff; } } //Nu gör vi en ny bild med MemoryImageSource //och createImage() MemoryImageSource imgsrc=new MemoryImageSource(d.width,d.height,pixels,0,d.width); blueimage=createImage(imgsrc); }
Vi
använder oss av de dubbla for-slingorna för att
svepa igenom arrayen. Det här är lite resursslösande
för man skulle kunna klara sig med bara en slinga. Men
det är lite mer pedagogiskt att göra det så
här. Vi använder oss av OCH-operatorn "&",
för att "maskera" bort den röda och den
blåa komponenten. Se följande räkneexempel
för att förstå hur OCH-operatorn fungerar:
0x12345678 & 0xff0000ff = 0x12000078
0x12345678 & 0xff = 0x00000078
0x12345678 & 0x000000ff = 0x00000078
0x12345678 & 0xff00 = 0x00005600 Som
du ser här ovan så är "000000ff"
samma sak som "ff" (precis som den decimala siffran
"00100", som egentligen bara betyder "100").
Nu kommer bilden att vara uppbyggd av olika blåskalor.
Vi testar appleten med följande grå bild:

I det här exemplet gör vi om
bilden "gauchos.jpg" till en blå bild .
Gör
en HTML fil för appleten och se till att du lägger
till applet-parametern "image" i HTML-koden. Vill
du se på slutresultatet så kan du klicka
här. Lek lite med maskeringsvärdet "0xff0000ff"
genom att ändra det till "0xffff0000" eller
"0xff00ffff". Vad får du för resultat?
Vad tror du händer om du byter till en färgbild?
Se bara till att du inte mixtrar med alfa-kanalen. Om du gör
det så kan bilden bli transparent och du kommer inte
att se någonting.
Nästa sida >>
|