基于 http://www.jfinal.com/share/361 修改,调用样例
render(new PhotoQrCode("xxx", 300, 300,"http://www.gtdblog.com/wp/wp-content/uploads/2017/09/meyou4-1.png",0xff9966));
源码
package com.rm.controller; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.net.URL; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.client.j2se.MatrixToImageConfig; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import com.jfinal.kit.StrKit; import com.jfinal.render.Render; import com.jfinal.render.RenderException; public class PhotoQrCode extends Render { private static 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, ErrorCorrectionLevel.H); } /** * 黑白图标 * * @param content * @param width * @param height * @param logoUrl * 网络图标地址 */ public PhotoQrCode(String content, int width, int height, String logoUrl) { init(content, width, height, ErrorCorrectionLevel.H); url = logoUrl; } /** * 指定二维码颜色,白色背景 * * @param content * @param width * @param height * @param logoUrl * 网络图标地址 * @param onColor * 二维码颜色 */ public PhotoQrCode(String content, int width, int height, String logoUrl, int onColor) { init(content, width, height, ErrorCorrectionLevel.H); url = logoUrl; onColor = (((onColor >> 24) & 0xff) > 0) ? onColor : onColor | 0xff000000; DEFAULT_CONFIG = new MatrixToImageConfig(onColor, 0xffffff); } /** * 指定前景 背景颜色 * * @param content * @param width * @param height * @param logoUrl * @param onColor * @param offColor */ public PhotoQrCode(String content, int width, int height, String logoUrl, int onColor, int offColor) { init(content, width, height, ErrorCorrectionLevel.H); url = logoUrl; DEFAULT_CONFIG = new MatrixToImageConfig(onColor, offColor); } private String url; 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(), url); } 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); if (logoPath != null) { // ImageIO.read(new File(logoPath)); BufferedImage logo = ImageIO.read(new URL(logoPath).openStream()); 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); } }