Initial sharing of project
|  | @ -0,0 +1,81 @@ | |||
| import java.util.ArrayList; | ||||
| import java.io.File; | ||||
| import java.awt.Color; | ||||
| import java.awt.image.BufferedImage; | ||||
| import javax.imageio.ImageIO; | ||||
| 
 | ||||
| /** | ||||
|  * Beschreiben Sie hier die Klasse Image. | ||||
|  *  | ||||
|  * @author Alexander Kimmig  | ||||
|  * @version 1.0 | ||||
|  */ | ||||
| public class Image | ||||
| { | ||||
|     /** | ||||
|      * Liest eine JPG-Bilddatei ein und gibt diese als ArrayList von RGB-Objekten zurück | ||||
|      *  | ||||
|      * @param filename Dateiname die eingelesen werden soll | ||||
|      * @return ArrayList<RGB> der einzelnen Pixelwerte | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public static ArrayList<RGB> readFile(String filename) throws Exception { | ||||
|         ArrayList<RGB> points = new ArrayList<>(); | ||||
|          | ||||
|         File file= new File(filename); | ||||
|         BufferedImage img = ImageIO.read(file); | ||||
|         for (int y = 0; y < img.getHeight(); y++) { | ||||
|             for (int x = 0; x < img.getWidth(); x++) { | ||||
|                 points.add(new RGB(img.getRGB(x,y))); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         return points; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Schreibt die RGB-Daten in eine Datei | ||||
|      *  | ||||
|      * @param input Dateiname der ursprünglichen Datei (wird für Dimensionen gebraucht) | ||||
|      * @param output Dateiname der neuen Datei | ||||
|      * @param data RGB-Daten der einzelnen Pixel | ||||
|      */ | ||||
|     public static void writeFile(String input, String output, ArrayList<RGB> data) throws Exception { | ||||
|         File file = new File(input); | ||||
|         BufferedImage img = ImageIO.read(file); | ||||
|          | ||||
|         int w = img.getWidth(); | ||||
|         int y = 0, x = 0; | ||||
|         for (RGB p : data) { | ||||
|             img.setRGB(x, y, p.toInt()); | ||||
|             if (++x >= w) { | ||||
|                 x = 0; | ||||
|                 ++y; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         File f = new File(output); | ||||
|         ImageIO.write(img, "jpg", f); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Schreibt die RGB-Daten in eine Datei anhand der Quantifizierungs-Punkte | ||||
|      * Jeder Pixel bekommt die Farbe des nächstliegenden Quantifizierungs-Punktes. | ||||
|      *  | ||||
|      * @param input Dateiname der ursprünglichen Datei (wird für Dimensionen gebraucht) | ||||
|      * @param output Dateiname der neuen Datei | ||||
|      * @param data RGB-Daten der einzelnen Pixel | ||||
|      * @param quants Quantifizierungs-Punkte | ||||
|      */ | ||||
|     public static void writeFile(String input, String target, ArrayList<RGB> data, ArrayList<RGB> quants) throws Exception { | ||||
|         ArrayList<RGB> q = new ArrayList<>(); | ||||
|          | ||||
|         // Mappe punkte auf quantifizierte Punkte
 | ||||
|         for (RGB p : data) { | ||||
|             q.add(Quant.findNearest(quants, p)); | ||||
|         } | ||||
|          | ||||
|         // schreibe Datei
 | ||||
|         writeFile(input, target, q); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,200 @@ | |||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| 
 | ||||
| /** | ||||
|  * Funktionen, um quantifizierungs-Punkte zu finden | ||||
|  *  | ||||
|  * @author Alexander Kimmig | ||||
|  * @version 1.0 | ||||
|  */ | ||||
| public class Quant | ||||
| { | ||||
|     /** | ||||
|      * Führt eine vollständige RGB-Qunatfizierung durch, Lädt die Datei | ||||
|      * input.jpg im Projektordner und speichert das Ergebnis in output.jpg | ||||
|      *  | ||||
|      * @param count Anzahl, wie viele Quantifizierungs-Punkte gefunden werden solle | ||||
|      * @param epoch Anzahl, wie viele Epochen durchlaufen werden sollen | ||||
|      * @throws Exception falls Datei nicht existiert | ||||
|      */ | ||||
|     public static void quantize(int count, int epoch) throws Exception { | ||||
|         ArrayList<RGB> ipoints = Image.readFile("./input.jpg"); | ||||
| 
 | ||||
|         ArrayList<RGB> quants = findQuants(count, epoch, ipoints); | ||||
| 
 | ||||
|         for (int i = 0; i < ipoints.size(); i++) { | ||||
|             RGB p = ipoints.get(i); | ||||
|             RGB t = findNearest(quants, p); | ||||
|             p.r = t.r; | ||||
|             p.g = t.g; | ||||
|             p.b = t.b; | ||||
|         } | ||||
|          | ||||
|         Image.writeFile("./input.jpg", "./output.jpg", ipoints); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Findet Quantenpunkte | ||||
|      *  | ||||
|      * @param count Anzahl, wie viele Quantifizierungs-Punkte gefunden werden solle | ||||
|      * @param epoch Anzahl, wie viele Epochen durchlaufen werden sollen | ||||
|      * @param ipoints RGB-Datenpunkte des Bildes | ||||
|      *  | ||||
|      * @return ArrayList<RGB> mit den Quantenpunkten  | ||||
|      * @throws Exception falls Datei nicht existiert | ||||
|      */ | ||||
|     public static ArrayList<RGB> findQuants(int count, int epoch, ArrayList<RGB> ipoints) throws Exception { | ||||
|         ArrayList<RGB> qpoints = new ArrayList<>(); | ||||
|          | ||||
|         // Füge neue, zufällige Punkte hinzu
 | ||||
|         for (int i = 0; i < count; i++) { | ||||
|             qpoints.add(new RGB(true)); | ||||
|         } | ||||
|          | ||||
|         for (int i = 0; i < epoch; i++) { | ||||
|             // Epoche durchlaufen
 | ||||
|             doEpoch(ipoints, qpoints); | ||||
|             // nich bewegte Quantenpunkte versetzen
 | ||||
|             if (i < epoch-1) resetQuants(qpoints); | ||||
|         } | ||||
|          | ||||
|         return qpoints; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Epoche durchlaufen | ||||
|      *  | ||||
|      * @param ipoints RGB-Bildpunkte | ||||
|      * @param qpoints bisherige Quantenpunkte -> werden direkt verändert | ||||
|      */ | ||||
|     public static void doEpoch(ArrayList<RGB> ipoints, ArrayList<RGB> qpoints) { | ||||
|         /* | ||||
|          * WICHTIG: Bildpunkte mischen, da ansonsten die Punkte linear durchgegangen werden. | ||||
|          * Bei großen Flächen am Ende (rechts unten) werden sonst viele Quantenpunkte in diesen | ||||
|          * Bereich gezogen | ||||
|          *  | ||||
|          * Ausprobieren: deaktivieren und das Beispielbild "sonnenaufgang" | ||||
|          */ | ||||
|         Collections.shuffle(ipoints); | ||||
|          | ||||
|         /* | ||||
|          * Eine Epoche: alle Bildpunkte einmal durchlaufen | ||||
|          */ | ||||
|         for (RGB t : ipoints) { | ||||
|             // jeweils den nächstliegenden Quantenpunkt finden
 | ||||
|             RGB q = findNearest(qpoints, t); | ||||
|              | ||||
|             // gegangener Weg speichern
 | ||||
|             q.walk += t.diff2(q); | ||||
|             q.count++; | ||||
|              | ||||
|             // den Punkt verschieben
 | ||||
|             q.r = (q.r + t.r) / 2; | ||||
|             q.g = (q.g + t.g) / 2; | ||||
|             q.b = (q.b + t.b) / 2; | ||||
|         } | ||||
|          | ||||
|         for (RGB tmp : qpoints) { | ||||
|             // falls Punkt verschoben: berechne mittlere gegangene Weglänge
 | ||||
|             if (tmp.count > 0) { | ||||
|                 tmp.walk = Math.max(1, tmp.walk / tmp.count); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Versetzt die Quantenpunkte, die im letzten Schritt nicht versetzt wurden, d.h. | ||||
|      * diejenigen, die zu weit von der Punktwolke entfernt sind. | ||||
|      *  | ||||
|      * Hierfür setze diejenigen, die nicht gegangen sind in die Nähe derjeniger Punkte, | ||||
|      * die besonders weit gelaufen sind (da dort ggf. underfitted) | ||||
|      *  | ||||
|      * @param qpoints Quantenpunkte | ||||
|      * @return int wie viele Punkte wurden versetzt | ||||
|      */ | ||||
|     public static int resetQuants(ArrayList<RGB> qpoints) { | ||||
|         int reset = 0; | ||||
|         for (int i = 0; i < qpoints.size(); i++) { | ||||
|             // finde denjenigen Punkt, der am wenigsten gelaufen ist
 | ||||
|             RGB min = findMinWalk(qpoints); | ||||
|             // wenn es keinen gibt oder dieser auch weit gelaufen ist, dann breche ab
 | ||||
|             if (min == null || min.walk > 5) break; | ||||
|              | ||||
|             // finde denjenigen, der am weitesten gelaufen ist (dessen Bereich underfitted ist)
 | ||||
|             RGB max = findMaxWalk(qpoints); | ||||
|             // breche ab, falls dieser insgesamt auch sehr wenig gelaufen ist
 | ||||
|             if (max.walk < 25) break; | ||||
|              | ||||
|             // passe den Wert an, damit dieser beim nächsten Schleifendurchlauf nicht mehr direkt gefunden wird
 | ||||
|             max.walk -= 36; | ||||
|              | ||||
|             // setze den Nichtläufer zum Weitläufer
 | ||||
|             min.setTo(max); | ||||
|             // und variiere dessen Positionen um maximal ±5
 | ||||
|             min.jitter(5); | ||||
|             // walk = -1 -> nicht mehr weiter in diesem Durchlauf betrachten (nicht mehr als Minimum finden)
 | ||||
|             min.walk = -1; | ||||
|             // zähle die Anzahl der versetzten Punkte
 | ||||
|             reset++; | ||||
|         } | ||||
|          | ||||
|         // setze gelaufene Wege aller Punkte zurück
 | ||||
|         for (RGB q : qpoints) { | ||||
|             q.walk = q.count = 0; | ||||
|         } | ||||
|          | ||||
|         return reset; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Finde denjenigen Punkt in der Liste, der am wenigsten weit gelaufen ist | ||||
|      *  | ||||
|      * @param quants Punktliste | ||||
|      * @return RGB der Punkt, der am wenigsten gelaufen ist oder null | ||||
|      */ | ||||
|     private static RGB findMinWalk(ArrayList<RGB> quants) { | ||||
|         RGB min = null; | ||||
|         for (RGB tmp : quants) { | ||||
|             if (tmp.walk >= 0 && (min == null || tmp.walk < min.walk)) { | ||||
|                 min = tmp; | ||||
|             } | ||||
|         } | ||||
|         return min; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Finde denjenigen Punkt in der Liste, der am weitesten gelaufen ist | ||||
|      *  | ||||
|      * @param quants Punktliste | ||||
|      * @return RGB der Punkt, der am weitesten gelaufen ist | ||||
|      */ | ||||
|     private static RGB findMaxWalk(ArrayList<RGB> quants) { | ||||
|         RGB max = quants.get(0); | ||||
|         for (RGB q : quants) { | ||||
|             if (q.walk > max.walk) max = q; | ||||
|         } | ||||
|         return max; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Finde den Punkt in der Liste der die kürzeste Distanz zum Zielpunkt hat | ||||
|      *  | ||||
|      * @param points Liste der Punkte | ||||
|      * @param target Zielpunkt | ||||
|      * @return RGB Punkt mit kürzestem Abstand | ||||
|      */ | ||||
|     public static RGB findNearest(ArrayList<RGB> points, RGB target) { | ||||
|         RGB nearest = points.get(0); | ||||
|         int mind = target.diff2(nearest); | ||||
|          | ||||
|         for (RGB p : points) { | ||||
|             int d = target.diff2(p); | ||||
|             if (d < mind) { | ||||
|                 nearest = p; | ||||
|                 mind = d; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         return nearest; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,14 @@ | |||
| ------------------------------------------------------------------------ | ||||
| Dies ist die README-Datei des Projekts. Hier sollten Sie Ihr Projekt | ||||
| beschreiben. | ||||
| Erzählen Sie dem Leser (jemand, der nichts über dieses Projekt weiss), | ||||
| alles, was er/sie wissen muss. Üblicherweise sollte der Kommentar  | ||||
| zumindest die folgenden Angaben umfassen: | ||||
| ------------------------------------------------------------------------ | ||||
| 
 | ||||
| PROJEKTBEZEICHNUNG: | ||||
| PROJEKTZWECK: | ||||
| VERSION oder DATUM: | ||||
| WIE IST DAS PROJEKT ZU STARTEN: | ||||
| AUTOR(EN): | ||||
| BENUTZERHINWEISE: | ||||
|  | @ -0,0 +1,161 @@ | |||
| import java.awt.Color; | ||||
| 
 | ||||
| /** | ||||
|  * Repräsentiert einen Punkt im RGB-Raum | ||||
|  *  | ||||
|  * @author Alexander Kimmig  | ||||
|  * @version 1.0 | ||||
|  */ | ||||
| public class RGB | ||||
| { | ||||
|     /** | ||||
|      * Rot-Anteil 0-255 | ||||
|      */ | ||||
|     public int r; | ||||
|      | ||||
|     /** | ||||
|      * Grün-Anteil 0-255 | ||||
|      */ | ||||
|     public int g; | ||||
|      | ||||
|     /** | ||||
|      * Blau-Anteil 0-255 | ||||
|      */ | ||||
|     public int b; | ||||
|      | ||||
|     /** | ||||
|      * Wie weit ist der Punkt in der letzten Epoche gelaufen | ||||
|      */ | ||||
|     public int walk; | ||||
|      | ||||
|     /** | ||||
|      * Wie oft ist der Punkt in der letzten Epoche gelaufen | ||||
|      */ | ||||
|     public int count; | ||||
|      | ||||
|     /** | ||||
|      * Konstruktor | ||||
|      *  | ||||
|      * @param random Punkt zufällig setzen | ||||
|      */ | ||||
|     public RGB(boolean random) { | ||||
|         this(0, 0, 0); | ||||
|          | ||||
|         if (random) this.setRandom(); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Konstruktor | ||||
|      *  | ||||
|      * @param c ein awt.Color-Wert | ||||
|      */ | ||||
|     public RGB(Color c) { | ||||
|         this(c.getRed(), c.getGreen(), c.getBlue()); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Konstruktor | ||||
|      *  | ||||
|      * @param c ein int-Wert 0xRRGGBB | ||||
|      */ | ||||
|     public RGB(int c) { | ||||
|         this(c >> 16 & 0xFF, c >> 8 & 0xFF, c & 0xFF); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Konstruktor | ||||
|      *  | ||||
|      * @param r Rot-Anteil 0-255 | ||||
|      * @param g Grün-Anteil 0-255 | ||||
|      * @param b Blau-Anteil 0-255 | ||||
|      */ | ||||
|     public RGB(int r, int g, int b) { | ||||
|         this.r = Math.min(255, Math.max(0, r)); | ||||
|         this.g = Math.min(255, Math.max(0, g)); | ||||
|         this.b = Math.min(255, Math.max(0, b)); | ||||
|          | ||||
|         this.walk = 0; | ||||
|         this.count = 0; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Kopier-Konstruktor | ||||
|      */ | ||||
|     public RGB(RGB copy) { | ||||
|         this(copy.r, copy.g, copy.b); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Ausgabe als String | ||||
|      *  | ||||
|      * @return String: "R, G, B" | ||||
|      */ | ||||
|     public String toString() { | ||||
|         return this.r + "," + this.g + "," + this.b; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Ausgabe als awt.Color | ||||
|      *  | ||||
|      * @return awt.Color | ||||
|      */ | ||||
|     public Color toColor() { | ||||
|         return new Color(this.r, this.g, this.b); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Ausgabe als int | ||||
|      */ | ||||
|     public int toInt() { | ||||
|         return (this.r << 16) + (this.g << 8) + (this.b); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Setze zufällige Koordinaten | ||||
|      */ | ||||
|     public void setRandom() { | ||||
|         this.r = (int)(Math.random() * 256); | ||||
|         this.g = (int)(Math.random() * 256); | ||||
|         this.b = (int)(Math.random() * 256); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Setze Koordinaten | ||||
|      */ | ||||
|     public void setTo(RGB p) { | ||||
|         this.r = p.r; | ||||
|         this.g = p.g; | ||||
|         this.b = p.b; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Variiere Koordinaten ±max | ||||
|      *  | ||||
|      * @param max maximale verschiebung pro Achse | ||||
|      */ | ||||
|     public void jitter(int max) { | ||||
|         this.r = Math.min(255, Math.max(0, this.r + ((int)(Math.random() * max * 2 - max)))); | ||||
|         this.g = Math.min(255, Math.max(0, this.g + ((int)(Math.random() * max * 2 - max)))); | ||||
|         this.b = Math.min(255, Math.max(0, this.b + ((int)(Math.random() * max * 2 - max)))); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Berechne den quadratischen Abstand zweier Punkte | ||||
|      *  | ||||
|      * @param a erster Punkt | ||||
|      * @param b zweiter Punkt | ||||
|      */ | ||||
|     public static int diff2(RGB a, RGB b) { | ||||
|         int dr = a.r - b.r; | ||||
|         int dg = a.g - b.g; | ||||
|         int db = a.b - b.b; | ||||
|         return dr*dr + dg*dg + db*db; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Berechne den quadratischen Abstand zu einem anderen Punkt | ||||
|      */ | ||||
|     public int diff2(RGB b) { | ||||
|         return RGB.diff2(this, b); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,251 @@ | |||
| import ChartDirector.*; | ||||
| import javax.swing.*; | ||||
| import java.awt.*; | ||||
| import java.awt.event.*; | ||||
| import java.util.ArrayList; | ||||
| import java.io.File; | ||||
| import java.util.Collections; | ||||
| 
 | ||||
| /** | ||||
|  * Zeigt das Fenster an mit allen Komponenten | ||||
|  *  | ||||
|  * @author Alexander Kimmig  | ||||
|  * @version 1.0 | ||||
|  */ | ||||
| public class Window implements ActionListener | ||||
| { | ||||
|     private JFrame frame; | ||||
|     private JPanel drawPanel; | ||||
|      | ||||
|     private ArrayList<RGB> image; | ||||
|     private ArrayList<RGB> orig; | ||||
|     private ArrayList<RGB> quants; | ||||
|      | ||||
|     private int alpha = 25; | ||||
|     private int beta = 45; | ||||
|      | ||||
|     private JButton vl; | ||||
|     private JButton vr; | ||||
|     private JButton vu; | ||||
|     private JButton vd; | ||||
|      | ||||
|     private JButton b_load; | ||||
|     private JButton b_gen; | ||||
|     private JButton b_epoc; | ||||
|     private JButton b_reset; | ||||
|     private JButton b_save; | ||||
| 
 | ||||
|     private JComboBox s_input; | ||||
|     private JTextField t_anz; | ||||
|     private JTextField t_output; | ||||
|      | ||||
|     /** | ||||
|      * Konstruktor: legt JFrame und alle Panels/Buttons an | ||||
|      */ | ||||
|     public Window() | ||||
|     { | ||||
|         frame = new JFrame(); | ||||
|         frame.addWindowListener(new WindowAdapter() { | ||||
|             public void windowClosing(WindowEvent e) { System.exit(0); } | ||||
|         }); | ||||
|          | ||||
|         JPanel mainPanel = new JPanel(); | ||||
|         mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); | ||||
|          | ||||
|         drawPanel = new JPanel(); | ||||
|         drawPanel.setPreferredSize(new Dimension(1000, 1000)); | ||||
|         drawPanel.setBackground(new Color(0xFFFFFF)); | ||||
|         JPanel view = new JPanel(); | ||||
|         JPanel steps = new JPanel(); | ||||
|         JPanel config = new JPanel(); | ||||
| 
 | ||||
|         mainPanel.add(drawPanel); | ||||
|         mainPanel.add(view); | ||||
|         mainPanel.add(steps); | ||||
|         mainPanel.add(config); | ||||
|          | ||||
|         vl = new JButton("<"); | ||||
|         vl.addActionListener(this); | ||||
|         view.add(vl); | ||||
|         vr = new JButton(">"); | ||||
|         vr.addActionListener(this); | ||||
|         view.add(vr); | ||||
|         vu = new JButton("^"); | ||||
|         vu.addActionListener(this); | ||||
|         view.add(vu); | ||||
|         vd = new JButton("v"); | ||||
|         vd.addActionListener(this); | ||||
|         view.add(vd); | ||||
|          | ||||
|         b_load = new JButton("Datei laden"); | ||||
|         b_load.addActionListener(this); | ||||
|         steps.add(b_load); | ||||
|          | ||||
|         b_gen = new JButton("Zufällige Punkte erzeugen"); | ||||
|         b_gen.addActionListener(this); | ||||
|         steps.add(b_gen); | ||||
| 
 | ||||
|         b_epoc = new JButton("Epoche durchspielen"); | ||||
|         b_epoc.addActionListener(this); | ||||
|         steps.add(b_epoc); | ||||
| 
 | ||||
|         b_reset = new JButton("Punkte versetzen"); | ||||
|         b_reset.addActionListener(this); | ||||
|         steps.add(b_reset); | ||||
|          | ||||
|         b_save = new JButton("Datei speichern"); | ||||
|         b_save.addActionListener(this); | ||||
|         steps.add(b_save); | ||||
|          | ||||
|         config.add(new JLabel("Input:")); | ||||
|         s_input = new JComboBox(getJPGs()); | ||||
|         config.add(s_input); | ||||
| 
 | ||||
|         config.add(new JLabel("Anzahl Punkte:")); | ||||
|         t_anz = new JTextField("32"); | ||||
|         t_anz.setPreferredSize(new Dimension(100,20)); | ||||
|         config.add(t_anz); | ||||
| 
 | ||||
|         config.add(new JLabel("Output:")); | ||||
|         t_output = new JTextField("output.jpg"); | ||||
|         t_output.setPreferredSize(new Dimension(100,20)); | ||||
|         config.add(t_output); | ||||
| 
 | ||||
|         frame.add(mainPanel); | ||||
| 
 | ||||
|         frame.pack(); | ||||
|         frame.setVisible(true); | ||||
|          | ||||
|         this.image = new ArrayList<>(); | ||||
|         this.quants = new ArrayList<>(); | ||||
|          | ||||
|         this.plot(); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * plottet die Punkte in ein 3D-Scatter-Plot und zeigt dieses an | ||||
|      */ | ||||
|     public void plot() | ||||
|     { | ||||
|         ChartViewer viewer = new ChartViewer(); | ||||
|          | ||||
|         // Einstellungen setzen
 | ||||
|         ThreeDScatterChart c = new ThreeDScatterChart(1000, 1000); | ||||
|         c.setPlotRegion(500, 480, 600, 600, 450); | ||||
|         c.xAxis().setTitle("R", "Arial Bold", 10); | ||||
|         c.yAxis().setTitle("G", "Arial Bold", 10); | ||||
|         c.zAxis().setTitle("B", "Arial Bold", 10); | ||||
|         c.xAxis().setDateScale(0, 255); | ||||
|         c.yAxis().setDateScale(0, 255); | ||||
|         c.zAxis().setDateScale(0, 255); | ||||
|         c.setViewAngle(alpha, beta); | ||||
|          | ||||
|         // Bildpunkte
 | ||||
|         double[] x = new double[image.size()]; | ||||
|         double[] y = new double[image.size()]; | ||||
|         double[] z = new double[image.size()]; | ||||
|         for (int i = 0; i < image.size(); i++) { | ||||
|             x[i] = image.get(i).r; | ||||
|             y[i] = image.get(i).g; | ||||
|             z[i] = image.get(i).b; | ||||
|         } | ||||
|         //               Koordinaten    Form        Größe  Farbe ARGB  Rahmen ARGB
 | ||||
|         c.addScatterGroup(x,y,z, "", Chart.CircleShape, 5, 0xE0FF0000, 0xFF000000); | ||||
|          | ||||
|         // Quantenpunkte
 | ||||
|         x = new double[quants.size()]; | ||||
|         y = new double[quants.size()]; | ||||
|         z = new double[quants.size()]; | ||||
|         for (int i = 0; i < quants.size(); i++) { | ||||
|             x[i] = quants.get(i).r; | ||||
|             y[i] = quants.get(i).g; | ||||
|             z[i] = quants.get(i).b; | ||||
|         } | ||||
|         c.addScatterGroup(x,y,z, "", Chart.CircleShape, 12); | ||||
|          | ||||
|         viewer.setChart(c); | ||||
|          | ||||
|         drawPanel.removeAll(); | ||||
|         drawPanel.add(viewer); | ||||
|          | ||||
|         frame.pack(); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Lies die vorhandenen JPG-Dateien aus dem Ordner inputs aus | ||||
|      *  | ||||
|      * @return String[] Dateinamen | ||||
|      */ | ||||
|     private String[] getJPGs() { | ||||
|         ArrayList<String> result = new ArrayList<String>(); | ||||
|          | ||||
|         File d = new File("./inputs/"); | ||||
|         File[] list = d.listFiles(); | ||||
|         for(int i=0; i<list.length; i++) { | ||||
|             String n = list[i].getName(); | ||||
|             // nur JPG-Bilder
 | ||||
|             if (n.matches(".*\\.[jJ][pP][eE]?[gG]$")) { | ||||
|                 result.add(n); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         String[] ret = new String[result.size()]; | ||||
|         return result.toArray(ret); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Button-Reaktivität | ||||
|      *  | ||||
|      * @param e ActionEvent | ||||
|      */ | ||||
|     public void actionPerformed(ActionEvent e) { | ||||
|         /** | ||||
|          * Pfeilbuttons: Ändern der Ansicht | ||||
|          */ | ||||
|         if (e.getSource() == this.vr) beta = (beta + 345) % 360; | ||||
|         if (e.getSource() == this.vl) beta = (beta + 15) % 360; | ||||
|         if (e.getSource() == this.vu) alpha = (alpha + 345) % 360; | ||||
|         if (e.getSource() == this.vd) alpha = (alpha + 15) % 360; | ||||
|          | ||||
|         /** | ||||
|          * Datei laden und RGB-Daten in ArrayList speichern | ||||
|          */ | ||||
|         if (e.getSource() == this.b_load) { | ||||
|             try { | ||||
|                 this.orig = Image.readFile("./inputs/" + (String)this.s_input.getSelectedItem()); | ||||
|                 for (RGB p : this.orig) { | ||||
|                     // kopiere die originalen Daten, damit die Liste später gemischt werden kann
 | ||||
|                     this.image.add(p); | ||||
|                 } | ||||
|             } catch (Exception ex) {} | ||||
|         } | ||||
|         /** | ||||
|          * Zufällige Punkte erzeugen | ||||
|          */ | ||||
|         if (e.getSource() == this.b_gen) { | ||||
|             this.quants = new ArrayList<>(); | ||||
|             for (int i = 0; i < Integer.parseInt(this.t_anz.getText()); i++) { | ||||
|                 this.quants.add(new RGB(true)); | ||||
|             } | ||||
|         } | ||||
|         /** | ||||
|          * Epoche durchlaufen | ||||
|          */ | ||||
|         if (e.getSource() == this.b_epoc) Quant.doEpoch(this.image, this.quants); | ||||
|         /** | ||||
|          * Nicht bewegte Punkte versetzen | ||||
|          */ | ||||
|         if (e.getSource() == this.b_reset) Quant.resetQuants(this.quants); | ||||
|         /** | ||||
|          * quantifiziertes Bild speichern | ||||
|          */ | ||||
|         if (e.getSource() == this.b_save) { | ||||
|             try { | ||||
|                 Image.writeFile("./inputs/" + (String)this.s_input.getSelectedItem(), "./outputs/" + this.t_output.getText(), this.orig, this.quants); | ||||
|             } catch (Exception ex) {} | ||||
|         } | ||||
| 
 | ||||
|         // neue Anzeige rendern
 | ||||
|         this.plot(); | ||||
|     } | ||||
| } | ||||
| After Width: | Height: | Size: 145 KiB | 
| After Width: | Height: | Size: 72 KiB | 
| After Width: | Height: | Size: 204 KiB | 
| After Width: | Height: | Size: 16 KiB | 
| After Width: | Height: | Size: 122 KiB | 
| After Width: | Height: | Size: 43 KiB | 
| After Width: | Height: | Size: 63 KiB | 
| After Width: | Height: | Size: 30 KiB | 
| After Width: | Height: | Size: 30 KiB | 
| After Width: | Height: | Size: 88 KiB | 
| After Width: | Height: | Size: 88 KiB | 
| After Width: | Height: | Size: 45 KiB | 
| After Width: | Height: | Size: 64 KiB | 
| After Width: | Height: | Size: 62 KiB | 
| After Width: | Height: | Size: 70 KiB | 
| After Width: | Height: | Size: 78 KiB | 
| After Width: | Height: | Size: 86 KiB | 
| After Width: | Height: | Size: 56 KiB | 
| After Width: | Height: | Size: 57 KiB | 
| After Width: | Height: | Size: 47 KiB | 
| After Width: | Height: | Size: 54 KiB | 
| After Width: | Height: | Size: 1.4 MiB | 
| After Width: | Height: | Size: 15 KiB | 
| After Width: | Height: | Size: 12 KiB | 
|  | @ -0,0 +1,74 @@ | |||
| #BlueJ package file | ||||
| dependency1.from=Image | ||||
| dependency1.to=RGB | ||||
| dependency1.type=UsesDependency | ||||
| dependency2.from=Image | ||||
| dependency2.to=Quant | ||||
| dependency2.type=UsesDependency | ||||
| dependency3.from=Quant | ||||
| dependency3.to=RGB | ||||
| dependency3.type=UsesDependency | ||||
| dependency4.from=Quant | ||||
| dependency4.to=Image | ||||
| dependency4.type=UsesDependency | ||||
| dependency5.from=Window | ||||
| dependency5.to=RGB | ||||
| dependency5.type=UsesDependency | ||||
| dependency6.from=Window | ||||
| dependency6.to=Image | ||||
| dependency6.type=UsesDependency | ||||
| dependency7.from=Window | ||||
| dependency7.to=Quant | ||||
| dependency7.type=UsesDependency | ||||
| editor.fx.0.height=0 | ||||
| editor.fx.0.width=0 | ||||
| editor.fx.0.x=0 | ||||
| editor.fx.0.y=0 | ||||
| objectbench.height=100 | ||||
| objectbench.width=595 | ||||
| package.divider.horizontal=0.599601593625498 | ||||
| package.divider.vertical=0.8102836879432624 | ||||
| package.editor.height=450 | ||||
| package.editor.width=885 | ||||
| package.editor.x=0 | ||||
| package.editor.y=25 | ||||
| package.frame.height=628 | ||||
| package.frame.width=1024 | ||||
| package.numDependencies=7 | ||||
| package.numTargets=4 | ||||
| package.showExtends=true | ||||
| package.showUses=true | ||||
| project.charset=UTF-8 | ||||
| readme.height=60 | ||||
| readme.name=@README | ||||
| readme.width=48 | ||||
| readme.x=10 | ||||
| readme.y=10 | ||||
| target1.height=70 | ||||
| target1.name=Window | ||||
| target1.showInterface=false | ||||
| target1.type=ClassTarget | ||||
| target1.width=120 | ||||
| target1.x=150 | ||||
| target1.y=280 | ||||
| target2.height=70 | ||||
| target2.name=Image | ||||
| target2.showInterface=false | ||||
| target2.type=ClassTarget | ||||
| target2.width=120 | ||||
| target2.x=320 | ||||
| target2.y=190 | ||||
| target3.height=70 | ||||
| target3.name=RGB | ||||
| target3.showInterface=false | ||||
| target3.type=ClassTarget | ||||
| target3.width=120 | ||||
| target3.x=320 | ||||
| target3.y=10 | ||||
| target4.height=70 | ||||
| target4.name=Quant | ||||
| target4.showInterface=false | ||||
| target4.type=ClassTarget | ||||
| target4.width=120 | ||||
| target4.x=460 | ||||
| target4.y=100 | ||||