14.15 Filter
14.15.1 Grundlegende Eigenschaft von Filtern
ImageFilter liegen zwischen Produzenten und Konsumenten und verändern Bildinformationen oder nehmen Einfluss auf die Größe. Sie verhalten sich ähnlich wie ein Proxy, der zwischen Quelle und Ziel liegt. Für Produzenten treten die Filter als Konsumenten auf, da sie die Schnittstelle ImageConsumer implementieren und die wichtige Methode setPixel() ausprogrammieren.
Um einen Filter anzuwenden, nutzen wir die Klasse FilteredImageSource. Im Konstruktor geben wir das Bild und den Filter an. Anschließend können wir den zurückgegebenen Produzenten an createImage() übergeben, und wir haben ein neues Bild.
Beispiel Die Realisierung eines Filters
Image src = getImage( "gatesInAlbuquerque.jpg " );
ImageFilter colorfilter = new GrayFilter();
ImageProducer imageprod = new FilteredImageSource( src.getSource(), colorfilter );
Image img = createImage( imageprod );
|
Hier klicken, um das Bild zu Vergrößern
14.15.2 Konkrete Filterklassen
Es gibt einige Unterklassen der Klasse ImageFilter, die für unsere Arbeit interessant sind.
|
BufferedImageFilter
Diesem Filter lässt sich ein Objekt vom Typ BufferedImageOp übergeben, mit dem unterschiedliche Manipulationen ermöglicht werden. BufferedImageOp ist eine Schnittstelle, die von AffineTransformOp, ConvolveOp, BandCombineOp und LookupOp implementiert wird. AffineTransformOp ist am attraktivsten, da es mit einem AffineTransform konstruiert wird, so dass leicht Vergrößerungen oder Rotationen ermöglicht werden. Über AffineTransform-Objekte erfahren wir im 2D-Abschnitt mehr. |
|
CropImageFilter
Bildteile werden herausgeschnitten. |
Hier klicken, um das Bild zu Vergrößern
|
ReplicateScaleFilter
Zum Vergrößern oder Verkleinern von Bildern. Ein einfacher Algorithmus wird angewendet. Eine weiche Vergrößerung oder Verkleinerung lässt sich mit der Unterklasse AreaAveragingScaleFilter erreichen. |
|
RGBImageFilter
Dieser allgemeine Filter ist für die eigene Filterklasse gedacht. Wir müssen lediglich eine filterRGB()-Methode angeben, die die RGB-Bildinformationen für jeden Punkt (x,y) modifiziert. Benötigt der Filter auch die Nachbarpunkte, können wir nicht mit RGBImageFilter arbeiten. |
Hier klicken, um das Bild zu Vergrößern
Beispiel Ein Filter, der den Rot- und Blauanteil in einem Bild vertauscht.
class RedBlueSwapFilter extends RGBImageFilter
{
public RedBlueSwapFilter()
{
canFilterIndexColorModel = true;
}
public int filterRGB( int x, int y, int rgb )
{
return ( (rgb & 0xff00ff00)
| ((rgb & 0xff0000) >> 16)
| ((rgb & 0xff) << 16));
}
}
|
14.15.3 Mit CropImageFilter Teile ausschneiden
Mit CropImageFilter lassen sich Teile des Bilds ausschneiden. Wir definieren dafür vom Bild einen Ausschnitt mit den Koordinaten x, y und der Breite und Höhe. Wie die anderen Bildfilter, so wird auch CropImageFilter mit dem FilteredImageSource als Produzent verwendet.
Beispiel Erzeuge für die Grafik big.gif in einem Applet ein neues Image-Objekt.
Das Original hat die Größe 100 x 100 Pixel. Das neue Bild soll einen Rand von 10 Pixeln haben.
Image origImage = getImage( getDocumentBase(), "big.gif" );
ImageFilter cropFilter = new CropImageFilter( 10, 10, 90, 90 );
Image cropImage = createImage( new
FilteredImageSource(origImage.getSource(),cropFilter) );
|
Bildausschnitte über PixelGrabber ausschneiden
Nicht nur über CropImageFilter lassen sich Bildausschnitte auswählen. Eine andere Lösung geht über PixelGrabber, da dieser auch einen Ausschnitt erlaubt. Darüber lässt sich dann mit MemoryImageSource wieder ein neues Bild erzeugen.
Beispiel Schneide aus dem Image img das passende Rechteck mit den Startkoordinaten x, y und der Breite width und der Höhe height aus
int pix[] = new int[width * height];
PixelGrabber pg = new PixelGrabber( img, x, y, width, height,
pix, 0, width );
try {
pg.grabPixels();
}
catch( InterruptedException e ) {}
newImg = createImage(new MemoryImageSource(width, height, pix, 0, width) );
|
An dieser Stelle sollten wir noch einmal den Unterschied zwischen den beiden Möglichkeiten betonen. PixelGrabber implementiert die Schnittestelle ImageConsumer, so dass er ein Bildkonsument ist und Daten in einem Integer-Feld ablegt. CropImageFilter ist ein Filter, der ein anderes Image-Objekt konstruiert und kein Feld.
14.15.4 Transparenz
Um eine bestimmte Farbe eines Bilds durchsichtig zu machen (also die Transparenz zu bestimmen), nutzen wir einen RGBImageFilter. Dabei implementieren wir einen Konstruktor, der die Farbe sichert, die transparent werden soll. Sie wird später in der Implementierung von filterRGB() verwendet. Die Methode, die ja für jeden Bildpunkt aufgerufen wird, liefert dann entweder die Farbe ohne Alpha-Kanal zurück (rgb|0xff000000) oder eben nur den Alpha-Kanal (rgb&0xffffff) für Transparenz. Eine interessante Erweiterung ist die Einführung einer Toleranzauswertung um einen »Zauberstab«, der ähnlich wie in Photoshop zu realisieren ist.
Listing 14.21 TransparentFilter.java
import java.awt.*;
import java.awt.image.*;
public class TransparentFilter extends RGBImageFilter
{
public TransparentFilter( Color color )
{
this.color = color.getRGB();
}
public int filterRGB( int x, int y, int rgb )
{
if ( rgb != color )
return rgb | 0xff000000;
else
return rgb & 0xffffff; //transparent
}
private int color;
}
|