Java 如何實現(xiàn)二維碼?

步驟1
第一步首先創(chuàng)建一個普通的 Maven 項目,然后要實現(xiàn)二維碼功能,我們肯定要使用別人提供好的 Jar 包,這里我用的是 google 提供的 jar,pom.xml 文件配置如下:
xml version="1.0"?encoding="UTF-8"?>
<project?xmlns="http://maven.apache.org/POM/4.0.0"
?????????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
?????????xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
????<modelVersion>4.0.0modelVersion>
????<groupId>org.javaboygroupId>
????<artifactId>QRCodeartifactId>
????<version>1.0-SNAPSHOTversion>
????<dependencies>
????????
????????<dependency>
????????????<groupId>com.google.zxinggroupId>
????????????<artifactId>coreartifactId>
????????????<version>3.3.0version>
????????dependency>
????dependencies>
project>步驟2
然后使用 google 提供的工具類,在項目根目錄下創(chuàng)建一個 util 包,將所需要的工具類放進去。
工具類1 (BufferedImageLuminanceSource)
不廢話,直接上代碼
/**
?* @author?bai
?* @date?2020/7/1 9:27
?*/
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);
????}
}工具類2 (QRCodeUtil)
這里面可以修改一些參數(shù),例如二維碼的尺寸,寬高等等。
/**
?* @author?bai
?* @date?2020/7/1 9:29
?*/
public?class?QRCodeUtil?{
????private?static?final?String CHARSET = "utf-8";
????private?static?final?String FORMAT_NAME = "JPG";
????// 二維碼尺寸
????private?static?final?int?QRCODE_SIZE = 300;
????// LOGO寬度
????private?static?final?int?WIDTH = 60;
????// LOGO高度
????private?static?final?int?HEIGHT = 60;
????private?static?BufferedImage createImage(String content, String imgPath, boolean?needCompress)?throws?Exception {
????????Hashtable hints = new?Hashtable();
????????hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
????????hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
????????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?(imgPath == null?|| "".equals(imgPath)) {
????????????return?image;
????????}
????????// 插入圖片
????????QRCodeUtil.insertImage(image, imgPath, needCompress);
????????return?image;
????}
????private?static?void?insertImage(BufferedImage source, String imgPath, boolean?needCompress)?throws?Exception {
????????File file = new?File(imgPath);
????????if?(!file.exists()) {
????????????System.err.println(""?+ imgPath + " 該文件不存在!");
????????????return;
????????}
????????Image src = ImageIO.read(new?File(imgPath));
????????int?width = src.getWidth(null);
????????int?height = src.getHeight(null);
????????if?(needCompress) { // 壓縮LOGO
????????????if?(width > WIDTH) {
????????????????width = WIDTH;
????????????}
????????????if?(height > HEIGHT) {
????????????????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();
????}
????public?static?void?encode(String content, String imgPath, String destPath, boolean?needCompress)?throws?Exception {
????????BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
????????mkdirs(destPath);
????????// String file = new Random().nextInt(99999999)+".jpg";
????????// ImageIO.write(image, FORMAT_NAME, new File(destPath+"/"+file));
????????ImageIO.write(image, FORMAT_NAME, new?File(destPath));
????}
????public?static?BufferedImage encode(String content, String imgPath, boolean?needCompress)?throws?Exception {
????????BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
????????return?image;
????}
????public?static?void?mkdirs(String destPath)?{
????????File file = new?File(destPath);
????????// 當文件夾不存在時,mkdirs會自動創(chuàng)建多層目錄,區(qū)別于mkdir.(mkdir如果父目錄不存在則會拋出異常)
????????if?(!file.exists() && !file.isDirectory()) {
????????????file.mkdirs();
????????}
????}
????public?static?void?encode(String content, String imgPath, String destPath)?throws?Exception {
????????QRCodeUtil.encode(content, imgPath, destPath, false);
????}
????// 被注釋的方法
????/*
?????* public static void encode(String content, String destPath, boolean
?????* needCompress) throws Exception { QRCodeUtil.encode(content, null, destPath,
?????* needCompress); }
?????*/
????public?static?void?encode(String content, String destPath)?throws?Exception {
????????QRCodeUtil.encode(content, null, destPath, false);
????}
????public?static?void?encode(String content, String imgPath, OutputStream output, boolean?needCompress)
????????????throws?Exception {
????????BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
????????ImageIO.write(image, FORMAT_NAME, output);
????}
????public?static?void?encode(String content, OutputStream output)?throws?Exception {
????????QRCodeUtil.encode(content, null, output, false);
????}
????public?static?String decode(File file)?throws?Exception {
????????BufferedImage image;
????????image = ImageIO.read(file);
????????if?(image == null) {
????????????return?null;
????????}
????????BufferedImageLuminanceSource source = new?BufferedImageLuminanceSource(image);
????????BinaryBitmap bitmap = new?BinaryBitmap(new?HybridBinarizer(source));
????????Result result;
????????Hashtable hints = new?Hashtable();
????????hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
????????result = new?MultiFormatReader().decode(bitmap, hints);
????????String resultStr = result.getText();
????????return?resultStr;
????}
????public?static?String decode(String path)?throws?Exception {
????????return?QRCodeUtil.decode(new?File(path));
????}
}啟動類
這一步就是調用方法,一般大家使用這種功能都是為了實現(xiàn)業(yè)務,例如常見的掃描二維碼跳轉鏈接(頁面),掃描二維碼出現(xiàn)文字等等。有些二維碼中間還帶有 Logo 這種圖片,將需要嵌入二維碼的圖片路徑準備好就沒有問題。
/**
?* @author bai
?* @date 2020/7/1 9:31
?*/
public?class?QRCodeApplication {
????public?static?void?main(String[] args) throws Exception {
????????// 存放在二維碼中的內容
????????// 二維碼中的內容可以是文字,可以是鏈接等
????????String?text = "http://www.baidu.com";
????????// 嵌入二維碼的圖片路徑
????????//String imgPath = "C:\\Users\\Administrator\\Pictures\\img\\dog.jpg";
????????// 生成的二維碼的路徑及名稱
????????String?destPath = "C:\\Users\\bai\\Pictures\\img\\code"?+ System.currentTimeMillis() + ".jpg";
????????//生成二維碼
????????QRCodeUtil.encode(text, null, destPath, true);
????????// 解析二維碼
????????String?str = QRCodeUtil.decode(destPath);
????????// 打印出解析出的內容
????????System.out.println(str);
????}
}效果截圖

源碼奉上
碼云:https://gitee.com/jian_bo_bai/QRCode
作者:紅顏禍水nvn
來源:http://suo.im/5R6ewH
?--END--
? 推薦
公眾號ID|javabaiwen
小編微信|619531440
每天分享技術干貨
視頻|電子書|面試題|開發(fā)經驗
評論
圖片
表情

