diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/ReadMe.md" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/ReadMe.md" new file mode 100644 index 0000000000000000000000000000000000000000..f2f45816668b80d03309dba94f1f704da1ab34b7 --- /dev/null +++ "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/ReadMe.md" @@ -0,0 +1,21 @@ +# 二维码应用工程 + + +## 一、文件版二维码生成 + + 1. 选择需要生成二维码图片的原始文本文件,主要包含包含xml、java、yaml、md等 + 2. 读取选择的文件文本内容,转换成二维码图片 + +![文件版二维码](images/qr001.png) + +![文件版二维码](images/qr002.png) + + +## 注意 + +如JFrame打成jar后,系统图标不显示,请确认在jar根目录下是否存在 /img/icon.gif, 原因可能为resources文件夹设置有问题,eg: Excluded:* + +## 二、文字版二维码生成 + + +![文字版二维码](images/qr003.png) \ No newline at end of file diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/images/qr001.png" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/images/qr001.png" new file mode 100644 index 0000000000000000000000000000000000000000..34ea2789367ff9c2014d755f94b3910c6273dc37 Binary files /dev/null and "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/images/qr001.png" differ diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/images/qr002.png" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/images/qr002.png" new file mode 100644 index 0000000000000000000000000000000000000000..d5bf0ccb8f28f5dd091707e761cc597c8282525a Binary files /dev/null and "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/images/qr002.png" differ diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/images/qr003.png" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/images/qr003.png" new file mode 100644 index 0000000000000000000000000000000000000000..b6dc2e8d7376d0d0a3c8ee89e6f479b0215d2953 Binary files /dev/null and "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/images/qr003.png" differ diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/pom-simple.xml" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/pom-simple.xml" new file mode 100644 index 0000000000000000000000000000000000000000..8f807196c951e4a1aa1c163f90c1f7583e178f8b --- /dev/null +++ "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/pom-simple.xml" @@ -0,0 +1,83 @@ + + + 4.0.0 + com.fly + qrcode-ui + 0.0.1 + file-to-qrcode + http://maven.apache.org + jar + + + UTF-8 + UTF-8 + 1.8 + 2.12.1 + + + + com.google.zxing + core + 3.4.1 + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j.version} + + + org.projectlombok + lombok + 1.18.12 + provided + + + commons-io + commons-io + 2.6 + + + org.apache.commons + commons-lang3 + 3.5 + + + + + qrcode-simple + + + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + + + + maven-assembly-plugin + 3.5.0 + + false + + + com.fly.ui.SimpleQrCodeUI + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/pom.xml" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/pom.xml" new file mode 100644 index 0000000000000000000000000000000000000000..d157f6bd10458ae26a09886eeab87e374158073c --- /dev/null +++ "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/pom.xml" @@ -0,0 +1,83 @@ + + + 4.0.0 + com.fly + qrcode-ui + 0.0.1 + file-to-qrcode + http://maven.apache.org + jar + + + UTF-8 + UTF-8 + 1.8 + 2.12.1 + + + + com.google.zxing + core + 3.4.1 + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j.version} + + + org.projectlombok + lombok + 1.18.12 + provided + + + commons-io + commons-io + 2.6 + + + org.apache.commons + commons-lang3 + 3.5 + + + + + ${project.artifactId}-${project.version} + + + maven-compiler-plugin + 3.7.0 + + 1.8 + 1.8 + + + + maven-assembly-plugin + 3.5.0 + + false + + + com.fly.MainRun + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/MainRun.java" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/MainRun.java" new file mode 100644 index 0000000000000000000000000000000000000000..6a8e1566d087c8484062ef736180dccece58cbf7 --- /dev/null +++ "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/MainRun.java" @@ -0,0 +1,30 @@ +package com.fly; + +import javax.swing.SwingUtilities; + +import org.apache.commons.lang3.RandomUtils; + +import com.fly.ui.QrCodeUI; +import com.fly.ui.SimpleQrCodeUI; + +/** + * + * MainRun + * + * @author 00fly + * @version [版本号, 2023年3月5日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +public class MainRun +{ + public static void main(String[] args) + { + if (RandomUtils.nextBoolean()) + { + SwingUtilities.invokeLater(() -> new QrCodeUI()); + return; + } + SwingUtilities.invokeLater(() -> new SimpleQrCodeUI()); + } +} diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/ui/QrCodeUI.java" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/ui/QrCodeUI.java" new file mode 100644 index 0000000000000000000000000000000000000000..fb44c170d720c791f70b86f3d13a6b3fba8670b1 --- /dev/null +++ "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/ui/QrCodeUI.java" @@ -0,0 +1,245 @@ +package com.fly.ui; + +import java.awt.Dimension; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.stream.Stream; + +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.filechooser.FileFilter; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; + +import com.fly.utils.QRCodeUtil; + +/***** + * 界面操作展示类 + */ +public class QrCodeUI extends JFrame +{ + private static final long serialVersionUID = -9154321945329564644L; + + // 界面组件 + JPanel panel = new JPanel(); + + JTextArea textArea = new JTextArea(); + + JTextField fileText = new JTextField(null, 40); + + JButton fileDirBrowse = new JButton("请选择"); + + JButton removeButton = new JButton("清除空白行及空格"); + + JButton qrButton = new JButton(" 生 成 二 维 码 "); + + JButton clearButton = new JButton(" 清 除 内 容 "); + + String[] acceptSuffix = {".xml", ".java", ".yml", ".yaml", ".md", ".txt"}; + + // 构造函数 + public QrCodeUI() + { + // 加载图标 + URL imgURL = getClass().getResource("/img/icon.gif"); + if (imgURL != null) + { + Image image = getToolkit().createImage(imgURL); + setIconImage(image); + } + setTitle("二维码应用工具 V1.0"); + setSize(900, 550); + Dimension screenSize = getToolkit().getScreenSize(); + Dimension frameSize = this.getSize(); + frameSize.height = Math.min(screenSize.height, frameSize.height); + frameSize.width = Math.min(screenSize.width, frameSize.width); + setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); + addMenu(); + addButton(); + try + { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + SwingUtilities.updateComponentTreeUI(this); + } + catch (Exception e) + { + } + setResizable(false); + setVisible(true); + setDefaultCloseOperation(EXIT_ON_CLOSE); + fileText.setFocusable(false); + } + + // Menu set + private void addMenu() + { + JMenuBar mb = new JMenuBar(); + // 一级菜单 + JMenu conf = new JMenu(" 系 统 "); + // 子菜单 + JMenuItem exit = new JMenuItem("退出"); + exit.addActionListener(event -> System.exit(0)); + conf.add(exit); + mb.add(conf); + JMenu help = new JMenu(" 帮 助 "); + JMenuItem about = new JMenuItem("关于工具"); + about.addActionListener((ActionEvent event) -> JOptionPane.showMessageDialog(null, "二维码应用工具 V1.0,00fly 于2023年3月。\n", "关于本工具", JOptionPane.INFORMATION_MESSAGE)); + help.add(about); + mb.add(help); + setJMenuBar(mb); + } + + // JButton set + private void addButton() + { + panel.setLayout(null); + getContentPane().add(panel); + + JLabel textLabel = new JLabel("文件内容"); + textLabel.setBounds(20, 10, 120, 18); + panel.add(textLabel); + + JLabel fileLabel = new JLabel(" 待生成QR原始文件"); + fileLabel.setBounds(30, 410, 240, 18); + panel.add(fileLabel); + + textArea.setEditable(false); + + JScrollPane scroll = new JScrollPane(textArea); + scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + scroll.setBounds(20, 30, 850, 360); + panel.add(scroll); + + fileText.setBounds(150, 410, 450, 24); + fileText.setText(new File(" ").getAbsolutePath().trim()); + fileText.setToolTipText("选择需要生成二维码图片的原始文本文件,包含xml、java、yaml、md等"); + panel.add(fileText); + fileDirBrowse.setBounds(610, 410, 80, 25); + fileDirBrowse.setToolTipText("选择需要生成二维码图片的原始文本文件,包含xml、java、yaml、md等"); + fileDirBrowse.addActionListener(event -> { + String path = fileText.getText(); + File xmlfile = new File(path); + if (new File(fileText.getText()).exists()) + { + xmlfile = new File(path).getParentFile(); + } + JFileChooser fc = new JFileChooser(xmlfile); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + fc.setDialogTitle("原始文件选择"); + if (fc.showOpenDialog(null) == JFileChooser.CANCEL_OPTION) + { + return; + } + fc.setFileFilter(new FileFilter() + { + @Override + public boolean accept(File file) + { + String name = file.getName().toLowerCase(); + return Stream.of(acceptSuffix).anyMatch(t -> name.endsWith(t)); + } + + @Override + public String getDescription() + { + return ""; + } + }); + File f = fc.getSelectedFile(); + if (f != null && f.isFile()) + { + fileText.setText(f.getAbsolutePath()); + try + { + textArea.setText(FileUtils.readFileToString(f, StandardCharsets.UTF_8)); + qrButton.setEnabled(true); + } + catch (IOException e) + { + } + } + }); + panel.add(fileDirBrowse); + + removeButton.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + String content = textArea.getText(); + if (StringUtils.isNotBlank(content)) + { + content = content.replaceAll("\t", " ").replaceAll("((\r\n)|\n)[\\s\t ]*(\\1)+", "$1"); + textArea.setText(content); + } + } + }); + removeButton.setBounds(100, 450, 160, 30); + removeButton.add(qrButton); + panel.add(removeButton); + + qrButton.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + if (!qrButton.isEnabled()) + { + return; + } + try + { + String content = textArea.getText(); + BufferedImage image = QRCodeUtil.createImage(content, null, false); + new ShowDialog(image); + } + catch (Exception e1) + { + JOptionPane.showMessageDialog(null, "失败原因: " + e1.getMessage(), "二维码生成失败", JOptionPane.ERROR_MESSAGE); + } + } + }); + qrButton.setBounds(350, 450, 160, 30); + qrButton.setEnabled(false); + panel.add(qrButton); + + clearButton.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + textArea.setText(null); + qrButton.setEnabled(false); + } + }); + clearButton.setBounds(600, 450, 160, 30); + panel.add(clearButton); + } + + // Run + public static void main(String[] args) + { + SwingUtilities.invokeLater(() -> new QrCodeUI()); + } +} diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/ui/ShowDialog.java" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/ui/ShowDialog.java" new file mode 100644 index 0000000000000000000000000000000000000000..67359fbb6ccb998beb9d75d24c6ad4e85de2ef2a --- /dev/null +++ "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/ui/ShowDialog.java" @@ -0,0 +1,51 @@ +package com.fly.ui; + +import java.awt.Dimension; +import java.awt.image.BufferedImage; +import java.net.URL; + +import javax.swing.ImageIcon; +import javax.swing.JDialog; +import javax.swing.JLabel; + +/** + * + * qr显示弹出窗口 + * + * @author 00fly + * @version [版本号, 2023年3月3日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +public class ShowDialog extends JDialog +{ + private static final long serialVersionUID = 8010838747205419843L; + + public ShowDialog(BufferedImage image) + { + super(); + // 加载图标 + URL imgURL = getClass().getResource("/img/icon.gif"); + if (imgURL != null) + { + setIconImage(getToolkit().createImage(imgURL)); + } + setTitle("请扫描二维码"); + setSize(510, 530); + + // 自适应居中处理 + Dimension screenSize = getToolkit().getScreenSize(); + Dimension dialogSize = getSize(); + dialogSize.height = Math.min(screenSize.height, dialogSize.height); + dialogSize.width = Math.min(screenSize.width, dialogSize.width); + setLocation((screenSize.width - dialogSize.width) / 2, (screenSize.height - dialogSize.height) / 2); + + // 生成二维码图片 + add(new JLabel(new ImageIcon(image))); + + setVisible(true); + setResizable(false); + setAlwaysOnTop(true); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } +} diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/ui/SimpleQrCodeUI.java" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/ui/SimpleQrCodeUI.java" new file mode 100644 index 0000000000000000000000000000000000000000..60366e0e54dcab8889836daaad63c673e17cc0b6 --- /dev/null +++ "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/ui/SimpleQrCodeUI.java" @@ -0,0 +1,112 @@ +package com.fly.ui; + +import java.awt.BorderLayout; +import java.awt.HeadlessException; +import java.awt.Image; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.net.URL; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +import org.apache.commons.lang3.StringUtils; + +import com.fly.utils.QRCodeUtil; + +/** + * + * 文本二维码生成简化版本 + * + * @author 00fly + * @version [版本号, 2023年3月3日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +public class SimpleQrCodeUI extends JFrame +{ + private static final long serialVersionUID = -708209618541039567L; + + JTextArea textArea = new JTextArea(); + + JButton qrButton = new JButton("生 成 二 维 码"); + + public SimpleQrCodeUI() + throws HeadlessException + { + initComponent(); + + // 设定用户界面的外观 + try + { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + SwingUtilities.updateComponentTreeUI(this); + } + catch (Exception e) + { + } + + // 加载图标 + URL imgURL = getClass().getResource("/img/icon.gif"); + if (imgURL != null) + { + Image image = getToolkit().createImage(imgURL); + setIconImage(image); + } + this.setTitle("二维码应用工具 V1.0"); + this.setBounds(400, 200, 1200, 550); + this.setResizable(true); + this.setVisible(true); + this.setDefaultCloseOperation(EXIT_ON_CLOSE); + } + + /** + * 组件初始化 + * + * @see [类、类#方法、类#成员] + */ + private void initComponent() + { + textArea.setToolTipText("输入需要生成二维码图片的原始文本内容"); + + // JTextArea不自带滚动条,因此就需要把文本区放到一个滚动窗格中 + JScrollPane scroll = new JScrollPane(textArea); + scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + + this.add(scroll, BorderLayout.CENTER); + this.add(qrButton, BorderLayout.SOUTH); + qrButton.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + try + { + String content = textArea.getText(); + if (StringUtils.isNotBlank(content)) + { + content = content.replaceAll("\t", " ").replaceAll("((\r\n)|\n)[\\s\t ]*(\\1)+", "$1"); + BufferedImage image = QRCodeUtil.createImage(content, null, false); + new ShowDialog(image); + } + } + catch (Exception e1) + { + JOptionPane.showMessageDialog(null, e1.getMessage(), "二维码生成失败", JOptionPane.ERROR_MESSAGE); + } + } + }); + } + + public static void main(String[] args) + { + SwingUtilities.invokeLater(() -> new SimpleQrCodeUI()); + } +} diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/utils/BufferedImageLuminanceSource.java" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/utils/BufferedImageLuminanceSource.java" new file mode 100644 index 0000000000000000000000000000000000000000..9183262bb33acc367744c14f8318c0a1cab1fb5e --- /dev/null +++ "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/utils/BufferedImageLuminanceSource.java" @@ -0,0 +1,108 @@ +package com.fly.utils; + +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; + +import com.google.zxing.LuminanceSource; + +public class BufferedImageLuminanceSource extends LuminanceSource +{ + private final BufferedImage image; + + private final int left; + + private final int top; + + public BufferedImageLuminanceSource(BufferedImage image) + { + this(image, 0, 0, image.getWidth(), image.getHeight()); + } + + public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) + { + super(width, height); + + int sourceWidth = image.getWidth(); + int sourceHeight = image.getHeight(); + if (left + width > sourceWidth || top + height > sourceHeight) + { + throw new IllegalArgumentException("Crop rectangle does not fit within image data."); + } + + for (int y = top; y < top + height; y++) + { + for (int x = left; x < left + width; x++) + { + if ((image.getRGB(x, y) & 0xFF000000) == 0) + { + image.setRGB(x, y, 0xFFFFFFFF); // = white + } + } + } + + this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY); + this.image.getGraphics().drawImage(image, 0, 0, null); + this.left = left; + this.top = top; + } + + @Override + public byte[] getRow(int y, byte[] row) + { + if (y < 0 || y >= getHeight()) + { + throw new IllegalArgumentException("Requested row is outside the image: " + y); + } + int width = getWidth(); + if (row == null || row.length < width) + { + row = new byte[width]; + } + image.getRaster().getDataElements(left, top + y, width, 1, row); + return row; + } + + @Override + public byte[] getMatrix() + { + int width = getWidth(); + int height = getHeight(); + int area = width * height; + byte[] matrix = new byte[area]; + image.getRaster().getDataElements(left, top, width, height, matrix); + return matrix; + } + + @Override + public boolean isCropSupported() + { + return true; + } + + @Override + public LuminanceSource crop(int left, int top, int width, int height) + { + return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height); + } + + @Override + public boolean isRotateSupported() + { + return true; + } + + @Override + public LuminanceSource rotateCounterClockwise() + { + int sourceWidth = image.getWidth(); + int sourceHeight = image.getHeight(); + AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth); + BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY); + Graphics2D g = rotatedImage.createGraphics(); + g.drawImage(image, transform, null); + g.dispose(); + int width = getWidth(); + return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width); + } +} \ No newline at end of file diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/utils/QRCodeUtil.java" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/utils/QRCodeUtil.java" new file mode 100644 index 0000000000000000000000000000000000000000..cab01acf3f73999d08f9e2ef8269f6eceaa8c2e3 --- /dev/null +++ "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/java/com/fly/utils/QRCodeUtil.java" @@ -0,0 +1,153 @@ +package com.fly.utils; + +import java.awt.BasicStroke; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Shape; +import java.awt.geom.RoundRectangle2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Hashtable; + +import javax.imageio.ImageIO; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.BinaryBitmap; +import com.google.zxing.DecodeHintType; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatReader; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.Result; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.common.HybridBinarizer; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; + +public class QRCodeUtil +{ + /** + * 二维码尺寸 + */ + private static final int QRCODE_SIZE = 500; + + /** + * LOGO宽度 + */ + private static final int WIDTH = 60; + + /** + * LOGO高度 + */ + private static final int HEIGHT = 60; + + /** + * 给定内容、图标生成二维码图片 + * + * @param content 內容 + * @param imgURL 图标 + * @param needCompress 是否压缩尺寸 + * @return + * @throws Exception + * @see [类、类#方法、类#成员] + */ + public static BufferedImage createImage(String content, URL imgURL, boolean needCompress) + throws Exception + { + Hashtable hints = new Hashtable<>(); + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); + hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8); + hints.put(EncodeHintType.MARGIN, 1); + BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints); + int width = bitMatrix.getWidth(); + int height = bitMatrix.getHeight(); + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < width; x++) + { + for (int y = 0; y < height; y++) + { + image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); + } + } + if (imgURL == null) + { + return image; + } + // 插入图片 + insertImage(image, imgURL, needCompress); + return image; + } + + private static void insertImage(BufferedImage source, URL imgURL, boolean needCompress) + throws Exception + { + if (imgURL == null) + { + System.err.println("文件不存在!"); + return; + } + Image src = ImageIO.read(imgURL); + int width = src.getWidth(null); + int height = src.getHeight(null); + if (needCompress) + { + // 压缩LOGO + width = Math.min(width, WIDTH); + height = Math.min(height, HEIGHT); + Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH); + BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics g = tag.getGraphics(); + g.drawImage(image, 0, 0, null); + g.dispose(); + src = image; + } + // 插入LOGO + Graphics2D graph = source.createGraphics(); + int x = (QRCODE_SIZE - width) / 2; + int y = (QRCODE_SIZE - height) / 2; + graph.drawImage(src, x, y, width, height, null); + Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6); + graph.setStroke(new BasicStroke(3f)); + graph.draw(shape); + graph.dispose(); + } + + /** + * 解析二维码图 + * + * @param file + * @return + * @throws Exception + * @see [类、类#方法、类#成员] + */ + public static String decode(File file) + throws Exception + { + BufferedImage image = ImageIO.read(file); + if (image == null) + { + return null; + } + BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image); + BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); + Hashtable hints = new Hashtable<>(); + hints.put(DecodeHintType.CHARACTER_SET, StandardCharsets.UTF_8.name()); + Result result = new MultiFormatReader().decode(bitmap, hints); + return result.getText(); + } + + /** + * 解析二维码图 + * + * @param path + * @return + * @throws Exception + * @see [类、类#方法、类#成员] + */ + public static String decode(String path) + throws Exception + { + return decode(new File(path)); + } +} \ No newline at end of file diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/resources/img/icon.gif" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/resources/img/icon.gif" new file mode 100644 index 0000000000000000000000000000000000000000..8a108d9533617797078de136cb96a826941f8f85 Binary files /dev/null and "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/resources/img/icon.gif" differ diff --git "a/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/resources/log4j2.xml" "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/resources/log4j2.xml" new file mode 100644 index 0000000000000000000000000000000000000000..6f92a68617566e13a094682c8623fcc1c5b82408 --- /dev/null +++ "b/\347\216\251\350\275\254\344\272\214\347\273\264\347\240\201-\346\262\241\347\275\221\347\273\234\344\271\237\350\203\275\344\274\240\346\226\207\345\255\227/src/main/resources/log4j2.xml" @@ -0,0 +1,87 @@ + + + + + logs + qrcode + %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file