Hem E-böcker Specialeffekter och spelutveckling i Java PixelGrabber klassen  

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