jfinal重写renderQrCode方法,不在本地磁盘生成二维码支持logo添加

并没有太多的变动,其实这段代码还有一个bug,就是logo上去是黑色的,丑的不得了。马赛克是我自己加的,实在是不好意思分享网址。

snipaste_20170718_171710.png

public class PhotoQrCode extends Render {

	private static final MatrixToImageConfig DEFAULT_CONFIG = new MatrixToImageConfig();

	private String content;
	private int width;
	private int height;
	private ErrorCorrectionLevel errorCorrectionLevel;

	/**
	 * 构造方法,经测试不指定纠错参数时,默认使用的是 'L' 最低级别纠错参数
	 * 
	 * @param content
	 *            二维码携带内容
	 * @param width
	 *            二维码宽度
	 * @param height
	 *            二维码高度
	 */
	public PhotoQrCode(String content, int width, int height) {
		init(content, width, height, null);
	}

	private void init(String content, int width, int height, ErrorCorrectionLevel errorCorrectionLevel) {
		if (StrKit.isBlank(content)) {
			throw new IllegalArgumentException("content 不能为空");
		}
		if (width < 0 || height < 0) {
			throw new IllegalArgumentException("width 与 height 不能小于 0");
		}
		this.content = content;
		this.width = width;
		this.height = height;
		this.errorCorrectionLevel = errorCorrectionLevel;
	}

	@Override
	public void render() {
		response.setHeader("Pragma", "no-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		response.setContentType("image/png");

		Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
		hints.put(EncodeHintType.MARGIN, 0); // 去掉白色边框,极度重要,否则二维码周围的白边会很宽
		if (errorCorrectionLevel != null) {
			hints.put(EncodeHintType.ERROR_CORRECTION, errorCorrectionLevel);
		}

		try {
			QRCodeWriter writer = new QRCodeWriter();
			BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);

			// 经测试 200 X 200 大小的二维码使用 "png" 格式只有 412B,而 "jpg" 却达到 15KB
			String path = request.getSession().getServletContext().getRealPath("/static/QrCodeImg/logo.png");
			overlapImage(bitMatrix, "png", response.getOutputStream(), path);
		} catch (Exception e) {
			throw new RenderException(e);
		}
	}

	/**
	 * 将照片logo添加到二维码中间
	 * @param matrix
	 * @param format
	 * @param stream
	 * @param logoPath
	 * @throws IOException
	 */
	public void overlapImage(BitMatrix matrix, String format, OutputStream stream, String logoPath) throws IOException {
		BufferedImage image = MatrixToImageWriter.toBufferedImage(matrix, DEFAULT_CONFIG);
		BufferedImage logo = ImageIO.read(new File(logoPath));
		Graphics2D g = image.createGraphics();
		// 考虑到logo照片贴到二维码中,建议大小不要超过二维码的1/5;
		int width = image.getWidth() / 3;
		int height = image.getHeight() / 3;
		// logo起始位置,此目的是为logo居中显示
		int x = (image.getWidth() - width) / 2;
		int y = (image.getHeight() - height) / 2;
		// 绘制图
		g.drawImage(logo, x, y, width, height, null);
		g.dispose();// 清理内存中的图片,返还内存给系统
		// 输出二维码
		ImageIO.write(image, format, stream);
	}
}


评论区

JFinal

2017-07-19 10:24

思路才是最重要的,能举一反三就很不错,感谢你的分享

我要做菜鸟

2017-08-01 09:05

就是一个流的事,哈哈~

你妹啊

2019-07-19 17:21

@JFinal 怎么使用