v1.1 noch ohne Kommentare
							parent
							
								
									35378ef3fe
								
							
						
					
					
						commit
						1a0376ec61
					
				
							
								
								
									
										26
									
								
								Image.java
								
								
								
								
							
							
						
						
									
										26
									
								
								Image.java
								
								
								
								
							|  | @ -33,14 +33,29 @@ public class Image | |||
|         return points; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Liest eine JPG-Bilddatei ein und gibt diese als ArrayList von RGB-Objekten zurück | ||||
|      *  | ||||
|      * @param filename Dateiname die eingelesen werden soll | ||||
|      * @return BufferedImage | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public static BufferedImage loadFile(String filename) throws Exception { | ||||
|         ArrayList<RGB> points = new ArrayList<>(); | ||||
|          | ||||
|         File file= new File(filename); | ||||
|         return ImageIO.read(file); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * 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 | ||||
|      * @return BufferedImage | ||||
|      */ | ||||
|     public static void writeFile(String input, String output, ArrayList<RGB> data) throws Exception { | ||||
|     public static BufferedImage writeFile(String input, String output, ArrayList<RGB> data) throws Exception { | ||||
|         File file = new File(input); | ||||
|         BufferedImage img = ImageIO.read(file); | ||||
|          | ||||
|  | @ -54,10 +69,14 @@ public class Image | |||
|             } | ||||
|         } | ||||
|          | ||||
|         if (output != "") { | ||||
|             File f = new File(output); | ||||
|             ImageIO.write(img, "jpg", f); | ||||
|         } | ||||
|          | ||||
|         return img; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Schreibt die RGB-Daten in eine Datei anhand der Quantifizierungs-Punkte | ||||
|      * Jeder Pixel bekommt die Farbe des nächstliegenden Quantifizierungs-Punktes. | ||||
|  | @ -66,8 +85,9 @@ public class Image | |||
|      * @param output Dateiname der neuen Datei | ||||
|      * @param data RGB-Daten der einzelnen Pixel | ||||
|      * @param quants Quantifizierungs-Punkte | ||||
|      * @return BufferedImage | ||||
|      */ | ||||
|     public static void writeFile(String input, String target, ArrayList<RGB> data, ArrayList<RGB> quants) throws Exception { | ||||
|     public static BufferedImage writeFile(String input, String target, ArrayList<RGB> data, ArrayList<RGB> quants) throws Exception { | ||||
|         ArrayList<RGB> q = new ArrayList<>(); | ||||
|          | ||||
|         // Mappe punkte auf quantifizierte Punkte
 | ||||
|  | @ -76,6 +96,6 @@ public class Image | |||
|         } | ||||
|          | ||||
|         // schreibe Datei
 | ||||
|         writeFile(input, target, q); | ||||
|         return writeFile(input, target, q); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,399 @@ | |||
| import com.jogamp.opengl.GL2; | ||||
| import com.jogamp.opengl.glu.GLU; | ||||
| import com.jogamp.opengl.GLAutoDrawable; | ||||
| import com.jogamp.opengl.GLCapabilities; | ||||
| import com.jogamp.opengl.GLEventListener; | ||||
| import com.jogamp.opengl.GLProfile; | ||||
| import com.jogamp.opengl.awt.GLCanvas; | ||||
| 
 | ||||
| import javax.swing.JFrame; | ||||
| import java.awt.Color; | ||||
| import java.awt.event.KeyListener; | ||||
| import java.awt.event.KeyEvent; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| 
 | ||||
| import javax.swing.*; | ||||
| import java.awt.*; | ||||
| import java.awt.event.*; | ||||
| import java.util.ArrayList; | ||||
| import java.io.File; | ||||
| import java.util.Collections; | ||||
| 
 | ||||
| import java.awt.image.BufferedImage; | ||||
| 
 | ||||
| public class OGL_Window implements GLEventListener, KeyListener, ActionListener { | ||||
|     private int imgHeight = 200; | ||||
|      | ||||
|     private JFrame frame; | ||||
|     private JPanel drawPanel; | ||||
|     private JPanel drawImg; | ||||
|     private JPanel drawQImg; | ||||
|      | ||||
|     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; | ||||
| 
 | ||||
|     private final GLCanvas glcanvas; | ||||
|      | ||||
|     private ArrayList<RGB> image; | ||||
|     private ArrayList<RGB> orig; | ||||
|     private ArrayList<RGB> quants; | ||||
|      | ||||
|     private BufferedImage img; | ||||
|     private BufferedImage qimg; | ||||
|      | ||||
|     private int azimut = 25; | ||||
|     private int rot = 45; | ||||
|      | ||||
|     @Override | ||||
|     public void display(GLAutoDrawable drawable) { | ||||
|         final GL2 gl = drawable.getGL().getGL2(); | ||||
| 
 | ||||
|         gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT | GL2.GL_STENCIL_BUFFER_BIT); | ||||
| 
 | ||||
|         final GLU glu = GLU.createGLU(gl); | ||||
|         gl.glMatrixMode(GL2.GL_PROJECTION); | ||||
|         gl.glLoadIdentity(); | ||||
|         double w = this.drawPanel.getWidth(); | ||||
|         double h = this.drawPanel.getHeight(); | ||||
|         glu.gluPerspective(45,w/h,0.1,100); | ||||
|         gl.glMatrixMode(GL2.GL_MODELVIEW); | ||||
|         gl.glLoadIdentity(); | ||||
|         glu.gluLookAt( | ||||
|             0,0,3, | ||||
|             0,0,0, | ||||
|             0,1,0 | ||||
|         ); | ||||
|         gl.glRotatef(this.azimut,1,0,0); | ||||
|         gl.glRotatef(-this.rot,0,1,0); | ||||
| 
 | ||||
|         gl.glLineWidth(5); | ||||
|         gl.glBegin(GL2.GL_LINES); | ||||
|          | ||||
|         gl.glColor4f(0,0,0,1); | ||||
|         gl.glVertex3f(0,0,0); | ||||
|         gl.glColor4f(1,0,0,1); | ||||
|         gl.glVertex3f(1,0,0); | ||||
|          | ||||
|         gl.glColor4f(0,0,0,1); | ||||
|         gl.glVertex3f(0,0,0); | ||||
|         gl.glColor4f(0,1,0,1); | ||||
|         gl.glVertex3f(0,1,0); | ||||
|          | ||||
|         gl.glColor4f(0,0,0,1); | ||||
|         gl.glVertex3f(0,0,0); | ||||
|         gl.glColor4f(0,0,1,1); | ||||
|         gl.glVertex3f(0,0,1); | ||||
|         gl.glEnd(); | ||||
|                  | ||||
|         gl.glEnable(GL2.GL_BLEND); | ||||
|         gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA); | ||||
| 
 | ||||
|         gl.glPointSize(8); | ||||
|         gl.glBegin(GL2.GL_POINTS); | ||||
|         for (RGB p : this.image) { | ||||
|             gl.glColor4f(((float)(p.r))/256/4,((float)(p.g))/256/4,((float)(p.b))/256/4,0.15f); | ||||
|             gl.glVertex3f( | ||||
|                 ((float)(p.r))/256, | ||||
|                 ((float)(p.g))/256, | ||||
|                 ((float)(p.b))/256 | ||||
|             ); | ||||
|         } | ||||
|         gl.glEnd(); | ||||
|          | ||||
|         gl.glPointSize(20); | ||||
|         gl.glBegin(GL2.GL_POINTS); | ||||
|         for (RGB p : this.quants) { | ||||
|             gl.glColor4f(((float)(p.r))/256,((float)(p.g))/256,((float)(p.b))/256,1f); | ||||
|             gl.glVertex3f( | ||||
|                 ((float)(p.r))/256, | ||||
|                 ((float)(p.g))/256, | ||||
|                 ((float)(p.b))/256 | ||||
|             ); | ||||
|         } | ||||
|         gl.glEnd(); | ||||
|          | ||||
|         gl.glPointSize(20); | ||||
|         gl.glBegin(GL2.GL_POINTS); | ||||
|         gl.glColor4ub((byte)0,(byte)0,(byte)0,(byte)255); | ||||
|         gl.glVertex3f(0,0,0); | ||||
|         gl.glEnd(); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public void dispose(GLAutoDrawable arg0) {} | ||||
| 
 | ||||
|     @Override | ||||
|     public void init(GLAutoDrawable drawable) {}  | ||||
| 
 | ||||
|     @Override | ||||
|     public void reshape(GLAutoDrawable drawable, int arg1, int arg2, int arg3, int arg4) {} | ||||
|      | ||||
|     @Override | ||||
|     public void keyPressed(KeyEvent e) {} | ||||
|      | ||||
|     @Override | ||||
|     public void keyTyped(KeyEvent e) {} | ||||
|      | ||||
|     @Override | ||||
|     public void keyReleased(KeyEvent e) { | ||||
|         if (e.getKeyCode() == KeyEvent.VK_LEFT) { | ||||
|             this.rot += 15; | ||||
|         } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { | ||||
|             this.rot -= 15; | ||||
|         } else if (e.getKeyCode() == KeyEvent.VK_UP) { | ||||
|             this.azimut -= 15; | ||||
|         } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { | ||||
|             this.azimut += 15; | ||||
|         } else { | ||||
|             return; | ||||
|         } | ||||
|          | ||||
|         this.glcanvas.repaint(); | ||||
|     } | ||||
|      | ||||
|     private OGL_Window() { | ||||
|         this.image = new ArrayList<>(); | ||||
|         this.orig = new ArrayList<>(); | ||||
|         this.quants = new ArrayList<>(); | ||||
|          | ||||
|         //getting the capabilities object of GL2 profile
 | ||||
|         final GLProfile profile = GLProfile.get(GLProfile.GL2); | ||||
|         GLCapabilities capabilities = new GLCapabilities(profile); | ||||
|         capabilities.setBackgroundOpaque(false); | ||||
| 
 | ||||
|         // The canvas
 | ||||
|         glcanvas = new GLCanvas(capabilities); | ||||
|         glcanvas.addGLEventListener(this); | ||||
|         glcanvas.setSize(500, 500); | ||||
|         glcanvas.setBackground(new Color(220, 220, 220)); | ||||
|         glcanvas.addKeyListener(this); | ||||
| 
 | ||||
|         OGL_Window that = this; | ||||
| 
 | ||||
|         //creating frame
 | ||||
|         frame = new JFrame("RGB Quantisierer"); | ||||
|         frame.addWindowListener(new WindowAdapter() { | ||||
|             public void windowClosing(WindowEvent e) { System.exit(0); } | ||||
|         }); | ||||
|         frame.addComponentListener(new ComponentAdapter() { | ||||
|            public void componentResized(ComponentEvent e) { | ||||
|                int width = (int)that.frame.getSize().getWidth(); | ||||
|                int height = (int)that.frame.getSize().getHeight() - 160 - that.imgHeight; | ||||
|                that.glcanvas.setSize(width, height); | ||||
|                that.drawPanel.setSize(new Dimension(width, height)); | ||||
|            } | ||||
|         }); | ||||
|          | ||||
|         JPanel mainPanel = new JPanel(); | ||||
|         mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); | ||||
|          | ||||
|         drawPanel = new JPanel(); | ||||
|         JPanel view = new JPanel(); | ||||
|         JPanel steps = new JPanel(); | ||||
|         JPanel config = new JPanel(); | ||||
|         JPanel images = new JPanel(); | ||||
| 
 | ||||
|         mainPanel.add(drawPanel); | ||||
|         mainPanel.add(view); | ||||
|         mainPanel.add(steps); | ||||
|         mainPanel.add(config); | ||||
|         mainPanel.add(images); | ||||
|          | ||||
|         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); | ||||
|          | ||||
|         drawImg = new JPanel(); | ||||
|         drawImg.setPreferredSize(new Dimension(this.imgHeight + 50,this.imgHeight + 10)); | ||||
|         drawQImg = new JPanel(); | ||||
|         drawQImg.setPreferredSize(new Dimension(this.imgHeight + 50,this.imgHeight + 10)); | ||||
|         images.add(drawImg); | ||||
|         images.add(drawQImg); | ||||
|          | ||||
|         frame.add(mainPanel); | ||||
|         drawPanel.add(glcanvas); | ||||
| 
 | ||||
|         frame.pack(); | ||||
|         frame.setVisible(true); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Button-Reaktivität | ||||
|      *  | ||||
|      * @param e ActionEvent | ||||
|      */ | ||||
|     public void actionPerformed(ActionEvent e) { | ||||
|         /** | ||||
|          * Pfeilbuttons: Ändern der Ansicht | ||||
|          */ | ||||
|         if (e.getSource() == this.vr) this.rot = (this.rot + 345) % 360; | ||||
|         if (e.getSource() == this.vl) this.rot = (this.rot + 15) % 360; | ||||
|         if (e.getSource() == this.vu) this.azimut = (this.azimut + 345) % 360; | ||||
|         if (e.getSource() == this.vd) this.azimut = (this.azimut + 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()); | ||||
|                 this.img = Image.loadFile("./inputs/" + (String)this.s_input.getSelectedItem()); | ||||
|                 this.image = new ArrayList<>(); | ||||
|                 for (RGB p : this.orig) { | ||||
|                     // kopiere die originalen Daten, damit die Liste später gemischt werden kann
 | ||||
|                     this.image.add(p); | ||||
|                 } | ||||
|                  | ||||
|                 this.drawImage(this.img, this.drawImg); | ||||
|             } 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)); | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 BufferedImage i = Image.writeFile("./inputs/" + (String)this.s_input.getSelectedItem(), "", this.orig, this.quants); | ||||
|                 this.drawImage(i, this.drawQImg); | ||||
|             } catch (Exception ex) {} | ||||
|         } | ||||
|         /** | ||||
|          * Epoche durchlaufen | ||||
|          */ | ||||
|         if (e.getSource() == this.b_epoc) { | ||||
|             Quant.doEpoch(this.image, this.quants); | ||||
| 
 | ||||
|             try { | ||||
|                 BufferedImage i = Image.writeFile("./inputs/" + (String)this.s_input.getSelectedItem(), "", this.orig, this.quants); | ||||
|                 this.drawImage(i, this.drawQImg); | ||||
|             } catch (Exception ex) {} | ||||
|         } | ||||
|         /** | ||||
|          * Nicht bewegte Punkte versetzen | ||||
|          */ | ||||
|         if (e.getSource() == this.b_reset) { | ||||
|             Quant.resetQuants(this.quants); | ||||
| 
 | ||||
|             try { | ||||
|                 BufferedImage i = Image.writeFile("./inputs/" + (String)this.s_input.getSelectedItem(), "", this.orig, this.quants); | ||||
|                 this.drawImage(i, this.drawQImg); | ||||
|             } catch (Exception ex) {} | ||||
|         } | ||||
|         /** | ||||
|          * 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.glcanvas.repaint(); | ||||
|     } | ||||
|      | ||||
|     private void drawImage(BufferedImage i, JPanel p) { | ||||
|         int w = i.getWidth(); | ||||
|         int h = i.getHeight(); | ||||
|          | ||||
|         if (w > h) { | ||||
|             h = h * this.imgHeight / w; | ||||
|             w = this.imgHeight; | ||||
|         } else { | ||||
|             w = w * this.imgHeight / h; | ||||
|             h = this.imgHeight; | ||||
|         } | ||||
|          | ||||
|         JLabel img = new JLabel(new ImageIcon(i.getScaledInstance(w,h,1))); | ||||
|         img.setPreferredSize(new Dimension(this.imgHeight, this.imgHeight)); | ||||
|         p.removeAll(); | ||||
|         p.add(img); | ||||
|         p.revalidate(); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * 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); | ||||
|     } | ||||
| 
 | ||||
|     public static void main() throws Exception { | ||||
|         new OGL_Window(); | ||||
|     } | ||||
| } | ||||
|  | @ -4,14 +4,17 @@ PROJEKTZWECK: Liest ein Bild aus einer JPG-Datei ein und stellt die | |||
|     Anschließend werden zufallsverteilte Punkte den Originaldaten | ||||
|     angenähert um  abschließend das Bild auf diese Farben reduziert | ||||
|     wieder abzuspeichern. | ||||
| VERSION oder DATUM: 1.0.1 (26.10.2023) | ||||
| WIE IST DAS PROJEKT ZU STARTEN: Instanz der Klasse Window anlegen | ||||
| VERSION oder DATUM: 1.1 (27.10.2023) | ||||
| WIE IST DAS PROJEKT ZU STARTEN: OGL_Window -> main()-Methode starten | ||||
| AUTOR: Alexander Kimmig (a.kimmig@dhg-rw.de) | ||||
| BENUTZERHINWEISE: Die ChartDirector_s.jar muss in den BlueJ-Einstellungen | ||||
|     als externe Benutzerbibliothek eingebunden werden. | ||||
|     (Quelle: https://www.advsofteng.com/doc/cdjava.htm) | ||||
| 
 | ||||
| CHANGELOG: | ||||
| * Version 1.1 (27.10.2023) | ||||
|     * umgestellt auf OpenGL, manuelles Rendering | ||||
|     *  | ||||
| * Version 1.0.1 (26.10.2023) | ||||
|     * Möglichkeit, das Fenster in kleinerer Auflösung anzuzeigen | ||||
|     * Möglichkeit, die Punktwolke farbig anzuzeigen | ||||
|  |  | |||
|  | @ -1,3 +1,7 @@ | |||
| /** | ||||
|  * BITTE NICHT MEHR NUTZEN -> stattdessen OGL_Window verwenden! | ||||
|  */ | ||||
| 
 | ||||
| import ChartDirector.*; | ||||
| import javax.swing.*; | ||||
| import java.awt.*; | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 905 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 55 KiB | 
		Loading…
	
		Reference in New Issue