代码实现
/**
* 二维码生成
* 该方法可以有效去除生成的二维码的多余空白
* @param url 二维码跳转路径
* @param height 高
* @param width 宽
* @param imageType 图片格式
* @param hint 留白度
*/
public static String generateQRCodeFile(String url, int height, int width, String imageType, int hint){
try {
//生成二维码
BitMatrix matrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, width, height, getHints(hint));
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, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
//去除多余空白
BufferedImage distinctImage = removeWhiteBorder(image);
int disHeight = distinctImage.getHeight();
int disWidth = distinctImage.getWidth();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//去除空白后可能导致二维码图片变小,所以放大二维码
if(disHeight < height || disWidth < width){
BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = newImage.createGraphics();
AffineTransform af = new AffineTransform();
af.scale(width * 1.0 / disWidth, height * 1.0 / disHeight);
graphics.drawImage(distinctImage, af, null);
graphics.dispose();
ImageIO.write(newImage, imageType, outputStream);
}else{
ImageIO.write(distinctImage, imageType, outputStream);
}
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
FileItem fileItem = MtgiCommUtil.createFileItem(inputStream, "file." + imageType);
//上传到文件服务
FileUtil fileUtil = SpringUtil.getBean(FileUtil.class);
return fileUtil.getFileId(fileItem);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Zxing二维码参数设置
* @param hint 白边大小
*/
private static java.util.Map<EncodeHintType, Object> getHints(int hint) {
java.util.Map<EncodeHintType, Object> hints = new java.util.HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.ERROR_CORRECTION, com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.H);
hints.put(EncodeHintType.MARGIN, hint);
return hints;
}
/**
* 去除二维码图像多余的白边
*/
private static BufferedImage removeWhiteBorder(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
int leftMost = width;
int rightMost = 0;
int topMost = height;
int bottomMost = 0;
// 扫描每一行和每一列,找到有色块的最小矩形
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (image.getRGB(x, y) != -1) { // 非白色
leftMost = Math.min(leftMost, x);
rightMost = Math.max(rightMost, x);
topMost = Math.min(topMost, y);
bottomMost = Math.max(bottomMost, y);
}
}
}
// 计算出最小矩形的宽和高
int newWidth = rightMost - leftMost + 1;
int newHeight = bottomMost - topMost + 1;
// 创建一个新图像并复制原图像的最小矩形部分
BufferedImage newImage = new BufferedImage(newWidth, newHeight, image.getType());
for (int y = topMost; y <= bottomMost; y++) {
for (int x = leftMost; x <= rightMost; x++) {
newImage.setRGB(x - leftMost, y - topMost, image.getRGB(x, y));
}
}
return newImage;
}