diff --git a/QR/.classpath b/QR/.classpath
new file mode 100644
index 0000000..e693970
--- /dev/null
+++ b/QR/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/QR/.project b/QR/.project
new file mode 100644
index 0000000..e89508e
--- /dev/null
+++ b/QR/.project
@@ -0,0 +1,17 @@
+
+
+ Sven.QR
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/QR/.settings/org.eclipse.jdt.core.prefs b/QR/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..bb35fa0
--- /dev/null
+++ b/QR/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/QR/bin/BorderInformation.class b/QR/bin/BorderInformation.class
new file mode 100644
index 0000000..c3cbf32
Binary files /dev/null and b/QR/bin/BorderInformation.class differ
diff --git a/QR/bin/MainFrame$1.class b/QR/bin/MainFrame$1.class
new file mode 100644
index 0000000..bf1764f
Binary files /dev/null and b/QR/bin/MainFrame$1.class differ
diff --git a/QR/bin/MainFrame$2.class b/QR/bin/MainFrame$2.class
new file mode 100644
index 0000000..4ef01d5
Binary files /dev/null and b/QR/bin/MainFrame$2.class differ
diff --git a/QR/bin/MainFrame$3.class b/QR/bin/MainFrame$3.class
new file mode 100644
index 0000000..a881e5c
Binary files /dev/null and b/QR/bin/MainFrame$3.class differ
diff --git a/QR/bin/MainFrame$4.class b/QR/bin/MainFrame$4.class
new file mode 100644
index 0000000..a4d5252
Binary files /dev/null and b/QR/bin/MainFrame$4.class differ
diff --git a/QR/bin/MainFrame$5.class b/QR/bin/MainFrame$5.class
new file mode 100644
index 0000000..bf187a4
Binary files /dev/null and b/QR/bin/MainFrame$5.class differ
diff --git a/QR/bin/MainFrame$6.class b/QR/bin/MainFrame$6.class
new file mode 100644
index 0000000..4264ef0
Binary files /dev/null and b/QR/bin/MainFrame$6.class differ
diff --git a/QR/bin/MainFrame.class b/QR/bin/MainFrame.class
new file mode 100644
index 0000000..b82a17b
Binary files /dev/null and b/QR/bin/MainFrame.class differ
diff --git a/QR/bin/Pair.class b/QR/bin/Pair.class
new file mode 100644
index 0000000..6a9a342
Binary files /dev/null and b/QR/bin/Pair.class differ
diff --git a/QR/bin/PrintActionListener$ImagePrintable.class b/QR/bin/PrintActionListener$ImagePrintable.class
new file mode 100644
index 0000000..5ea3e1d
Binary files /dev/null and b/QR/bin/PrintActionListener$ImagePrintable.class differ
diff --git a/QR/bin/PrintActionListener.class b/QR/bin/PrintActionListener.class
new file mode 100644
index 0000000..749a2a9
Binary files /dev/null and b/QR/bin/PrintActionListener.class differ
diff --git a/QR/bin/SvenQR.class b/QR/bin/SvenQR.class
new file mode 100644
index 0000000..28784e2
Binary files /dev/null and b/QR/bin/SvenQR.class differ
diff --git a/QR/jgoodies-common-1.8.0-sources.jar b/QR/jgoodies-common-1.8.0-sources.jar
new file mode 100644
index 0000000..24762f7
Binary files /dev/null and b/QR/jgoodies-common-1.8.0-sources.jar differ
diff --git a/QR/jgoodies-common-1.8.0.jar b/QR/jgoodies-common-1.8.0.jar
new file mode 100644
index 0000000..e67347f
Binary files /dev/null and b/QR/jgoodies-common-1.8.0.jar differ
diff --git a/QR/jgoodies-forms-1.8.0-sources.jar b/QR/jgoodies-forms-1.8.0-sources.jar
new file mode 100644
index 0000000..822eb93
Binary files /dev/null and b/QR/jgoodies-forms-1.8.0-sources.jar differ
diff --git a/QR/jgoodies-forms-1.8.0.jar b/QR/jgoodies-forms-1.8.0.jar
new file mode 100644
index 0000000..a6a8126
Binary files /dev/null and b/QR/jgoodies-forms-1.8.0.jar differ
diff --git a/QR/src/BorderInformation.java b/QR/src/BorderInformation.java
new file mode 100644
index 0000000..eb6049b
--- /dev/null
+++ b/QR/src/BorderInformation.java
@@ -0,0 +1,11 @@
+public class BorderInformation {
+ // Randstärke in Pixeln
+ public float BorderWidth;
+ // Erstes schwarzes Pixel in der linken oberen Ecke
+ public Pair firstBlackPixel;
+
+ public BorderInformation(float width, Pair firstBlack) {
+ BorderWidth = width;
+ firstBlackPixel = firstBlack;
+ }
+}
diff --git a/QR/src/MainFrame.java b/QR/src/MainFrame.java
new file mode 100644
index 0000000..5b197ef
--- /dev/null
+++ b/QR/src/MainFrame.java
@@ -0,0 +1,227 @@
+import java.awt.BorderLayout;
+import java.awt.EventQueue;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.UIManager;
+import javax.swing.border.EmptyBorder;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.JMenuBar;
+import javax.swing.JTabbedPane;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JMenu;
+import javax.swing.KeyStroke;
+import java.awt.event.KeyEvent;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.awt.event.InputEvent;
+import java.awt.FlowLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import javax.swing.JLabel;
+import com.jgoodies.forms.factories.DefaultComponentFactory;
+import javax.swing.JTextField;
+import javax.imageio.ImageIO;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JCheckBox;
+
+public class MainFrame extends JFrame {
+
+ private JPanel contentPane;
+ private JTextField textField;
+ private JTextField textField_1;
+ JButton btnEinlesen = new JButton("Einlesen");
+ JLabel lblNewLabel = new JLabel("Ausgelesener Wert: -");
+ JButton btnDrucken = new JButton("Drucken");
+ JButton btnSpeichern = new JButton("Speichern");
+
+ // Parent für JFileChooser
+ JFrame _this = this;
+ // File zum speichern / lesen
+ File f;
+ // Generierter QR-Code
+ BufferedImage img = null;
+
+ /**
+ * Launch the application.
+ */
+ public static void main(String[] args) {
+ EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ MainFrame frame = new MainFrame();
+ frame.setVisible(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ /**
+ * Create the frame.
+ */
+ public MainFrame() {
+ setTitle("Sven.QR");
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setBounds(100, 100, 600, 400);
+ contentPane = new JPanel();
+ contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
+ setContentPane(contentPane);
+ contentPane.setLayout(new BorderLayout(0, 0));
+
+ JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
+ contentPane.add(tabbedPane, BorderLayout.CENTER);
+
+ JPanel panel_1 = new JPanel();
+ tabbedPane.addTab(" QR-Code generieren ", null, panel_1, null);
+ panel_1.setLayout(null);
+
+ JLabel lblQrcode = new JLabel("QR-Code Wert:");
+ lblQrcode.setBounds(10, 14, 80, 14);
+ panel_1.add(lblQrcode);
+
+ textField_1 = new JTextField();
+ textField_1.setBounds(94, 11, 424, 20);
+ panel_1.add(textField_1);
+ textField_1.setColumns(10);
+
+ //
+ // = BUTTON GENERIEREN: Generiert einen QR-Code aus dem Wert der TextBox und speichert ihn.
+ //
+ JButton btnGenerieren = new JButton("Generieren");
+ btnGenerieren.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ try {
+ int value = Integer.parseInt(textField_1.getText());
+ img = SvenQR.GenerateQR(value);
+ } catch(Exception e1) {
+ JOptionPane.showMessageDialog(_this, "QR-Code konnte nicht generiert werden: " + e1.getMessage());
+ return;
+ }
+
+ btnDrucken.setEnabled(true);
+ btnSpeichern.setEnabled(true);
+ }
+ });
+ btnGenerieren.setBounds(94, 42, 89, 23);
+ panel_1.add(btnGenerieren);
+
+ //
+ // = BUTTON DRUCKEN: Druckt den generierten QR-Code.
+ //
+
+ btnDrucken.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ new Thread(new PrintActionListener(img)).start();
+ }
+ });
+ btnDrucken.setEnabled(false);
+ btnDrucken.setBounds(292, 42, 89, 23);
+ panel_1.add(btnDrucken);
+
+ //
+ // = BUTTON SPEICHERN: Speichert den generierten QR-Code.
+ //
+
+ btnSpeichern.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ // JFileChooser erstellen
+ JFileChooser fc = new JFileChooser();
+ // Dateifilter setzen
+ FileNameExtensionFilter filter = new FileNameExtensionFilter(
+ "PNG (*.png)", "png");
+
+ fc.setFileFilter(filter);
+
+ // Wenn im Dialog nicht OK gedrückt wurde, Methode verlassen
+ if (fc.showSaveDialog(_this) != JFileChooser.APPROVE_OPTION)
+ return;
+
+ f = fc.getSelectedFile();
+
+ try {
+ ImageIO.write(img, "png", f);
+ } catch (IOException e1) {
+ JOptionPane.showMessageDialog(_this, "QR-Code konnte nicht gespeichert werden: " + e1.getMessage());
+ return;
+ }
+ }
+ });
+ btnSpeichern.setEnabled(false);
+ btnSpeichern.setBounds(193, 42, 89, 23);
+ panel_1.add(btnSpeichern);
+
+ JPanel panel = new JPanel();
+ tabbedPane.addTab(" QR-Code einlesen ", null, panel, null);
+ panel.setLayout(null);
+
+ JLabel lblQuelldatei = new JLabel("Quelldatei:");
+ lblQuelldatei.setBounds(10, 12, 55, 14);
+ panel.add(lblQuelldatei);
+
+ textField = new JTextField();
+ textField.setBounds(75, 8, 451, 21);
+ panel.add(textField);
+ textField.setColumns(10);
+
+ //
+ // = BUTTON ... : Wählt die Quelldatei mit einem JFileChooser aus. =
+ //
+ JButton button = new JButton("...");
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ // JFileChooser erstellen
+ JFileChooser fc = new JFileChooser();
+ fc.setCurrentDirectory(new File("T:/INTABI19/Projekt/ELMO Interactive Toolbox/rec"));
+
+ // Wenn im Dialog nicht OK gedrückt wurde, Methode verlassen
+ if (fc.showOpenDialog(_this) != JFileChooser.APPROVE_OPTION)
+ return;
+
+ // Ausgewählte Datei auslesen
+ f = fc.getSelectedFile();
+ // Pfad der Datei in Textbox schreiben
+ textField.setText(f.getAbsolutePath());
+
+ // Einlesen-Button aktivieren
+ btnEinlesen.setEnabled(true);
+ }
+ });
+ button.setBounds(536, 7, 23, 23);
+ panel.add(button);
+
+ //
+ // = BUTTON EINLESEN: Liest ausgewählten QR-Code aus Datei ein. =
+ //
+ btnEinlesen.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ // Ausgelesener Wert
+ int value = -1;
+
+ // Versuche, den QR-Code einzulesen
+ // Wenn das nicht geht, wird eine Fehlermeldung ausgegeben
+ try {
+ value = SvenQR.ReadQR(f.getAbsolutePath());
+ } catch (IOException e1) {
+ JOptionPane.showMessageDialog(_this, "QR-Code konnte nicht eingelesen werden: " + e1.getMessage());
+ return;
+ }
+
+ // Ausgelesener Wert auf Label schreiben
+ lblNewLabel.setText("Ausgelesener Wert: " + value);
+ }
+ });
+ btnEinlesen.setEnabled(false);
+ btnEinlesen.setBounds(75, 40, 89, 23);
+ panel.add(btnEinlesen);
+
+
+ lblNewLabel.setBounds(10, 74, 549, 14);
+ panel.add(lblNewLabel);
+ }
+}
diff --git a/QR/src/Pair.java b/QR/src/Pair.java
new file mode 100644
index 0000000..86373d6
--- /dev/null
+++ b/QR/src/Pair.java
@@ -0,0 +1,15 @@
+public class Pair {
+ public int x, y;
+
+ public Pair(int _x, int _y) {
+ x = _x;
+ y = _y;
+ }
+
+ // Kopierkonstruktor, da eine Zuweisung nicht die Werte kopiert,
+ // sondern beide Variablen auf den gleichen Speicher zeigen lässt.
+ public Pair(Pair copy) {
+ x = copy.x;
+ y = copy.y;
+ }
+}
diff --git a/QR/src/PrintActionListener.java b/QR/src/PrintActionListener.java
new file mode 100644
index 0000000..ad02e2f
--- /dev/null
+++ b/QR/src/PrintActionListener.java
@@ -0,0 +1,71 @@
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+
+// Quelle: https://stackoverflow.com/questions/18404553/proper-way-of-printing-a-bufferedimage-in-java
+
+public class PrintActionListener implements Runnable {
+
+ private BufferedImage image;
+
+ public PrintActionListener(BufferedImage image) {
+ this.image = image;
+ }
+
+ @Override
+ public void run() {
+ PrinterJob printJob = PrinterJob.getPrinterJob();
+ printJob.setPrintable(new ImagePrintable(printJob, image));
+
+ if (printJob.printDialog()) {
+ try {
+ printJob.print();
+ } catch (PrinterException prt) {
+ prt.printStackTrace();
+ }
+ }
+ }
+
+ public class ImagePrintable implements Printable {
+
+ private double x, y, width;
+
+ private int orientation;
+
+ private BufferedImage image;
+
+ public ImagePrintable(PrinterJob printJob, BufferedImage image) {
+ PageFormat pageFormat = printJob.defaultPage();
+ this.x = pageFormat.getImageableX();
+ this.y = pageFormat.getImageableY();
+ this.width = pageFormat.getImageableWidth();
+ this.orientation = pageFormat.getOrientation();
+ this.image = image;
+ }
+
+ @Override
+ public int print(Graphics g, PageFormat pageFormat, int pageIndex)
+ throws PrinterException {
+ if (pageIndex == 0) {
+ int pWidth = 0;
+ int pHeight = 0;
+ if (orientation == PageFormat.PORTRAIT) {
+ pWidth = (int) Math.min(width, (double) image.getWidth());
+ pHeight = pWidth * image.getHeight() / image.getWidth();
+ } else {
+ pHeight = (int) Math.min(width, (double) image.getHeight());
+ pWidth = pHeight * image.getWidth() / image.getHeight();
+ }
+ g.drawImage(image, (int) x, (int) y, pWidth, pHeight, null);
+ return PAGE_EXISTS;
+ } else {
+ return NO_SUCH_PAGE;
+ }
+ }
+
+ }
+
+ }
diff --git a/QR/src/SvenQR.java b/QR/src/SvenQR.java
new file mode 100644
index 0000000..68cf771
--- /dev/null
+++ b/QR/src/SvenQR.java
@@ -0,0 +1,484 @@
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.io.*;
+import javax.imageio.ImageIO;
+
+public class SvenQR {
+ // Anzahl der Rechtecke horizontal
+ public static final int AMNT_RECT_X = 4;
+ // Anzahl der Rechtecke vertikal
+ public static final int AMNT_RECT_Y = 3;
+ // Rahmendicke in Pixeln
+ public static final int BORDER_WIDTH = 8;
+ // Rechteckgröße in Pixeln
+ public static final int RECT_WIDTH = 40;
+
+ // Liest das angegebene Bild ein und wertet den QR-Code aus.
+ public static int ReadQR(String fileName) throws IOException {
+ // Quellbild
+ BufferedImage img = ImageIO.read(new File(fileName));
+ // Informationen über den Rand und die Ausmaße
+ BorderInformation info;
+ // Gemessene Größe des QR-Codes
+ Pair measuredSize;
+ // Wert des QR-Codes
+ int value;
+
+ img = _IN_PrepareImage(img);
+
+ info = _IN_GetBorderWidth(img);
+
+ Pair imageSize = new Pair((int) img.getWidth(), (int) img.getHeight());
+ measuredSize = _IN_GetMeasuredSize(img, info, imageSize);
+
+ // Durchschnittsgröße der Rechtecke
+ int avgSquareWidth = (int) ((measuredSize.x - 4f * info.BorderWidth) / AMNT_RECT_X);
+ int avgSquareHeight = (int) ((measuredSize.y - 4f * info.BorderWidth) / AMNT_RECT_Y);
+ Pair avgSquareSize = new Pair(avgSquareWidth, avgSquareHeight);
+
+ value = _IN_HeuristicDetermination(img, info, avgSquareSize);
+
+ return value;
+ }
+
+ public static BufferedImage GenerateQR(int value) {
+ boolean[][] bits;
+ BufferedImage img;
+
+ // Konvertiere die Zahl in eine Bit-Tabelle, die der QR-Code-Darstellung
+ // entspricht
+ bits = _OUT_GetBits(value);
+
+ // Generiere Bild
+ img = _OUT_DrawImage(bits);
+
+ return img;
+ }
+
+ public static BufferedImage _IN_PrepareImage(BufferedImage img) {
+ // Bildgröße auslesen
+ int width = img.getWidth();
+ int height = img.getHeight();
+
+ //
+ // = BILD ENTSÄTTIGEN UND KONTRAST SPREIZEN =
+ //
+ // Jedes Pixel durchgehen und in Graustufen umwandeln,
+ // danach den Kontrast spreizen, sodass nur noch schwarze
+ // und weiße Pixel im Bild sind, anders kann der Algorithmus
+ // nicht arbeiten.
+ //
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+
+ // Aktuelles Pixel auslesen
+ int value = img.getRGB(x, y);
+ Color c1 = new Color(value);
+
+ // Graustufe berechnen
+ int grau = (c1.getBlue() + c1.getRed() + c1.getGreen()) / 3;
+
+ // Kontrast spreizen
+ if (grau >= 127) {
+ grau = 255;
+ } else {
+ grau = 0;
+ }
+
+ // Pixel ersetzen
+ Color c = new Color(grau, grau, grau);
+ img.setRGB(x, y, c.getRGB());
+ }
+ }
+
+ /*try {
+ File fx = new File("X:/ents.png"); // Speicherort
+ ImageIO.write(img, "png", fx); // Bildformat
+ } catch (IOException e) {
+ System.out.println("Error: " + e);
+ }*/
+
+ //
+ // = ALLEINSTEHENDE PIXEL IM BILD ENTFERNEN =
+ //
+ // Wenn das Bild fleckig ist, entstehen einzelne Pixel, die
+ // den Algorithmus zum auslesen stören können, also werden
+ // diese entfernt.
+ //
+
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ boolean weissAussendrum = true;
+
+ // Rechts
+ if (!(x < width - 1 && img.getRGB(x + 1, y) == -1))
+ weissAussendrum = false;
+ // Links
+ if (!(x > 0 && img.getRGB(x - 1, y) == -1))
+ weissAussendrum = false;
+ // Drunter
+ if (!(y < height - 1 && img.getRGB(x, y + 1) == -1))
+ weissAussendrum = false;
+ // Drüber
+ if (!(y > 0 && img.getRGB(x, y - 1) == -1))
+ weissAussendrum = false;
+
+ // Links oben
+ if (!(x > 0 && y > 0 && img.getRGB(x - 1, y - 1) == - 1))
+ weissAussendrum = false;
+ // Links unten
+ if (!(x > 0 && y < height - 1 && img.getRGB(x - 1, y + 1) == -1))
+ weissAussendrum = false;
+ // Rechts oben
+ if (!(x < width - 1 && y > 0 && img.getRGB(x + 1, y - 1) == -1))
+ weissAussendrum = false;
+ // Rechts unten
+ if (!(x < width - 1 && y < height - 1 && img.getRGB(x + 1, y + 1) == -1))
+ weissAussendrum = false;
+
+ if (weissAussendrum)
+ img.setRGB(x, y, -1 );
+
+ }
+ }
+
+ /*try {
+ File fx = new File("X:/prep2.png"); // Speicherort
+ ImageIO.write(img, "png", fx); // Bildformat
+ } catch (IOException e) {
+ System.out.println("Error: " + e);
+ }*/
+
+ return img;
+ }
+
+ private static BorderInformation _IN_GetBorderWidth(BufferedImage img) {
+ Color pixel;
+
+ // Informationen über den Rahmen des QR-Codes
+ BorderInformation info = null;
+
+ // Breite des schwarzen Rahmens und Orientierungspunkte
+ float borderWidth = -1f;
+ Pair firstBlackPixel = new Pair(-1, -1);
+ Pair firstWhitePixel;
+
+ //
+ // = SUCHE DAS ERSTE SCHWARZE PIXEL IN DER LINKEN OBEREN ECKE =
+ //
+
+ // Gehe diagonal durch das Bild auf der Suche nach schwarzen Pixeln
+ while (!_IN_CompareColors(img.getRGB(firstBlackPixel.x + 1, firstBlackPixel.y + 1), Color.BLACK)) {
+ firstBlackPixel.x++;
+ firstBlackPixel.y++;
+ }
+
+ firstBlackPixel.x++;
+ firstBlackPixel.y++;
+
+ // Aufgrund von Ungenauigkeiten beim Drucken, gehen wir drei Pixel in den Rand rein
+ firstBlackPixel.x += 2;
+
+ System.out.println("Suche schwarzes Pixel.");
+ System.out.println("X: " + firstBlackPixel.x + " Y: " + firstBlackPixel.y + "\n");
+
+
+ // Gehe so weit wie möglich nach oben
+ while (firstBlackPixel.y > 0
+ && _IN_CompareColors(img.getRGB(firstBlackPixel.x, firstBlackPixel.y - 1), Color.BLACK))
+ firstBlackPixel.y--;
+
+ System.out.println("Gehe so weit wie möglich nach oben");
+ System.out.println("X: " + firstBlackPixel.x + " Y: " + firstBlackPixel.y + "\n");
+
+ // Gehe so weit wie möglich nach links
+ while (firstBlackPixel.x > 0
+ && _IN_CompareColors(img.getRGB(firstBlackPixel.x - 1, firstBlackPixel.y), Color.BLACK))
+ firstBlackPixel.x--;
+
+ System.out.println("Gehe so weit wie möglich nach links");
+ System.out.println("X: " + firstBlackPixel.x + " Y: " + firstBlackPixel.y + "\n");
+
+ //
+ // = SUCHE DAS ERSTE WEISSE PIXEL VOM INNEREN RAHMEN =
+ //
+
+ firstWhitePixel = new Pair(firstBlackPixel);
+
+ // Gehe diagonal vom ersten schwarzen Pixel durch das Bild
+ while (!_IN_CompareColors(img.getRGB(firstWhitePixel.x + 1, firstWhitePixel.y + 1), Color.WHITE)) {
+ firstWhitePixel.x++;
+ firstWhitePixel.y++;
+ }
+
+ firstWhitePixel.x++;
+ firstWhitePixel.y++;
+
+ System.out.println("Suche weißes Pixel");
+ System.out.println("X: " + firstWhitePixel.x + " Y: " + firstWhitePixel.y + "\n");
+
+ // Gehe so weit wie möglich nach oben
+ while (_IN_CompareColors(img.getRGB(firstWhitePixel.x, firstWhitePixel.y - 1), Color.WHITE))
+ firstWhitePixel.y--;
+
+ System.out.println("Gehe soweit wie möglich nach oben");
+ System.out.println("X: " + firstWhitePixel.x + " Y: " + firstWhitePixel.y + "\n");
+
+ // Gehe so weit wie möglich nach links
+ while (_IN_CompareColors(img.getRGB(firstWhitePixel.x - 1, firstWhitePixel.y), Color.WHITE))
+ firstWhitePixel.x--;
+
+ System.out.println("Gehe soweit wie möglich nach links");
+ System.out.println("X: " + firstWhitePixel.x + " Y: " + firstWhitePixel.y + "\n");
+
+ // Differenzen, also Rahmenstärke ausrechnen
+ int deltaX = firstWhitePixel.x - firstBlackPixel.x;
+ int deltaY = firstWhitePixel.y - firstBlackPixel.y;
+
+ // Durchschnitt ermitteln
+ borderWidth = (deltaX + deltaY) / 2f;
+
+ System.out.println("Border width: " + borderWidth);
+
+ info = new BorderInformation(borderWidth, firstBlackPixel);
+ return info;
+ }
+
+ private static Pair _IN_GetMeasuredSize(BufferedImage img, BorderInformation borderInfo, Pair imageSize) {
+ Pair measuredSize;
+ Pair upperRightBlackPixel, lowerLeftBlackPixel;
+ Color pixel;
+
+ //
+ // = MESSE DIE BREITE DES QR-CODES =
+ //
+
+ upperRightBlackPixel = new Pair(borderInfo.firstBlackPixel);
+ // Weil das Bild nicht immer gerade ist, messen wir in der Mitte des
+ // schwarzen Rahmens
+ upperRightBlackPixel.y += borderInfo.BorderWidth / 2f;
+
+ while (upperRightBlackPixel.x < imageSize.x - 1
+ && !_IN_CompareColors(img.getRGB(upperRightBlackPixel.x + 1, upperRightBlackPixel.y), Color.WHITE))
+ upperRightBlackPixel.x++;
+
+ //
+ // = MESSE DIE HÖHE DES QR-CODES =
+ //
+
+ lowerLeftBlackPixel = new Pair(borderInfo.firstBlackPixel);
+ // Immer mittig messen, kann bei arg schiefen Bildern jedoch auch wieder
+ // zu fehlerhaften Ergebnissen führen
+ // In solch einem Fall können wir nichts tun :/
+ lowerLeftBlackPixel.x += borderInfo.BorderWidth / 2f;
+
+ while (lowerLeftBlackPixel.y < imageSize.y - 1
+ && !_IN_CompareColors(img.getRGB(upperRightBlackPixel.x, upperRightBlackPixel.y + 1), Color.WHITE))
+ lowerLeftBlackPixel.y++;
+
+ // Errechne die Größe des QR-Codes aus den Differenzen der Punkte
+ measuredSize = new Pair(upperRightBlackPixel.x - borderInfo.firstBlackPixel.x,
+ lowerLeftBlackPixel.y - borderInfo.firstBlackPixel.y);
+ measuredSize.x++;
+ measuredSize.y++;
+
+ System.out.println("Gemessene Größe: " + measuredSize.x + " x " + measuredSize.y);
+
+ return measuredSize;
+ }
+
+ private static int _IN_HeuristicDetermination(BufferedImage img, BorderInformation borderInfo, Pair avgSquareSize) {
+ boolean[][] bits = new boolean[AMNT_RECT_X][AMNT_RECT_Y];
+ float halfWidth = avgSquareSize.x / 2f, halfHeight = avgSquareSize.y / 2f;
+ int c_value;
+
+ for (int x = 0; x < AMNT_RECT_X; x++) {
+ for (int y = 0; y < AMNT_RECT_Y; y++) {
+
+ int _x = (int) (2 * borderInfo.BorderWidth);
+ _x += (int) (x * avgSquareSize.x);
+ _x += (int) halfWidth;
+ _x += borderInfo.firstBlackPixel.x;
+
+ int _y = (int) (2 * borderInfo.BorderWidth);
+ _y += (int) (y * avgSquareSize.y);
+ _y += (int) halfHeight;
+ _y += borderInfo.firstBlackPixel.y;
+
+ c_value = img.getRGB(_x, _y);
+ System.out.println("X: " + _x + " Y: " + _y + " V: " + (_IN_CompareColors(c_value, Color.WHITE) ? false : true));
+
+ if (_IN_CompareColors(c_value, Color.WHITE))
+ bits[x][y] = false;
+ else if (_IN_CompareColors(c_value, Color.BLACK))
+ bits[x][y] = true;
+ }
+ }
+
+ int value = 0;
+
+ if (bits[0][0])
+ value += 1;
+ if (bits[1][0])
+ value += 2;
+ if (bits[2][0])
+ value += 4;
+ if (bits[3][0])
+ value += 8;
+
+ if (bits[0][1])
+ value += 16;
+ if (bits[1][1])
+ value += 32;
+ if (bits[2][1])
+ value += 64;
+ if (bits[3][1])
+ value += 128;
+
+ if (bits[0][2])
+ value += 256;
+ if (bits[1][2])
+ value += 512;
+ if (bits[2][2])
+ value += 1024;
+ if (bits[3][2])
+ value += 2048;
+
+ return value;
+ }
+
+ private static boolean _IN_CompareColors(int rgb, Color template) {
+ Color c = new Color(rgb);
+ if (c.getRed() != template.getRed())
+ return false;
+ if (c.getGreen() != template.getGreen())
+ return false;
+ if (c.getBlue() != template.getBlue())
+ return false;
+ return true;
+ }
+
+ private static boolean[][] _OUT_GetBits(int value) {
+ // Die Bits in QR-Code-Darstellung
+ boolean[][] bits = new boolean[AMNT_RECT_X][AMNT_RECT_Y];
+ // Die Bits als Binärstring
+ String bitsAsString = Integer.toBinaryString(value);
+ // Anzahl an führenden Nullen für 12-Bit:
+ int amntLeadingZeros = 12 - bitsAsString.length();
+
+ // Stelle führende Nullen voran
+ for (int i = 0; i < amntLeadingZeros; i++)
+ bitsAsString = "0" + bitsAsString;
+
+ bits[0][0] = bitsAsString.charAt(11) == '0' ? false : true;
+ bits[1][0] = bitsAsString.charAt(10) == '0' ? false : true;
+ bits[2][0] = bitsAsString.charAt(9) == '0' ? false : true;
+ bits[3][0] = bitsAsString.charAt(8) == '0' ? false : true;
+ bits[0][1] = bitsAsString.charAt(7) == '0' ? false : true;
+ bits[1][1] = bitsAsString.charAt(6) == '0' ? false : true;
+ bits[2][1] = bitsAsString.charAt(5) == '0' ? false : true;
+ bits[3][1] = bitsAsString.charAt(4) == '0' ? false : true;
+ bits[0][2] = bitsAsString.charAt(3) == '0' ? false : true;
+ bits[1][2] = bitsAsString.charAt(2) == '0' ? false : true;
+ bits[2][2] = bitsAsString.charAt(1) == '0' ? false : true;
+ bits[3][2] = bitsAsString.charAt(0) == '0' ? false : true;
+
+ return bits;
+ }
+
+ private static BufferedImage _OUT_DrawImage(boolean[][] bits) {
+ // Bildgröße
+ Pair imageSize;
+ // Bild
+ BufferedImage img;
+ // Grafikobjekt zum zeichnen
+ Graphics2D g;
+
+ // Bildbreite und -höhe berechnen
+ // Bei 72 dpi entspricht 1mm 3px, wir nehmen 2px
+ imageSize = new Pair(BORDER_WIDTH * 4 + AMNT_RECT_X * RECT_WIDTH, BORDER_WIDTH * 4 + AMNT_RECT_Y * RECT_WIDTH);
+
+ // Bild erstellen und Grafikobjekt erstellen
+ img = new BufferedImage(imageSize.x, imageSize.y, BufferedImage.TYPE_INT_ARGB);
+ g = img.createGraphics();
+
+ //
+ // = QR-CODE-ZEICHEN =
+ //
+
+ // Äußeren Rahmen zeichnen
+ g.setColor(Color.BLACK);
+ g.fillRect(0, 0, imageSize.x, imageSize.y);
+
+ // Inneren Rahmen zeichnen
+ g.setColor(Color.WHITE);
+ g.fillRect(BORDER_WIDTH, BORDER_WIDTH, imageSize.x - 2 * BORDER_WIDTH, imageSize.y - 2 * BORDER_WIDTH);
+
+ g.setColor(Color.BLACK);
+
+ // Rechtecke zeichnen
+ for (int x = 0; x < AMNT_RECT_X; x++) {
+ for (int y = 0; y < AMNT_RECT_Y; y++) {
+ int _x = BORDER_WIDTH * 2 + x * RECT_WIDTH;
+ int _y = BORDER_WIDTH * 2 + y * RECT_WIDTH;
+
+ if (!bits[x][y])
+ continue;
+
+ g.fillRect(_x, _y, RECT_WIDTH, RECT_WIDTH);
+ }
+ }
+
+ // Rechte untere Ecke als Orientierungspunkt entfernen
+ g.setColor(Color.WHITE);
+ g.fillRect(imageSize.x - BORDER_WIDTH, imageSize.y - BORDER_WIDTH, BORDER_WIDTH, BORDER_WIDTH);
+
+ return img;
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+