Bilder skalieren

Aus Byte-Welt Wiki
Wechseln zu: Navigation, Suche

Bilder skalieren

Einen ausführlichen Artikel zum Thema 'Bilder skalieren' gibt es unter The Perils of getScaledInstance. Die wichtigsten Punkte sind hier kurz zusammengefasst.

Bim Skalieren von Bildern gibt es im wesentlichen zwei mögliche Ziele: Man will das Bild entweder skaliert zeichnen, oder man will eine skalierte Instanz eines Bildes erstellen. In beiden Fällen kann man noch unterschiedliche Schwerpunkte setzen. So kann im einen Fall die Performance (also die Zeichengeschwindigkeit) besonders wichtig sein, und im anderen Fall die Bildqualität.

Bilder skaliert zeichnen

Wenn man ein Bild skaliert zeichnen will, kann man das am einfachsten direkt mit der geeigneten Methode drawImage aus der Klasse Graphics. Von dieser Methode gibt es verschiedene Varianten, und unter anderem eine, mit der man direkt sagen kann, wie groß das Bild gezeichnet werden soll:

public boolean drawImage(Image image, int x, int y, int width, int height, ImageObserver observer)

Um ein Bild in einer Größe von 400x300 Bildpunkten zu zeichnen, verwendet man also

 
graphics.drawImage(image, 0, 0, 400, 300, null);


Skalierte Instanzen erstellen

Um eine skalierte Instanz eines Bildes zu erstellen, kann man einfach das vorhandene Bild in ein Bild der gewünschten Größe hineinzeichnen:

BufferedImage originalImage = ImageIO.read(new File("image.png"));
BufferedImage scaledImage = new BufferedImage(400, 300, BufferedImage.TYPE_INT_ARGB);
Graphics g = scaledImage.createGraphics();
g.drawImage(originalImage, 0, 0, 400, 300, null);
g.dispose();

Wie man sieht wird hierbei die gleiche Methode drawImage aus der Klasse Graphics verwendet, wie beim skalierten Zeichnen. Allerdings wird das Bild hier nicht auf den Bildschirm, sondern in ein anderes Bild hinein gezeichnet.


RenderingHints: Qualität oder Geschwindigkeit?

Sowohl beim skalierten Zeichnen als auch beim erstellen skalierter Instanzen kann man durch das Setzen von Rendering Hints noch festlegen, ob eher in höherer Qualität oder eher in höherer Geschwindigkeit gezeichnet werden soll. Diese Rendering Hints setzt man in dem Graphics2D-Objekt, das man zum Zeichnen verwendet. Dabei ist egal, ob man direkt auf den Bildschirm oder in ein anderes Bild hinein zeichnet.

Zum Beispiel wird hier gesagt, dass bilineare Interpolation verwendet werden soll, was zwar etwas langsamer ist, aber für höhere Bildqualität sorgt:

Graphics2D g = (Graphics2D)graphics;
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                   RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(image, 0, 0, 400, 300, null);

Hätte man statt VALUE_INTERPOLATION_BILINEAR den Wert VALUE_INTERPOLATION_NEAREST_NEIGHBOR angegeben, wäre die Bildqualität geringer, aber das Zeichnen etwas schneller.


Warum nicht getScaledInstance?

Oft werden mit der Methode Image#getScaledInstance skalierte Instanzen von Bildern erstellt und gezeichnet - im schlimmsten Fall sogar bei jedem Zeichenvorgang erneut. Diese Methode ist oft weder in bezug auf Bildqualität noch in Bezug auf die Performance die geeignetste Lösung. Die Methoden aus der Klasse Graphics2D und die RenderingHints bieten mehr Möglichkeiten, die für das jeweilige Ziel beste Skalierungs-Art zu wählen. Zusätzlich können die skalierten Instanzen, die manuell erstellt werden, Hardwarebeschleunigt sein, wodurch sie später schneller gezeichnet werden können.


Das war nicht alles!

Es gibt noch viele Details, die man beim Skalieren von Bildern berücksichtigen kann. Im oben verlinkten Artikel wird genauer auf diese Details eingegangen und verschiedene mögliche Strategien beim Skalieren besprochen, und die Ergebnisse mit Benchmarks und Testbildern verglichen. Aber schon die Frage, ob man Bilder in einem bestimmten Anwendungsfall eher skaliert zeichnen sollte, oder ob es besser wäre, eine skalierte Instanz eines Bildes zu erstellen, kann schwierig zu beantworten sein. Dieser Artikel soll nur die grundsätzlichen Unterschiede und Vorgehensweisen beschreiben, und hilft hoffentlich, zu verhindern, dass jemand vor jedem Zeichnen eines Bildes eine skalierte Instanz mit getScaledInstance erstellt....



Links