java二维码解析 zxing

参照于这位同学的
已经封装好了 可直接调用

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>qrcode-utils</artifactId>
    <version>1.2</version>
</dependency>

大致上如下

<dependency>
	<groupId>com.google.zxing</groupId>
	<artifactId>core</artifactId>
	<version>3.4.1</version>
</dependency>
<dependency>
	<groupId>com.google.zxing</groupId>
	<artifactId>javase</artifactId>
	<version>3.4.1</version>
</dependency>
package cn.a2490.utils;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;

import javax.imageio.ImageIO;

import com.google.common.base.Charsets;
import com.google.common.collect.Maps;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
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 int DEFAULT_LENGTH = 400;// 生成二维码的默认边长,因为是正方形的,所以高度和宽度一致
	private static final String FORMAT = "jpg";// 生成二维码的格式

	/**
	 * 根据内容生成二维码数据
	 *
	 * @param content 二维码文字内容[为了信息安全性,一般都要先进行数据加密]
	 * @param length  二维码图片宽度和高度
	 */
	private static BitMatrix createQrcodeMatrix(String content, int length) {
		Map<EncodeHintType, Object> hints = Maps.newEnumMap(EncodeHintType.class);
		// 设置字符编码
		hints.put(EncodeHintType.CHARACTER_SET, Charsets.UTF_8.name());
		// 指定纠错等级
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);

		try {
			return new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, length, length, hints);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * 根据指定边长创建生成的二维码,允许配置logo属性
	 *
	 * @param content  二维码内容
	 * @param length   二维码的高度和宽度
	 * @param logoFile logo 文件对象,可以为空
	 * @return 二维码图片的字节数组
	 */
	public static byte[] createQrcode(String content, int length, File logoFile) {
		if (logoFile != null && !logoFile.exists()) {
			throw new IllegalArgumentException("请提供正确的logo文件!");
		}

		BitMatrix qrCodeMatrix = createQrcodeMatrix(content, length);
		if (qrCodeMatrix == null) {
			return null;
		}
		try {
			File file = Files.createTempFile("qrcode_", "." + FORMAT).toFile();

//			MatrixToImageWriter.writeToFile(qrCodeMatrix, FORMAT, file);
			MatrixToImageWriter.writeToPath(qrCodeMatrix, FORMAT, Paths.get(file.getAbsolutePath()));
			if (logoFile != null) {
				// 添加logo图片, 此处一定需要重新进行读取,而不能直接使用二维码的BufferedImage 对象
				BufferedImage img = ImageIO.read(file);
				overlapImage(img, FORMAT, file.getAbsolutePath(), logoFile);
			}

			return toByteArray(file);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 创建生成默认高度(400)的二维码图片 可以指定是否贷logo
	 *
	 * @param content  二维码内容
	 * @param logoFile logo 文件对象,可以为空
	 * @return 二维码图片的字节数组
	 */
	public static byte[] createQrcode(String content, File logoFile) {
		return createQrcode(content, DEFAULT_LENGTH, logoFile);
	}

	/**
	 * 将文件转换为字节数组, 使用MappedByteBuffer,可以在处理大文件时,提升性能
	 *
	 * @param file 文件
	 * @return 二维码图片的字节数组
	 */
	private static byte[] toByteArray(File file) {
		try (FileChannel fc = new RandomAccessFile(file, "r").getChannel();) {
			MappedByteBuffer byteBuffer = fc.map(MapMode.READ_ONLY, 0, fc.size()).load();
			byte[] result = new byte[(int) fc.size()];
			if (byteBuffer.remaining() > 0) {
				byteBuffer.get(result, 0, byteBuffer.remaining());
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 将logo添加到二维码中间
	 *
	 * @param image     生成的二维码图片对象
	 * @param imagePath 图片保存路径
	 * @param logoFile  logo文件对象
	 * @param format    图片格式
	 */
	private static void overlapImage(BufferedImage image, String format, String imagePath, File logoFile)
			throws IOException {
		try {
			BufferedImage logo = ImageIO.read(logoFile);
			Graphics2D g = image.createGraphics();
			// 考虑到logo图片贴到二维码中,建议大小不要超过二维码的1/5;
			int width = image.getWidth() / 5;
			int height = image.getHeight() / 5;
			// 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
			// logo默认边框宽度
			g.setStroke(new BasicStroke(2));
			// 边框颜色
			g.setColor(Color.RED);
			g.drawRect(x, y, width, height);

			g.dispose();
			// 写入logo图片到二维码
			ImageIO.write(image, format, new File(imagePath));
		} catch (Exception e) {
			throw new IOException("二维码添加logo时发生异常!", e);
		}
	}

	/**
	 * 解析二维码
	 *
	 * @param file 二维码文件内容
	 * @return 二维码的内容
	 */
	public static String decodeQrcode(File file) throws IOException, NotFoundException {
		BufferedImage image = ImageIO.read(file);
		LuminanceSource source = new BufferedImageLuminanceSource(image);
		Binarizer binarizer = new HybridBinarizer(source);
		BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
		Map<DecodeHintType, Object> hints = Maps.newEnumMap(DecodeHintType.class);
		hints.put(DecodeHintType.CHARACTER_SET, Charsets.UTF_8.name());
		return new MultiFormatReader().decode(binaryBitmap, hints).getText();
	}

	public static void main(String[] args) throws NotFoundException, IOException {
		String decodeQrcode = decodeQrcode(new File("\\Desktop\\1111.jpg"));
		System.out.println(decodeQrcode);
	}

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值