二維碼工具類,提供多種生成二維碼、解析二維碼的方法,包括中間logo的二維碼等方法。html
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.2.0</version>
</dependency>java
QrcodeUtils.java 源碼:apache
import java.awt.Color; import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.imageio.ImageIO; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.SystemUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.zxing.BinaryBitmap; import com.google.zxing.DecodeHintType; import com.google.zxing.LuminanceSource; import com.google.zxing.MultiFormatReader; import com.google.zxing.Reader; import com.google.zxing.ReaderException; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; /** * 二維碼工具類 * */ public class QrcodeUtils { private static final transient Logger LOGGER = LoggerFactory.getLogger(QrcodeUtils.class); private static transient String DEFAULT_FORMAT = "jpg"; private static transient int DEFAULT_WIDTH = 200; private static transient int DEFAULT_HEIGHT = 200; static { try { final String[] foo = new String[] { "240", "240" }; final String format = "jpg"; if (StringUtils.isNotBlank(format)) { DEFAULT_FORMAT = StringUtils.strip(format).toLowerCase(); } if (ArrayUtils.isNotEmpty(foo) && foo.length == 2) { Integer tmpWidth = Integer.valueOf(foo[0]); Integer tmpHeight = Integer.valueOf(foo[1]); if (tmpWidth > 0 && tmpHeight > 0) { DEFAULT_WIDTH = tmpWidth; DEFAULT_HEIGHT = tmpHeight; } else { LOGGER.warn("qrcode size must be lager than zero."); } } } catch (Throwable e) { LOGGER.warn("read default qrcode size config error: ", e); } } /** * 生成二維碼(無中間logo) * * @param content * 二維碼文本內容 * @param destFile * 輸出文件 */ public static final void gen(final String content, File destFile) throws Exception { gen(content, destFile, DEFAULT_WIDTH, DEFAULT_HEIGHT); } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param destFile * 目的文件 * @param logoFile * 中間logo文件 * */ public static final void gen(final String content, final File destFile, final File logoFile) throws Exception { gen(content, destFile, logoFile, DEFAULT_WIDTH, DEFAULT_HEIGHT); } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param destFile * 目的文件 * @param logoFile * 中間logo文件 * @param width * 寬度 * @param height * 高度 */ public static final void gen(final String content, final File destFile, final File logoFile, int width, int height) throws Exception { FolderUtils.mkdirs(destFile.getParent()); OutputStream output = null; InputStream input = null; try { output = new BufferedOutputStream(new FileOutputStream(destFile)); if (logoFile != null && logoFile.exists() && logoFile.isFile()) { input = new BufferedInputStream(new FileInputStream(logoFile)); } gen(content, output, input, width, height); } catch (FileNotFoundException e) { e.printStackTrace(); throw new Exception(e); } finally { IOUtils.closeQuietly(output); IOUtils.closeQuietly(input); } } /** * 生成二維碼(無中間logo) * * @param content * 二維碼文本內容 * @param destFile * 輸出文件 * @param width * 寬度 * @param height * 高度 */ public static final void gen(final String content, File destFile, int width, int height) throws Exception { FolderUtils.mkdirs(destFile.getParent()); OutputStream output = null; try { output = new BufferedOutputStream(new FileOutputStream(destFile)); gen(content, output, width, height); } catch (FileNotFoundException e) { e.printStackTrace(); throw new Exception(e); } catch (Exception e) { throw e; } finally { IOUtils.closeQuietly(output); } } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param output * 輸出流 */ public static final void gen(final String content, final OutputStream output) throws Exception { gen(content, output, DEFAULT_WIDTH, DEFAULT_HEIGHT); } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param output * 輸出流 * @param logoInput * 中間logo輸入流,爲空時中間無logo */ public static final void gen(final String content, final OutputStream output, final InputStream logoInput) throws Exception { gen(content, output, logoInput, DEFAULT_WIDTH, DEFAULT_HEIGHT); } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param output * 輸出流 * @param logoInput * 中間logo輸入流,爲空時中間無logo * @param width * 寬度 * @param height * 高度 */ public static final void gen(final String content, final OutputStream output, final InputStream logoInput, int width, int height) throws Exception { gen(content, output, logoInput, width, height, ErrorCorrectionLevel.M); } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param output * 輸出流 * @param logoInput * 中間logo輸入流,爲空時中間無logo * @param width * 寬度 * @param height * 高度 * @param errorCorrectionLevel * 容錯級別 */ public static final void gen(final String content, final OutputStream output, final InputStream logoInput, int width, int height, ErrorCorrectionLevel errorCorrectionLevel) throws Exception { if (StringUtils.isEmpty(content)) { throw new IllegalArgumentException("qr code content cannot be empty."); } if (output == null) { throw new IllegalArgumentException("qr code output stream cannot be null."); } final BitMatrix matrix = MatrixToImageWriterEx.createQRCode(content, width, height, errorCorrectionLevel); if (logoInput == null) { try { MatrixToImageWriter.writeToStream(matrix, DEFAULT_FORMAT, output); return; } catch (IOException e) { e.printStackTrace(); throw new Exception(e); } } final MatrixToLogoImageConfig logoConfig = new MatrixToLogoImageConfig(Color.BLUE, 4); final String destPath = FilenameUtils.normalizeNoEndSeparator(SystemUtils.getJavaIoTmpDir() + File.separator + UUID.randomUUID().toString() + ".tmp"); InputStream tmpInput = null; final File destFile = new File(destPath); try { MatrixToImageWriterEx.writeToFile(matrix, DEFAULT_FORMAT, destPath, logoInput, logoConfig); tmpInput = new BufferedInputStream(new FileInputStream(destFile)); IOUtils.copy(tmpInput, output); } catch (IOException e) { e.printStackTrace(); throw new Exception(e); } finally { IOUtils.closeQuietly(tmpInput); destFile.delete(); } } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param output * 輸出流 * @param width * 寬度 * @param height * 高度 */ public static final void gen(final String content, final OutputStream output, int width, int height) throws Exception { gen(content, output, null, width, height); } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param destPath * 輸出文件路徑 */ public static final void gen(final String content, final String destPath) throws Exception { gen(content, destPath, DEFAULT_WIDTH, DEFAULT_HEIGHT); } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param destPath * 輸出文件路徑 * @param width * 寬度 * @param height * 高度 */ public static final void gen(final String content, final String destPath, int width, int height) throws Exception { gen(content, new File(destPath), width, height); } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param destPath * 目的文件路徑 * @param logoPath * 中間logo文件路徑 */ public static final void gen(final String content, final String destPath, final String logoPath) throws Exception { gen(content, destPath, logoPath, DEFAULT_WIDTH, DEFAULT_HEIGHT); } /** * 生成二維碼 * * @param content * 二維碼文本內容 * @param destPath * 目的文件路徑 * @param logoPath * 中間logo文件路徑 * @param width * 寬度 * @param height * 高度 */ public static final void gen(final String content, final String destPath, final String logoPath, int width, int height) throws Exception { File foo = new File(destPath); File bar = new File(logoPath); gen(content, foo, bar, width, height); } /** * 解析二維碼 * * @param input * 二維碼輸入流 */ public static final String parse(InputStream input) throws Exception { Reader reader = null; BufferedImage image; try { image = ImageIO.read(input); if (image == null) { throw new Exception("cannot read image from inputstream."); } final LuminanceSource source = new BufferedImageLuminanceSource(image); final BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); final Map<DecodeHintType, String> hints = new HashMap<DecodeHintType, String>(); hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); // 解碼設置編碼方式爲:utf-8, reader = new MultiFormatReader(); return reader.decode(bitmap, hints).getText(); } catch (IOException e) { e.printStackTrace(); throw new Exception("parse QR code error: ", e); } catch (ReaderException e) { e.printStackTrace(); throw new Exception("parse QR code error: ", e); } } /** * 解析二維碼 * * @param url * 二維碼url */ public static final String parse(URL url) throws Exception { InputStream in = null; try { in = url.openStream(); return parse(in); } catch (IOException e) { e.printStackTrace(); throw new Exception("parse QR code error: ", e); } finally { IOUtils.closeQuietly(in); } } /** * 解析二維碼 * * @param file * 二維碼圖片文件 */ public static final String parse(File file) throws Exception { InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(file)); return parse(in); } catch (FileNotFoundException e) { e.printStackTrace(); throw new Exception("parse QR code error: ", e); } finally { IOUtils.closeQuietly(in); } } /** * 解析二維碼 * * @param filePath * 二維碼圖片文件路徑 */ public static final String parse(String filePath) throws Exception { InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(filePath)); return parse(in); } catch (FileNotFoundException e) { e.printStackTrace(); throw new Exception("parse QR code error: ", e); } finally { IOUtils.closeQuietly(in); } } } MatrixToImageWriterEx.java 源碼: import java.awt.BasicStroke; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Hashtable; import javax.imageio.ImageIO; import org.apache.commons.io.IOUtils; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.client.j2se.MatrixToImageConfig; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; class MatrixToImageWriterEx { private static final MatrixToLogoImageConfig DEFAULT_CONFIG = new MatrixToLogoImageConfig(); /** * 根據內容生成二維碼數據 * * @param content * 二維碼文字內容[爲了信息安全性,通常都要先進行數據加密] * @param width * 二維碼照片寬度 * @param height * 二維碼照片高度 * @param errorCorrectionLevel * 糾錯等級 * @return a {@link com.google.zxing.common.BitMatrix} object. * @since 0.0.7 */ public static BitMatrix createQRCode(String content, int width, int height, ErrorCorrectionLevel errorCorrectionLevel) { Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>(); // 設置字符編碼 hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); // 指定糾錯等級 hints.put(EncodeHintType.ERROR_CORRECTION, errorCorrectionLevel); BitMatrix matrix = null; try { matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); } catch (WriterException e) { e.printStackTrace(); } return matrix; } /** * 根據內容生成二維碼數據 * * @param content * 二維碼文字內容[爲了信息安全性,通常都要先進行數據加密] * @param width * 二維碼照片寬度 * @param height * 二維碼照片高度 * @return a {@link com.google.zxing.common.BitMatrix} object. * @since 0.0.7 */ public static BitMatrix createQRCode(String content, int width, int height) { return createQRCode(content, width, height, ErrorCorrectionLevel.H); } /** * 寫入二維碼、以及將照片logo寫入二維碼中 * * @param matrix * 要寫入的二維碼 * @param format * 二維碼照片格式 * @param imagePath * 二維碼照片保存路徑 * @param logoPath * logo路徑 * @throws java.io.IOException * if any. * @since 0.0.7 */ public static void writeToFile(BitMatrix matrix, String format, String imagePath, String logoPath) throws IOException { InputStream input = null; try { input = new BufferedInputStream(new FileInputStream(logoPath)); writeToFile(matrix, format, imagePath, input); } catch (IOException e) { throw e; } finally { IOUtils.closeQuietly(input); } } /** * <p> * writeToFile. * </p> * * @param matrix * a {@link com.google.zxing.common.BitMatrix} object. * @param format * a {@link java.lang.String} object. * @param imagePath * a {@link java.lang.String} object. * @param logoInputStream * a {@link java.io.InputStream} object. * @throws java.io.IOException * if any. * @since 0.0.7 */ public static void writeToFile(BitMatrix matrix, String format, String imagePath, InputStream logoInputStream) throws IOException { MatrixToImageWriter.writeToPath(matrix, format, new File(imagePath).toPath(), new MatrixToImageConfig()); // 添加logo圖片, 此處必定須要從新進行讀取,而不能直接使用二維碼的BufferedImage 對象 BufferedImage img = ImageIO.read(new File(imagePath)); MatrixToImageWriterEx.overlapImage(img, format, imagePath, logoInputStream, DEFAULT_CONFIG); } /** * 寫入二維碼、以及將照片logo寫入二維碼中 * * @param matrix * 要寫入的二維碼 * @param format * 二維碼照片格式 * @param imagePath * 二維碼照片保存路徑 * @param logoPath * logo路徑 * @param logoConfig * logo配置對象 * @throws java.io.IOException * if any. * @since 0.0.7 */ public static void writeToFile(BitMatrix matrix, String format, String imagePath, InputStream logoPath, MatrixToLogoImageConfig logoConfig) throws IOException { MatrixToImageWriter.writeToPath(matrix, format, new File(imagePath).toPath(), new MatrixToImageConfig()); // 添加logo圖片, 此處必定須要從新進行讀取,而不能直接使用二維碼的BufferedImage 對象 BufferedImage img = ImageIO.read(new File(imagePath)); MatrixToImageWriterEx.overlapImage(img, format, imagePath, logoPath, logoConfig); } /** * 將照片logo添加到二維碼中間 * * @param image * 生成的二維碼照片對象 * @param imagePath * 照片保存路徑 * @param imagePath * 照片保存路徑 * @param imagePath * 照片保存路徑 * @param imagePath * 照片保存路徑 * @param imagePath * 照片保存路徑 * @param imagePath * 照片保存路徑 * @param logoInputStream * logo輸入流 * @param formate * 照片格式 * @param logoConfig * a {@link cn.yicha.commons.qrcode.MatrixToLogoImageConfig} * object. * @since 0.0.7 */ public static void overlapImage(BufferedImage image, String formate, String imagePath, InputStream logoInputStream, MatrixToLogoImageConfig logoConfig) { try { BufferedImage logo = ImageIO.read(logoInputStream); Graphics2D g = image.createGraphics(); // 考慮到logo照片貼到二維碼中,建議大小不要超過二維碼的1/5; int width = image.getWidth() / logoConfig.getLogoPart(); int height = image.getHeight() / logoConfig.getLogoPart(); // logo起始位置,此目的是爲logo居中顯示 int x = (image.getWidth() - width) / 2; int y = (image.getHeight() - height) / 2; // 繪製圖 g.drawImage(logo, x, y, width, height, null); // 給logo畫邊框 // 構造一個具備指定線條寬度以及 cap 和 join 風格的默認值的實心 BasicStroke g.setStroke(new BasicStroke(logoConfig.getBorder())); g.setColor(logoConfig.getBorderColor()); g.drawRect(x, y, width, height); g.dispose(); // 寫入logo照片到二維碼 ImageIO.write(image, formate, new File(imagePath)); } catch (Exception e) { e.printStackTrace(); } } }
MatrixToLogoImageConfig.java 源碼:安全
import java.awt.Color; class MatrixToLogoImageConfig { // logo默認邊框顏色 /** Constant <code>DEFAULT_BORDERCOLOR</code> */ public static final Color DEFAULT_BORDERCOLOR = Color.RED; // logo默認邊框寬度 /** Constant <code>DEFAULT_BORDER=2</code> */ public static final int DEFAULT_BORDER = 2; // logo大小默認爲照片的1/5 /** Constant <code>DEFAULT_LOGOPART=5</code> */ public static final int DEFAULT_LOGOPART = 5; private final int border = DEFAULT_BORDER; private final Color borderColor; private final int logoPart; /** * Creates a default config with on color {@link #BLACK} and off color * {@link #WHITE}, generating normal black-on-white barcodes. * * @since 0.0.7 */ public MatrixToLogoImageConfig() { this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART); } /** * <p> * Constructor for MatrixToLogoImageConfig. * </p> * * @param borderColor * a {@link java.awt.Color} object. * @param logoPart * a int. * @since 0.0.7 */ public MatrixToLogoImageConfig(Color borderColor, int logoPart) { this.borderColor = borderColor; this.logoPart = logoPart; } /** * <p> * Getter for the field <code>borderColor</code>. * </p> * * @return a {@link java.awt.Color} object. * @since 0.0.7 */ public Color getBorderColor() { return borderColor; } /** * <p> * Getter for the field <code>border</code>. * </p> * * @return a int. * @since 0.0.7 */ public int getBorder() { return border; } /** * <p> * Getter for the field <code>logoPart</code>. * </p> * * @return a int. * @since 0.0.7 */ public int getLogoPart() { return logoPart; } }
文章轉載地址:http://www.cnblogs.com/zhoubang521/p/5200118.htmldom