共计 6617 个字符,预计需要花费 17 分钟才能阅读完成。
引入 Google Zxing jar 包
<dependency> | |
<groupId>com.google.zxing</groupId> | |
<artifactId>core</artifactId> | |
<version>3.4.0</version> | |
</dependency> | |
<dependency> | |
<groupId>com.google.zxing</groupId> | |
<artifactId>javase</artifactId> | |
<version>3.4.0</version> | |
</dependency> |
工具类
package com.sunlands.feo.school.candlestick.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 org.springframework.stereotype.Component; | |
import javax.imageio.ImageIO; | |
import java.awt.*; | |
import java.awt.geom.RoundRectangle2D; | |
import java.awt.image.BufferedImage; | |
import java.io.File; | |
import java.io.IOException; | |
import java.io.OutputStream; | |
import java.util.Hashtable; | |
/** | |
* @author dongxie | |
*/ | |
@Component | |
public class QrCodeUtils { | |
private static final String CHARSET = "UTF-8"; | |
private static final String FORMAT_NAME = "JPG"; | |
/** | |
* 二维码尺寸 | |
*/ | |
private static final int QRCODE_SIZE = 300; | |
/** | |
* LOGO 宽度 | |
*/ | |
private static final int WIDTH = 60; | |
/** | |
* LOGO 高度 | |
*/ | |
private static final int HEIGHT = 60; | |
/** | |
* 创立二维码图片 | |
* | |
* @param content 内容 | |
* @param logoPath logo | |
* @param isCompress 是否压缩 Logo | |
* @return 返回二维码图片 | |
* @throws WriterException e | |
* @throws IOException BufferedImage | |
*/ | |
public static BufferedImage createImage(String content, String logoPath, boolean isCompress) throws WriterException, IOException {Hashtable<EncodeHintType, Object> hints = new Hashtable<>(); | |
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); | |
hints.put(EncodeHintType.CHARACTER_SET, CHARSET); | |
hints.put(EncodeHintType.MARGIN, 1); | |
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints); | |
int width = bitMatrix.getWidth(); | |
int height = bitMatrix.getHeight(); | |
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); | |
for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); | |
} | |
} | |
if (logoPath == null || "".equals(logoPath)) {return image;} | |
// 插入图片 | |
QrCodeUtils.insertImage(image, logoPath, isCompress); | |
return image; | |
} | |
/** | |
* 增加 Logo | |
* | |
* @param source 二维码图片 | |
* @param logoPath Logo | |
* @param isCompress 是否压缩 Logo | |
* @throws IOException void | |
*/ | |
private static void insertImage(BufferedImage source, String logoPath, boolean isCompress) throws IOException {File file = new File(logoPath); | |
if (!file.exists()) {return;} | |
Image src = ImageIO.read(new File(logoPath)); | |
int width = src.getWidth(null); | |
int height = src.getHeight(null); | |
// 压缩 LOGO | |
if (isCompress) {if (width > WIDTH) {width = WIDTH;} | |
if (height > HEIGHT) {height = HEIGHT;} | |
Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH); | |
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); | |
Graphics g = tag.getGraphics(); | |
// 绘制放大后的图 | |
g.drawImage(image, 0, 0, null); | |
g.dispose(); | |
src = image; | |
} | |
// 插入 LOGO | |
Graphics2D graph = source.createGraphics(); | |
int x = (QRCODE_SIZE - width) / 2; | |
int y = (QRCODE_SIZE - height) / 2; | |
graph.drawImage(src, x, y, width, height, null); | |
Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6); | |
graph.setStroke(new BasicStroke(3f)); | |
graph.draw(shape); | |
graph.dispose();} | |
/** | |
* 生成带 Logo 的二维码 | |
* | |
* @param content 二维码内容 | |
* @param logoPath Logo | |
* @param destPath 二维码输入门路 | |
* @param isCompress 是否压缩 Logo | |
* @throws Exception void | |
*/ | |
public static void create(String content, String logoPath, String destPath, boolean isCompress) throws Exception {BufferedImage image = QrCodeUtils.createImage(content, logoPath, isCompress); | |
mkdirs(destPath); | |
ImageIO.write(image, FORMAT_NAME, new File(destPath)); | |
} | |
/** | |
* 生成不带 Logo 的二维码 | |
* | |
* @param content 二维码内容 | |
* @param destPath 二维码输入门路 | |
*/ | |
public static void create(String content, String destPath) throws Exception {QrCodeUtils.create(content, null, destPath, false); | |
} | |
/** | |
* 生成带 Logo 的二维码,并输入到指定的输入流 | |
* | |
* @param content 二维码内容 | |
* @param logoPath Logo | |
* @param output 输入流 | |
* @param isCompress 是否压缩 Logo | |
*/ | |
public static void create(String content, String logoPath, OutputStream output, boolean isCompress) throws Exception {BufferedImage image = QrCodeUtils.createImage(content, logoPath, isCompress); | |
ImageIO.write(image, FORMAT_NAME, output); | |
} | |
/** | |
* 生成不带 Logo 的二维码,并输入到指定的输入流 | |
* | |
* @param content 二维码内容 | |
* @param output 输入流 | |
* @throws Exception void | |
*/ | |
public static void create(String content, OutputStream output) throws Exception {QrCodeUtils.create(content, null, output, false); | |
} | |
/** | |
* 二维码解析 | |
* | |
* @param file 二维码 | |
* @return 返回解析失去的二维码内容 | |
* @throws Exception String | |
*/ | |
public static String parse(File file) throws Exception { | |
BufferedImage image; | |
image = ImageIO.read(file); | |
if (image == null) {return null;} | |
BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image); | |
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); | |
Result result; | |
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(); | |
hints.put(DecodeHintType.CHARACTER_SET, CHARSET); | |
result = new MultiFormatReader().decode(bitmap, hints); | |
return result.getText();} | |
/** | |
* 二维码解析 | |
* | |
* @param path 二维码存储地位 | |
* @return 返回解析失去的二维码内容 | |
* @throws Exception String | |
*/ | |
public static String parse(String path) throws Exception {return QrCodeUtils.parse(new File(path)); | |
} | |
/** | |
* 判断门路是否存在,如果不存在则创立 | |
* | |
* @param dir 目录 | |
*/ | |
public static void mkdirs(String dir) {if (dir != null && !"".equals(dir)) {File file = new File(dir); | |
if (!file.isDirectory()) {file.mkdirs(); | |
} | |
} | |
} | |
} |
应用
package com.jiafly.blueberry.controller; | |
import com.jiafly.blueberry.common.utils.QrCodeUtils; | |
import org.apache.tomcat.util.http.fileupload.IOUtils; | |
import org.springframework.web.bind.annotation.GetMapping; | |
import org.springframework.web.bind.annotation.RequestMapping; | |
import org.springframework.web.bind.annotation.RequestParam; | |
import org.springframework.web.bind.annotation.RestController; | |
import javax.imageio.ImageIO; | |
import javax.imageio.stream.ImageOutputStream; | |
import javax.servlet.http.HttpServletResponse; | |
import java.awt.image.BufferedImage; | |
import java.io.ByteArrayInputStream; | |
import java.io.ByteArrayOutputStream; | |
import java.io.InputStream; | |
import java.io.OutputStream; | |
/** | |
* 二维码 | |
* | |
* @author dongxie | |
*/ | |
@RestController | |
@RequestMapping(path = "/qrcode") | |
public class QrCodeController {@GetMapping(path = "/create") | |
public void image(HttpServletResponse response, @RequestParam("content") String content) { | |
try {BufferedImage bufferedImage = QrCodeUtils.createImage(content, null, false); | |
responseImage(response, bufferedImage); | |
} catch (Exception e) { | |
// 异样自行处理,应用程序切忌间接打印堆栈日志,难定位 | |
e.printStackTrace();} | |
} | |
/** | |
* 设置 可通过 postman 或者浏览器间接浏览 | |
* | |
* @param response response | |
* @param bufferedImage bufferedImage | |
* @throws Exception e | |
*/ | |
public void responseImage(HttpServletResponse response, BufferedImage bufferedImage) throws Exception {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); | |
ImageOutputStream imageOutput = ImageIO.createImageOutputStream(byteArrayOutputStream); | |
ImageIO.write(bufferedImage, "jpeg", imageOutput); | |
InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); | |
OutputStream outputStream = response.getOutputStream(); | |
response.setContentType("image/jpeg"); | |
response.setCharacterEncoding("UTF-8"); | |
IOUtils.copy(inputStream, outputStream); | |
outputStream.flush();} | |
} |
正文完