使用二维码创建与解析的时候,必须得先导入zxing.jar或者使用(core-3.4.0.jar以及javase-3.4.0.jar)
项目总体组成如下:
CodeServlet二维码生成类:
package com.sxt.servlet;
import com.sxt.utils.ZXingCodeEncodeUtils;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@WebServlet("/code.action")
public class CodeServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//生成图片
//BufferedImage codeImage= ZXingCodeEncodeUtils.createZXingCodeNormal("洲洲",300,300);
InputStream logoStream=ZXingCodeEncodeUtils.class.getClassLoader().getResourceAsStream("4.jpg");
BufferedImage codeImage=ZXingCodeEncodeUtils.createZxingCodeUseLogo("洲洲",300,300,logoStream);
ServletOutputStream outputStream=resp.getOutputStream();
ImageIO.write(codeImage,"JPEG",outputStream);
outputStream.close();
}
}
DeCodeServlet二维码解析类:
package com.sxt.servlet;
import com.sxt.utils.ZXingCodeDecodeUtils;
import com.sxt.utils.ZXingCodeEncodeUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/decode.action")
@MultipartConfig
public class DeCodeServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Part part=req.getPart("mf");
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
String string=ZXingCodeDecodeUtils.decodeCodeStream(part.getInputStream());
PrintWriter out=resp.getWriter();
out.write(string);
out.flush();
out.close();
}
}
ZXingCodeEncodeUtils二维码生成工具类
package com.sxt.utils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.EnumMap;
/**
* 生成二维码
*/
public class ZXingCodeEncodeUtils {
//声明颜色
//二维码颜色
private static final int BLACK=0xFF000000;
//二维码背景颜色
private static final int WHITE=0xFFFFFFFF;
//二维码格式参数
private static final EnumMap<EncodeHintType,Object>hints=new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
static {
/**
* 二维码的纠错级别(排错率),4个级别:L(7%)、M(15%)、Q(25%)、H(30%)(最好H)
* 纠错信息同样存储在二维码中,纠错级别越高,纠错信息占用的空间越多,那么能存储的有用信息就越少;共有四级;选择M,扫描速度快
*/
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//二维码边界空白大小1,2,3,4(4默认为最大)
hints.put(EncodeHintType.MARGIN,1);
hints.put(EncodeHintType.CHARACTER_SET,"UTF-8");//设置放入字符的编码
}
/**
* 生成二维码保存到D盘
*/
public static void createZXingSaveToDisk(String content,
int width,int height,
String savePath,String imageType) {
try {
BufferedImage image=createZXingCodeNormal(content,width,height);
//保存图片到硬盘
File file=new File(savePath);
if(!file.exists()){
file.createNewFile();
}
ImageIO.write(image,imageType,file);
System.out.println("生成成功");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 生成二维码,返回图片对象
* @param content
* @param width
* @param height
*/
public static BufferedImage createZXingCodeNormal(String content,int width,int height) {
try {
//生成二维码的相应信息 黑色条形继续放大 则可以看到存储的信息(二维数组)
BitMatrix encode = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
//得到二维码的宽度
int code_width = encode.getWidth();
//得到二维码的高度
int code_height = encode.getHeight();
//创建图片
BufferedImage image = new BufferedImage(code_width,code_height, BufferedImage.TYPE_INT_RGB);
//遍历二维数组,把二维码的信息写到图片里面
for (int i = 0; i < code_width; i++) {
for (int j = 0; j < code_height; j++) {
//设置图片的基本的基本属性
image.setRGB(i, j, encode.get(i, j) ? BLACK : WHITE);
}
}
System.out.println("生成成功");
return image;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 生成一张带logo的二维码
* logoStream:logo流对象
*/
public static void createZxingCodeUseLogoSaveDisk(String content, int width, int height, String savePath, String imageType, InputStream logoStream){
try {
BufferedImage codeImage=createZxingCodeUseLogo(content,width,height,logoStream);
//保存图片到硬盘
File file=new File(savePath);
if(!file.exists()){
file.createNewFile();
}
ImageIO.write(codeImage,imageType,file);
System.out.println("生成成功");
} catch (IOException e) {
e.printStackTrace();
return;
}
}
public static BufferedImage createZxingCodeUseLogo(String content, int width, int height, InputStream logoStream){
//生成二维码图片
BufferedImage codeNormal= createZXingCodeNormal(content,width,height);
BufferedImage logoImage;
if(codeNormal!=null){
//判断logoStream是否为空
if(logoStream!=null){
//拿到可以操作当前图片的画笔
Graphics2D graphics=codeNormal.createGraphics();
try {
//得到logo图片的原始对象
logoImage=ImageIO.read(logoStream);
//得到logo对象的原始宽高
int old_logo_width=logoImage.getWidth();
int old_logo_height=logoImage.getHeight();
//得到二维码的宽高
int code_width=codeNormal.getWidth();
int code_height=codeNormal.getHeight();
//得出logo在二维码里面能够存在的最大值
int logo_max_width=code_width/5;
int logo_max_height=code_height/5;
//计算logo可用的宽和高
int logo_width=logo_max_width<old_logo_width?logo_max_width:old_logo_width;
int logo_height=logo_max_height<old_logo_height?logo_max_height:old_logo_height;
//计算logo的开始点的坐标
int x=(code_width-logo_width)/2;
int y=(code_height-logo_height)/2;
/**
* arg0:logo图片对象
* arg1:开始画的x轴坐标
* arg2:开始画的y轴坐标
* arg3:要画的x轴的长度
* arg4:要画的y轴的长度
* arg5 null
*/
graphics.drawImage(logoImage,x,y,logo_width,logo_height,null);
graphics.setStroke(new BasicStroke(2));
graphics.setColor(Color.RED);
//画白色边框
graphics.drawRoundRect(x,y,logo_width,logo_height,15,15);
graphics.dispose();//让画上去的内容生效
return codeNormal;
} catch (IOException e) {
e.printStackTrace();
System.out.println("生成失败");
}
// 把logoStream转成图片对象
}
}else {
System.out.println("生成失败");
}
return null;
}
public static void main(String[] args) {
// createZXingSaveToDisk("洲洲",400,
// 400,"D:/image/zhouzhou.gif",
// "JPEG");
InputStream logoStream=ZXingCodeEncodeUtils.class.getClassLoader().getResourceAsStream("4.jpg");
createZxingCodeUseLogoSaveDisk("洲洲",400,400,"D:/image/zhouzhou.gif", "JPEG",logoStream);
}
}
ZXingCodeDecodeUtils二维码解析类
package com.sxt.utils;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.EnumMap;
/**
* 解析二维码
*/
public class ZXingCodeDecodeUtils {
//二维码格式参数
private static final EnumMap<DecodeHintType,Object>decodeHints=new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
static {
decodeHints.put(DecodeHintType.CHARACTER_SET,"UTF-8");
}
/**
* 解析文件
* @param args
*/
public static String decodeCodeFile(String path){
File file=new File(path);
if(file.exists()){
//把文件转成图片对象
try {
String context=decodeCodeStream(new FileInputStream(file));
return context;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}else {
return null;
}
}
/**
* 解析流
* @param args
*/
public static String decodeCodeStream(InputStream is){
if(is!=null){
try {
BufferedImage image=ImageIO.read(is);
//解析二维码
LuminanceSource source=new BufferedImageLuminanceSource(image);
Binarizer binarizer=new HybridBinarizer(source);
BinaryBitmap binaryBitmap=new BinaryBitmap(binarizer);
MultiFormatReader reader=new MultiFormatReader();
Result result=reader.decode(binaryBitmap,decodeHints);
String context=result.getText();
return context;
}catch (Exception e){
e.printStackTrace();
return null;
}
}else {
return null;
}
}
public static void main(String[] args) throws FileNotFoundException {
// System.out.println(decodeCodeFile("D:/image/zhouzhou.gif"));
System.out.println(decodeCodeStream(new FileInputStream(new File("D:/image/zhouzhou.gif"))));
}
}
前端页面:
<%--
Created by IntelliJ IDEA.
User: Lenovo
Date: 2019/10/26
Time: 10:25
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<img src="/code.action">
<form action="/decode.action" method="post" enctype="multipart/form-data">
<input type="file" name="mf">
<input type="submit" value="解析">
</form>
</body>
</html>
运行结果如下:
手机扫描结果: