001
24.03.2008, 10:09 Uhr
~MartinF
Gast
|
Hallo,
ich bin zur Zeit dabei Java zu lernen (hab vor Jahren mit C und C++ angefangen). Also habe ich mich an die Aufgabe gewagt. Hier die Lösung:
C++: |
package de.martin.fill;
import java.awt.Color; import java.awt.Point; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO;
public class FillApp { private BufferedImage image;
public FillApp(File f) throws IOException { // Bild einlesen BufferedImage is = ImageIO.read(f);
/* * is.setRGB(0, 0, Color.RED.getRGB()) würde eine * UnsupportedOperationException werfen. Weshalb? * * Wird das Bild zuerst kopiert, dann klappt alles. Geht das auch ohne * diesen Umweg? */
// Hier wird das Bild kopiert final int w = is.getWidth(); final int h = is.getHeight(); image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < w; ++x) for (int y = 0; y < h; ++y) image.setRGB(x, y, is.getRGB(x, y)); }
/* * Sucht ein Pixel mit der Farbe color und einem benachbarten Pixel der * Farbe outline. */ private Point findPixel(int color, int outline) { /* * Das ist nicht der schnellste Weg ... :) */ for (int x = 0; x < image.getWidth(); ++x) for (int y = 0; y < image.getHeight(); ++y) if (image.getRGB(x, y) == color && (image.getRGB(x + 1, y) == outline || image.getRGB(x - 1, y) == outline || image.getRGB(x, y + 1) == outline || image .getRGB(x, y - 1) == outline)) return new Point(x, y); return null; }
/* * Algorithmus zur Flutfüllung */ public void start(int color, int outline, int newColor) { FloodfillAlgorithm proc = new FloodfillAlgorithm(image);
Point p = findPixel(color, outline); while (p != null) { proc.start(p, newColor); p = findPixel(color, outline); } }
/* * save speichert das bearbeitete Bild */ public void save(File f) throws IOException { ImageIO.write(image, "png", f); }
public static void main(String[] args) { try { // Die Pfade müssen angepasst werden !! FillApp app = new FillApp(new File("/home/martin/tmp/bild.gif")); app.start(Color.white.getRGB(), Color.black.getRGB(), Color.red.getRGB()); app.save(new File("/home/martin/tmp/out.png")); System.out.println("fertig"); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } }
|
C++: |
package de.martin.fill;
import java.awt.Point; import java.awt.image.BufferedImage; import java.util.Stack;
public class FloodfillAlgorithm { private BufferedImage image;
public FloodfillAlgorithm(BufferedImage image) { this.image = image; }
public void start(Point p, int newColor) { int color = image.getRGB(p.x, p.y);
Stack v = new Stack(); v.push(p);
while (!v.empty()) { p = (Point) v.pop();
if (image.getRGB(p.x, p.y) == color) { image.setRGB(p.x, p.y, newColor);
v.push(new Point(p.x, p.y + 1)); v.push(new Point(p.x, p.y - 1)); v.push(new Point(p.x + 1, p.y)); v.push(new Point(p.x - 1, p.y)); } } }
}
|
Der Algorithmus an sich ist nicht schwierig - im Netz finden sich genug Informationen.
Den Quelltext finde ich so noch nicht sehr schön. Es gibt einige Stellen, wo ich noch etwas verbessern würde aber leider nicht weiß wie (da fehlt mir noch das notwendige Verständnis von der umfangreichen Standardbibliothek). Vielleicht können die Java-Experten mal einen Blick drauf werfen? ...
Hoffe ich konnte weiterhelfen. Mir jedenfalls hat die Aufgabe viel gebracht. ;)
Grüße Martin |