ImageIcon och bildhantering

Klassen ImageIcon

Klassen ImageIcon representerar en ikon med en bild på. Den används (förstås) för att hantera ikoner, men går ofta också bra att använda för bildhantering. Den ärver ingen annan klass och är alltså inte att betrakta som ett fönster, utan snarare som en "bildhanterare". Här är ett kort exempel, SimpleImage.java, som visar en bild med hjälp av en ikon. Eftersom ikonen inte är ett fönster placerar vid den i en JLabel (se nedan). JLabel ärver av JComponent, så nu är bilden, dvs labeln, ett fönster som till exempel kan adderas till en frame eller hantera mushändelser.

Bildhanering från och med 1.4

Från SDK 1.4 finns ett både enkelt och kraftfullt API som heter Image I/O och innehåller omfattande stöd för att läsa och skriva bilder. Kör det här programmet så får du veta vilka format din SDK stöder, CheckSupportedFormats.java. SDK 1.4.1 för linux kan läsa gif, png och jpeg och skriva png och jpeg.

Här kommer ett program som visar hur man läser en bild, ReadImage.java. Raden image = ImageIO.read(f); är det enda som krävs för att läsa en bild från fil. Parametern f är ett objekt av typen java.io.File som pekar på bildfilen. Du startar programmet genom att skriva
java -Dleffe.imagename=sökväg till filen ReadImage.

Här kommer ett program som visar hur man skriver en bild, WriteImage.java. Raden image = ImageIO.write(image, "png", f); är det enda som krävs för att läsa en bild från fil. Parametern image är bilden som ska sparas, "png" anger bildens format och f är ett objekt av typen java.io.File som pekar på bildfilen.

API:et Image I/O innehåller väsentligt mer funktionalitet för att läsa och skriva bilder men är ändå anmärkningsvärt lättanvänt. En utförlig beskrivning av det finns här, http://java.sun.com/j2se/1.4/docs/guide/imageio/index.html.

Bildhantering före 1.4

Ska vi sköta om bildhanteringen själva, utan hjälp av ImageIcon, är det en del klurigheter att tänka på. Vi går igenom det allra viktigaste med hjälp av källkoden till klassen ImageIcon. Så här går det till när den laddar in en bild:

MediaTracker tracker = new MediaTracker( this );

image = Toolkit.getDefaultToolkit().getImage("en-liten-bild.gif");  //rad 1
tracker.addImage(image, 0);                                         //rad 2
try {
  tracker.waitForID(0, 5000);                                       //rad 3
} catch (InterruptedException e) {
  System.out.println("INTERRUPTED while loading Image");
}

int loadStatus = tracker.statusID(0, false);                        //rad 4
tracker.removeImage(image, 0);                                      //rad 5

int width = image.getWidth(imageObserver);                          //rad 6
int height = image.getHeight(imageObserver);                        //rad 7
 

På rad 1 börjar bilden med angivet namn att laddas in. Metoden getImage() drar igång en tråd som laddar bilden, därefter returnerar den. På rad två anropas metoden addImage i klassen MediaTracker. MediaTracker är en hjälpklass för bildhantering. Metoden addImage() gör ingenting med bilden, den informerar bara MediaTracker om bilden och tilldelar bilden ett ID (0 i det här fallet). På rad tre väntar vi på att bilden ska laddas in, när metoden waitForID returnerar är inladdningen avslutad, men vi vet inte hur det gick. Metoden statusID() på rad 4 ger oss information om resultatet. Returvärdet är OR:at av fyra konstanter i MediaTracker: LOADING, ABORTED, ERRORED, COMPLETE. På rad fem tar vi bort bilden från MediaTrackers lista över bilder. Rad sex och sju ger oss bredd och höjd på den inladdade bilden. ImageObserver är ett interface som implementeras av Component. Om bilden ännu inte vore färdigladdad (men det är den i det här fallet) skulle metoderna returnera -1, när sedan bildens höjd/bredd blev känd skulle metoden imageUpdate() i ImageObserver anropas. I anropet av imageUpdate() skickas ett antal flaggor med information om bilden. När bilden till slut ska ritas anropas metoden drawImage(image, x, y, imageObserver)i klassen Graphics. Även den returnerar bums om än inte bilden hade varit färdigladdad. ImageObserver anropas på samma sätt som beskrivits närmast ovan.