Advanced   Java   Services
Image / Icon / BufferedImage / Screenshot
Back Next Up Home


Seit den Versionen 1.3 und 1.4 gibt es einige interessante neue Möglichkeiten, von denen hier einige angesprochen werden sollen. So kann man mit Hilfe der in 1.3 neu eingeführten Klasse Robot z.Bsp. ScreenShots anfertigen. Diese oder auch andere Bilder lassen sich dann mit Hilfe der Klasse ImageIO aus dem in 1.4 neu hinzugefügten package javax.imageio auch z.Bsp. auf die Festplatte schreiben. Außerdem soll hier auch die schon seit 1.1 existierende Möglichkeit aufgezeigt werden, ein Bild in ein Array von Pixels zu verwandeln, bzw. aus einem solchen wieder ein ein Bild herzustellen.

Hier zunächst eine Übersicht über die wichtigsten ImageKlassen. Alle Klassen, bei denen der package-Name nicht angegeben ist stammen aus dem package java.awt.image .

Die Image-Hierarchie


imagehierarchie2.jpg

Die ImageProducer-Hierarchie


imageproducerhierarchie2.jpg

Die ImageConsumer-Hierarchie


imageconsumerhierarchie2.jpg

Die Klasse ToolKit und ihre Realisierung


Die abstrakte Klasse Toolkit stellt Methoden zur Verfügung, die betriebssystemabhängig implementiert werden müssen. In der jeweiligen JVM existiert eine Realisierung von Toolkit. Verwendet man die SUN Implementation, so arbeitet man auf Windowssystemen mit einem Toolkit vom Typ sun.awt.windows.WToolkit . Würde man etwa Microsoft's (veraltete) JVM verwenden, so würde sich als Toolkit com.ms.awt.WToolkit ergeben. Den Klassennamen eines Objektes unbekannten Typs erhält man übrigens mit object.getClass().getName() .

Wie oft üblich in solchen Fällen, gibt es als Ersatz für einen Konstruktor eine statische Methode der abstrakten Klasse, die einem ein Objekt dieser Klasse besorgt.

Wie kommt man zu einem Toolkit ?

Es stellt sich heraus, daß alle drei Möglichkeiten dasselbe Toolkit sun.awt.windows.WToolkit liefern.

Ein Image-Objekt aus einem File erzeugen


Mit Hilfe eines Toolkit-Objekts erzeugt man ein Image-Objekt folgendermaßen

Image img = tk.getImage("myImage.jpg");
oder
Image img = tk.createImage("myImage.jpg");

Hat man eine Netzverbindung und eine Adresse, so kann man ein Image auch remote laden:

URL modigliani = new URL("http://btr0xw.rz.uni-bayreuth.de/cjackson/m/modigliani1.jpg")
Image img = tk.getImage(modigliani);
oder
Image img = tk.createImage(modigliani);

Bei einem Applet ersetzt der AppletContext die Klasse Toolkit.

AppletContext ac = myApplet.getAppletContext();
URL modigliani = new URL("http://btr0xw.rz.uni-bayreuth.de/cjackson/m/modigliani1.jpg")
Image img = ac.getImage(modigliani);

In allen Fällen erhält man mit SUN's Implementation für Windowssysteme ein ImageObjekt vom Typ sun.awt.windows.WImage .

Hinweise

Ein Image-Objekt darstellen (AWT)


AWT-Komponenten können Bilder nicht direkt anzeigen. Zum Anzeigen eines Bildes muß die paint-Methode überschrieben werden. Jede Klasse unterhalb von Component erbt von Component die Methode public void paint(Graphics g). Diese Methode ist für die graphische Darstellung der Komponente verantwortlich und wird auf Windows-Systemen u.a. etwa durch WM_PAINT Ereignisse aktiviert. Beim Aufruf wird ein Graphikkontext übergeben, der in Java durch ein Objekt der Klasse Graphics repräsentiert wird. Die Klasse Graphics bietet neben Methoden zum Zeichnen auch eine Reihe von drawImage()-Methoden an, mit denen man ImageObjekte darstellen kann. Alle drawImage()-Methoden erhalten als erstes Argument das darzustellende Bild und als letztes Argument ein Objekt vom Typ ImageObserver. Das Interface ImageObserver wird nur von der Klasse Component implementiert. In der folgenden Situation steht AWTComponent für irgendeine Unterklasse von Component aus dem package awt.

public class CustomComponent extends AWTComponent
{
   // ... (hier muß img bekanntgemacht werden)

   public void paint(Graphics g)
   {
      g.drawImage(img, 0,0, this);
   }

}

Sie hierzu auch Canvas Image MediaTracker.

Icon / ImageIcon / Ein Image-Objekt darstellen in Swing


imageiconhierarchie.jpg

Swingkomponenten wie JLabel oder AbstractButton haben diverse setIcon() Methoden und können damit Bilder direkt darstellen. Die Klasse ImageIcon hat eine sehr komfortable Konstruktorausstattung zum Erstellen von Icons.

Ein ImageIcon erzeugen :

ImageIcon imic = new ImageIcon("myImage.jpg") ;  // aus einer Datei
ImageIcon imic = new ImageIcon( new URL("http://....") ;  // aus einem URL

Hat man bereits ein Objekt vom Typ Image, so kann man daraus sehr einfach ein ImagIcon machen (und umgekehrt)

Vom Image zum ImageIcon und umgekehrt


Image img ;
ImageIcon imic = new ImageIcon(img) ;
oder
ImageIcon imic = new ImageIcon() ;
imic.setImage(img);

Imageicon imic ;
Image img = imic.getImage();


BufferedImage


Ein Imageobjekt ist zwar (natürlich) graphisch darstellbar, hat aber den Nachteil, daß man die Bilddaten des Imageobjekts nicht zur Verfügung hat. Mit einem Imageobjekt ist es nicht möglich die Bilddaten aus dem Hauptspeicher auf eine externes Speichermedium zu schreiben. Die Klasse BufferedImage implementiert jedoch das Interface WritableRenderedImage und verfügt damit über diese Möglichkeit.

Ein (leeres) BufferedImage erzeugen

hat man eine Komponente, so kann man mit

BufferedImage bufImg = (BufferedImage)component.createImage(width, height);

ein BufferedImage erzeugen. Dies funktioniert allerdings nur, wenn die Komponente sichtbar ist. Auch unterstützt das so erzeugte Objekt keine transparenten Pixels. Der cast ist notwendig, da die Methode ein Objekt vom Typ Image zurückgibt. Bei genauerer Untersuchung mit image.getClass().getName() und image instanceof java.awt.image.BufferedImage ergibt sich als Typ sun.awt.windows.Win32OffScreenImage.

Da die Klasse BufferedImage nicht abstrakt ist, kann man ihre Konstruktoren auch direkt benützen.

BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// unterstützt keine Transparenz

BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// unterstützt Transparenz


Die Version 1.4 des JDK fügt zu dem package java.awt.image das neue package javax.imageio hinzu. Hier befindet sich u.a. die äußerst nützliche Klasse ImageIO . Man kann sie u.a. wie folgt verwenden:

Auf ein BufferedImage zeichnen

Ein BufferedImage verfügt über einen eigenen Graphikkontext, den man sich mit Hilfe einer geeigneten Methode verschafft.

BufferedImage bufImg;
//ältere Methode :
Graphics g = bufImg.getGraphics();
//neuere Methode :
Graphics2D g2 = bufImg.createGraphics();
//zeichnen
g.setColor(Color.blue);
g.fillRect(...) ; 
//etc.
g.dispose();

Beide Methoden liefern ein Objekt vom Typ Graphics2D zurück. Will man Methoden aus Graphics2D verwenden, so empfiehlt sich die neuere Methode, weil man dann ohne cast auskommt.

Ein BufferedImage über ein File erzeugen

BufferedImage bufImg ;
try
{
   bufImg = ImageIO.read( new File("myImage.jpg") ) ;
}
catch(IOException ex)
{
   //...
}

Da ein BufferedImage ja auch ein Image ist, ergibt sich so eine weitere Möglichkeit, ein Image zu erzeugen, siehe hierzu weiter oben .

Ein BufferedImage im jpg-Format in eine Datei schreiben

BufferedImage bufImg;
try
{
   boolean boo = ImageIO.write(bufImg, "jpg", new File("myImage.jpg") ) ;
}
catch(IOException ex)
{
   //...
}


Ein Image in ein BufferedImage verwandeln


Die Idee ist im Grunde schon weiter oben gezeigt worden. Man muß das Image in ein BufferedImage zeichnen.

Image img; // sei initialisiert und fertig geladen

int w = img.getWidth(null); // es muß keinen ImageObserver geben
int h = img.getHeight(null);

BufferedImage bufImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
// einfachster Fall : BufferedImage.TYPE_INT_RGB
Graphics g = bufImg.createGraphics();
g.drawImage(img, 0, 0, null);
g.dispose();


Einen ScreenShot erstellen


Mit der in J2SDK 1.3 im package java.awt eingeführten Klasse Robot kann man denkbar einfach einen ScreenShot erstellen.

try
{
   // Bildschirmgröße ermitteln
   ToolKit tk = ToolKit.getDefaultToolkit() ;
   Dimension screenSize = tk.getScreenSize() ;
   Rectangle screenRect = new Rectangle(screenSize);

   // eigentlicher screenshot
   Robot rob = new Robot() ;
   BufferedImage screenShot = rob.createScreenCapture(screenRect) ;
}
catch(AWTException ex)
{
}

Mit einem Rectangle-Objekt kann man natürlich auch nur einen Teil des ganzen Bildschirms beschreiben. Wie man sieht erhält man den ScreenShot als BufferedImage zurück. Dieses läßt sich dann mit Hilfe der Klasse ImageIO etwa als .jpg-Datei wegschreiben.


Einige abstrakte Klassen und ihre Realisierung


Man kann sich fragen, wie das funktioniert ? Die Klasse Graphics etwa ist abstrakt, aber beim Überschreiben der paint()-Methode bekommt man ein gültiges Objekt vom Typ Graphics zurück. Hier finden Sie die Realisierungen einiger abstrakten Klassen. Die Realisierungen sind in diesen Fällen zwangsläufig betriebssystemabhängig. Die abstrakten Klassen fungieren hier als Schnittstelle. Für den Entwickler ist es egal, wie die Klasse aussieht und heißt. Durch die Realisierung ist ja sichergestellt, daß man alle Methoden der abstrakten Klasse verwenden kann. Die folgenden Graphiken zeigen nur die Realisierungen für Windowssysteme, doch ergeben sich für Unix/Linux analoge Klassen.

realisierungen1.jpg



realisierungen2.jpg

top Back Next Up Home