Advanced
Java
Services
|
Image / Icon / BufferedImage / Screenshot |
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
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
ImageIcon imic = new ImageIcon("myImage.jpg") ; // aus einer Datei Image img = imic.getImage();
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
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();
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();
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.