Bildverarbeitung in Java

Java ist keine Programmiersprache in der sich Bilder einfach manipulieren lassen. Dass es trotzdem geht und was nötig ist, soll dieser Artikel aufzeigen.
Zuerst muss man sich auch hier zuerst darüber Klar werden, was man will. Ich habe gefunden, dass es drei Ansätze gibt von denen ich zwei auf meine Problematik anwenden kann. Ausgangslage ist hierbei immer ein Bild mit einer fixen Dimension, das durch zusätzliche graphische Elemente aufgepeppt werden soll:

  1. Die zusätzlichen graphischen Elemente sind einfache Formen (Linien, Ellipsen, Rechtecke, Texte, …)
  2. Das resultierende Bild wird mit einem anderen Bild gleicher Dimension ergänzt.
  3. Das resultierende Bild wird mit Elementen aus einem anderen Bild ergänzt

Nun kommt die berechtigte Frage auf, was denn der Unterschied zwischen den beiden letzten Praktiken ist. Bei der ersten wird ein Bild mit einem anderen durch eine affine Transformation überlagert. Dies eignet sich jedoch nur wenn entweder alles von Bild A in B angezeigt werden soll, umgekehrt oder das eine Bild Transparent sein soll. Mit dieser Möglichkeit ist es nicht möglich beispielsweise ein in Bild B definiertes Polygon in A darzustellen, so dass die Fläche von A, die in Bild B nicht vom Polygon überdeckt ist, dargestellt wird. Man spricht hierbei von Blending image welches in dem gleichnamigen Artikel gut beschrieben wird. Diese Technik kann beispielsweise für Diashows oder für ein Wasserzeichen verwendet werden.
Das erste Verfahren eignet sich besonders, wenn einfache Strukturen das Bild ergänzen:

File f = new File(image2enhance);
image =ImageIO.read(f);
Graphics graphics = image.getGraphics();
graphics.setColor(Color.black);
Point start = new Point(0,25);
Point end = new Point(25,50);
graphics.drawLine(start.x, start.y, end.x, end.y);
String fileName = "someSillyFileName.png";
ImageIO.write(image, "PNG", new File(fileName));

Im Artikel Highlight ist dieser Mechanismus beschrieben.
Erst die dritte Methode lässt mehr Flexibilität zu. Der Einfachheit halber besitzt das Bild B, das den Artefakt enthält, der in Bild A hinzugefügt werden soll, dieselbe Dimensionen wie Bild A. Der Artefakt kann dann in Bild B entsprechend Positioniert werden. Als Hintergrundfarbe wird eine eindeutige Farbe gewählt, die im Artefakt nicht verwendet wird. Nun wird für jedes Pixel in Bild B überprüft, ob es sich um die Hintergrundfarbe handelt oder der Pixel zum Artefakt gehört. In letzterem Fall wird der Pixel in Bild A eingetragen. Auf diese Weise können auch komplexere Bedingungen erfüllt werden, z.B. Zeichne den Pixel nur wenn der entsprechende Pixel in Bild A eine bestimmte Farbe (nicht) hat.

private BufferedImage image=null;
public void createEnhancedImage(){
try {
try {
image =ImageIO.read(new File("backgroundFile.png"));
} catch (IOException e) {
e.printStackTrace();
}
BufferedImage bi = ImageIO.read(new File("baseFile.png"));
handlepixels(bi, 0, 0, 50, 50);
ImageIO.write(image, "PNG", new File("newFileName.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
private void handlepixels(Image img, int x, int y, int w, int h) {
int[] pixels = new int[w * h];
PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w);
try {
pg.grabPixels();
} catch (InterruptedException e) {
System.err.println("interrupted waiting for pixels!");
return;
}
if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
System.err.println("image fetch aborted or errored");
return;
}
for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { handlesinglepixel(x+i, y+j, pixels[j * w + i]); } } } private void handlesinglepixel(int x, int y, int pixel) { // int alpha = (pixel >> 24) & 0xff;
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel ) & 0xff;
Color col = new Color(red,green,blue);
if (col.getBlue()==0 && col.getGreen()==0 && col.getRead()==0){
} else {
// color is not black
// replace the pixel (x,y) in background with a pixel of color col
drawPixel(x, y, col);
}
}
private void drawPixel(int x, int y, Color col){
Graphics graphics = image.getGraphics();
graphics.setColor(col);
graphics.drawLine(x, y, x, y);
}

Schreibe einen Kommentar