QR-Programm
This commit is contained in:
parent
6cc9b9e973
commit
5481ca8841
8
QR/.classpath
Normal file
8
QR/.classpath
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="lib" path="jgoodies-common-1.8.0.jar" sourcepath="jgoodies-common-1.8.0-sources.jar"/>
|
||||
<classpathentry kind="lib" path="jgoodies-forms-1.8.0.jar" sourcepath="jgoodies-forms-1.8.0-sources.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
17
QR/.project
Normal file
17
QR/.project
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Sven.QR</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
11
QR/.settings/org.eclipse.jdt.core.prefs
Normal file
11
QR/.settings/org.eclipse.jdt.core.prefs
Normal file
@ -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
|
BIN
QR/bin/BorderInformation.class
Normal file
BIN
QR/bin/BorderInformation.class
Normal file
Binary file not shown.
BIN
QR/bin/MainFrame$1.class
Normal file
BIN
QR/bin/MainFrame$1.class
Normal file
Binary file not shown.
BIN
QR/bin/MainFrame$2.class
Normal file
BIN
QR/bin/MainFrame$2.class
Normal file
Binary file not shown.
BIN
QR/bin/MainFrame$3.class
Normal file
BIN
QR/bin/MainFrame$3.class
Normal file
Binary file not shown.
BIN
QR/bin/MainFrame$4.class
Normal file
BIN
QR/bin/MainFrame$4.class
Normal file
Binary file not shown.
BIN
QR/bin/MainFrame$5.class
Normal file
BIN
QR/bin/MainFrame$5.class
Normal file
Binary file not shown.
BIN
QR/bin/MainFrame$6.class
Normal file
BIN
QR/bin/MainFrame$6.class
Normal file
Binary file not shown.
BIN
QR/bin/MainFrame.class
Normal file
BIN
QR/bin/MainFrame.class
Normal file
Binary file not shown.
BIN
QR/bin/Pair.class
Normal file
BIN
QR/bin/Pair.class
Normal file
Binary file not shown.
BIN
QR/bin/PrintActionListener$ImagePrintable.class
Normal file
BIN
QR/bin/PrintActionListener$ImagePrintable.class
Normal file
Binary file not shown.
BIN
QR/bin/PrintActionListener.class
Normal file
BIN
QR/bin/PrintActionListener.class
Normal file
Binary file not shown.
BIN
QR/bin/SvenQR.class
Normal file
BIN
QR/bin/SvenQR.class
Normal file
Binary file not shown.
BIN
QR/jgoodies-common-1.8.0-sources.jar
Normal file
BIN
QR/jgoodies-common-1.8.0-sources.jar
Normal file
Binary file not shown.
BIN
QR/jgoodies-common-1.8.0.jar
Normal file
BIN
QR/jgoodies-common-1.8.0.jar
Normal file
Binary file not shown.
BIN
QR/jgoodies-forms-1.8.0-sources.jar
Normal file
BIN
QR/jgoodies-forms-1.8.0-sources.jar
Normal file
Binary file not shown.
BIN
QR/jgoodies-forms-1.8.0.jar
Normal file
BIN
QR/jgoodies-forms-1.8.0.jar
Normal file
Binary file not shown.
11
QR/src/BorderInformation.java
Normal file
11
QR/src/BorderInformation.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
227
QR/src/MainFrame.java
Normal file
227
QR/src/MainFrame.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
15
QR/src/Pair.java
Normal file
15
QR/src/Pair.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
71
QR/src/PrintActionListener.java
Normal file
71
QR/src/PrintActionListener.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
484
QR/src/SvenQR.java
Normal file
484
QR/src/SvenQR.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user