java的二维码生成和解析

JAVA的二维码的生成(带logo和不带logo)

准备工作

准备关于ZXing的二维码jar包
在这里插入图片描述
有关二维码jar包的下载
提取码:2uwl

二维码生成(带logo和不带logo)的代码

创建一个ZXingCodeEncodeUtils类

public class ZXingCodeEncodeUtils {
	// 二维码颜色,这里的0x表示16进制,FF表示透明度,后面6位是颜色
	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盘,不带logo
	 */
	public static void createZXingCodeSaveToDisk(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();
		}
	}

	/**
	 * 生成二维码返回图片对象
	 */
	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);
				}
			}
			return image;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	
	/**
	 * 生成一张带logo的二维码
	 * @param logoStream  logo的流对象
	 * 
	 */
	public static void createZxingCodeUseLogoSaveToDisk(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);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 生成一张带logo的二维码  返回BuffredeImage
	 * @param logoStream  logo的流对象
	 * 
	 */
	public static BufferedImage createZxingCodeUseLogo(String content, int width, int height,InputStream logoStream) {
		
		try {
			//生成二维码图片
			BufferedImage codeNormal = createZXingCodeNormal(content, width, height);
			if(null!=codeNormal) {
				//判断logoStream是否为空
				if(null!=logoStream) {
					//拿到可以操作当前图片的画笔
					Graphics2D graphics = codeNormal.createGraphics();
					//得到logo图片的对象
					BufferedImage 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在二维码里面能存在的最大值,因为logo最大占有75%
					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;
					
					/**
					 * logoImage logo图片对象
					 * x 开始画的x轴坐标
					 * y 开始画的y轴的坐
					 * logo_width 要画的x轴的长度
					 * logo_height 要画的y车的长度
					 * arg5  null
					 */
					graphics.drawImage(logoImage, x, y, logo_width, logo_height, null);
					
					graphics.setStroke(new BasicStroke(2));
					graphics.setColor(Color.WHITE);
					//画白色边框
					graphics.drawRoundRect(x, y, logo_width, logo_height, 15, 15);
					graphics.dispose();//让画上的去的内容生效
					return codeNormal;
				}
			}else {
				System.out.println("生成失败");
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("生成失败");
		}
		return null;
	}
	

	public static void main(String[] args) {
		//不带logo二维码调用
		//createZXingCodeSaveToDisk("小田", 400, 400, "D:/laolei.gif", "JPEG");
		//带logo调用,首先获取项目本地的logo图片
		InputStream logoStream=ZXingCodeEncodeUtils.class.getClassLoader().getResourceAsStream("logo.jpg");
		//二维码内容“小田”
		createZxingCodeUseLogoSaveToDisk("小田", 400, 400, "D:/xiaotian.gif", "JPEG", logoStream);
		
	}
}

综上可以看出带logo的二维码是在原来的二维码基础上画一个logo图标上去,但是logo占得面积不能超出二维码的25%,因为75%是二维码能识别的最大的扫描面积。

二维码的解析代码

两种方式解析本地二维码图片,创建一个ZXingCodeDecodeUtils类

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 content = decodeCodeStream(new FileInputStream(file));
				return content;
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}

		} else {
			return null;
		}
	}

	/**
	 * 解析流
	 * 
	 * @param args
	 */
	public static String decodeCodeStream(InputStream is) {
		if (null != is) {
			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 content = result.getText();
				return content;
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
		}
		return null;
	}

	public static void main(String[] args) throws FileNotFoundException {
	//方式1,文件路径方式
	//String string = decodeCodeFile("D:/xiaotian.gif");
		//方式2,流的方式
		String string = decodeCodeStream(new FileInputStream(new File("D:/xiaotian.gif")));
		System.out.println(string);
	}
}

拓展:在网页测试

编写测试Jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<img alt="" src="code.action" >


<form action="decode.action" method="post" enctype="multipart/form-data">
	<!--此处是一个表单提交给servlet-->
	<input type="file" name="mf">
	<input type="submit" value="解析">
</form>
</body>
</html>

编写第一个servlet类CodeServlet,用来生成二维码(带logo和不带logo)显示在网页

@WebServlet("/code.action")
public class CodeServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//生成带logo
		//BufferedImage codeImage=ZXingCodeEncodeUtils.createZXingCodeNormal("小田", 300, 300);
		//生成不带logo
		InputStream logoStream=this.getClass().getClassLoader().getResourceAsStream("logo.jpg");
		BufferedImage codeImage=ZXingCodeEncodeUtils.createZxingCodeUseLogo("小田", 300, 300, logoStream);
		//写在网页
		ServletOutputStream outputStream = response.getOutputStream();
		ImageIO.write(codeImage, "JPEG", outputStream);
		outputStream.close();
	}

}

编写第二个servlet类DeCodeServlet,用来解析二维码内容显示在网页

@WebServlet("/decode.action")
@MultipartConfig
public class DeCodeServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//获得文件
		Part part=request.getPart("mf");
		//修改响应和请求的编码格式
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		//调用解析二维码的类
		String string = ZXingCodeDecodeUtils.decodeCodeStream(part.getInputStream());
		PrintWriter out = response.getWriter();
		out.write(string);
		//刷新缓冲区
		out.flush();
		//关闭流
		out.close();
	}

}

总结

以上就是二维码的生成(带logo和不带logo)和解析,以及网页测试的例子。

你可能感兴趣的:(二维码,servlet)