Java 生成二维码
使用springboot,实现生成二维码功能,本案例相比之前版本,在外观上更美,在功能上更多,支持自定义logo,title,description内容
依赖
<!--二维码-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
xml
请求调用
@GetMapping("/qr-code")
public void qrCodeText(@RequestParam("text") String text,@RequestParam(value = "logo",required = false) String logo,@RequestParam(value = "title",required = false) String title ,@RequestParam(value = "description",required = false) String description, HttpServletResponse response, HttpServletRequest request) {
try{
byte[] bytes = QrCodeUtils.encodeQRCode(text,logo,title,description);
response.setContentType(QrCodeUtils.RESPONSE_CONTENT_TYPE);
OutputStream stream = response.getOutputStream();
stream.write(bytes);
stream.flush();
}catch (Exception e){
log.info("出错了");
}
}
java
二维码生成工具类(已优化)
package com.lb.upload.fileupload.utils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;
import sun.font.FontDesignMetrics;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
@Slf4j
public class QrCodeUtils {
public static int QRCODE_SIZE = 512;
private static int rowHeight;
public static int rowCount;
public static final String format = "png";
public static final String RESPONSE_CONTENT_TYPE = "image/png";
//默认logo本地
//public static final String LOGO_PATH = "src/main/resources/logo.jpg";
//默认logo远程
public static final String LOGO_PATH = "https://files.hyz.cool/files/qr-code-config/logo.jpg";
//默认logo服务端
//public static final String LOGO_PATH = "home/ubuntu/app/files/jar/logo.jpg";
//背景
public static final String BACKGROUND = "https://files.hyz.cool/files/qr-code-config/background.png";
public static byte[] encodeQRCode(String text, String logoUrl, String title, String description) {
try {
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
//容错率越高,可存储的信息越少;但是对二维码清晰对要求越小
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 生成二维码
BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
//删除白边
bitMatrix = deleteBorder(bitMatrix);
BufferedImage bufferedImage = toBufferedImage(bitMatrix);
//获取二维码小块儿边长
rowHeight = getRowHeight(bufferedImage);
//获取二维码行数
rowCount = bufferedImage.getWidth() / rowHeight;
//二维码圆角
bufferedImage = roundType1QrCode(bufferedImage);
//美化二维码
bufferedImage = beautifyQrCode(bufferedImage);
//设置logo
bufferedImage = addImgLogo(bufferedImage, logoUrl);
//添加title
bufferedImage = addQRCodeTitle(bufferedImage, title);
//添加description
bufferedImage = addQRCodeDescription(bufferedImage, description);
//添加边框
bufferedImage = addPadding(bufferedImage);
//转为透明背景
// bufferedImage = transparent(bufferedImage);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, format, out);
return out.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static final int BORDER_WIDTH = 0;
public static BitMatrix deleteBorder(BitMatrix matrix) {
int[] rec = matrix.getEnclosingRectangle();
int resWidth = rec[2] + BORDER_WIDTH;
int resHeight = rec[3] + BORDER_WIDTH;
BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
resMatrix.clear();
for (int i = BORDER_WIDTH; i < resWidth; i++) {
for (int j = BORDER_WIDTH; j < resHeight; j++) {
if (matrix.get(i + rec[0], j + rec[1])) resMatrix.set(i, j);
}
}
return resMatrix;
}
public static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
int onColor = 0xFF000000;
int offColor = 0x00ffffff;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, matrix.get(x, y) ? onColor : offColor);
}
}
return image;
}
private static BufferedImage roundType1QrCode(BufferedImage qr_code) {
BufferedImage result = null;
try {
result = qr_code;
int qr_codeWidth = result.getWidth();
int qr_codeHeight = result.getHeight();
Graphics2D graphics = result.createGraphics();
//消除文字锯齿
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.drawImage(qr_code, 0, 0, qr_codeWidth, qr_codeHeight, null);
//圆角1:内外角圆心相同
int[][] list = {
//(列,行,角度/90)
{0, 0, 1}, {3, 0, 0}, {rowCount - 7, 0, 1}, {rowCount - 4, 0, 0},//第一行
{0, 3, 2}, {3, 3, 3}, {rowCount - 7, 3, 2}, {rowCount - 4, 3, 3},//第七行
{0, rowCount - 7, 1}, {3, rowCount - 7, 0},//倒数第一列
{0, rowCount - 4, 2}, {3, rowCount - 4, 3},//倒数第七列
};
for (int i = 0; i < list.length; i++) {
graphics.setColor(Color.WHITE);
graphics.fillRect((list[i][0] + (list[i][2] != 1 && list[i][2] != 2 ? 2 : 0)) * rowHeight, (list[i][1] + +(list[i][2] !=0 && list[i][2] != 1 ? 2 : 0)) * rowHeight, rowHeight * 2, rowHeight * 2);
graphics.setColor(Color.BLACK);
graphics.fillArc(
list[i][0] * rowHeight,
list[i][1] * rowHeight,
rowHeight * 4, rowHeight * 4,
list[i][2] * 90, 90);
graphics.setColor(Color.WHITE);
graphics.fillArc(
(list[i][0] + 1) * rowHeight,
(list[i][1] + 1) * rowHeight,
rowHeight * 2, rowHeight * 2,
list[i][2] * 90, 90);
}
int[][] list1 = {
{2, 2, 1}, {4, 2, 0}, {rowCount - 5, 2, 1}, {rowCount - 3, 2, 0},
{2, 4, 2}, {4, 4, 3}, {rowCount - 5, 4, 2}, {rowCount - 3, 4, 3},
{2, rowCount - 5, 1}, {4, rowCount - 5, 0},
{2, rowCount - 3, 2}, {4, rowCount - 3, 3},
};
for (int i = 0; i < list1.length; i++) {
graphics.setColor(Color.WHITE);
graphics.fillRect(list1[i][0] * rowHeight, list1[i][1] * rowHeight, rowHeight, rowHeight);
graphics.setColor(new Color(14, 149, 228));
graphics.fillArc(
(list1[i][0] - (list1[i][2] == 0 || list1[i][2] == 3 ? 1 : 0)) * rowHeight,
(list1[i][1] - (list1[i][2] > 1 ? 1 : 0)) * rowHeight,
rowHeight * 2, rowHeight * 2,
list1[i][2] * 90, 90);
}
int[][] list2 = {
{3, 2}, {rowCount - 4, 2},
{2, 3}, {3, 3}, {4, 3}, {rowCount - 3, 3}, {rowCount - 4, 3}, {rowCount - 5, 3},
{3, 4}, {rowCount - 4, 4},
{3, rowCount - 5},
{2, rowCount - 4}, {3, rowCount - 4}, {4, rowCount - 4},
{3, rowCount - 3},
};
graphics.setColor(new Color(14, 149, 228));
for (int i = 0; i < list2.length; i++) {
graphics.fillRect(list2[i][0] * rowHeight, list2[i][1] * rowHeight, rowHeight, rowHeight);
}
graphics.dispose();
result.flush();
} catch (
Exception e) {
log.info("二维码美化失败");
}
return result;
}
private static BufferedImage roundType2QrCode(BufferedImage qr_code) {
BufferedImage result = null;
try {
result = qr_code;
int qr_codeWidth = result.getWidth();
int qr_codeHeight = result.getHeight();
Graphics2D graphics = result.createGraphics();
//消除文字锯齿
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.drawImage(qr_code, 0, 0, qr_codeWidth, qr_codeHeight, null);
//圆角2:内外角完全相同
int[][] list0 = {
//(列,行,角度/90)
{0, 0, 1}, {6, 0, 0}, {rowCount - 7, 0, 1}, {rowCount - 1, 0, 0},//第一行
// {2, 2, 1}, {4, 2, 0}, {rowCount - 5, 2, 1}, {rowCount - 3, 2, 0},//第三行
// {2, 4, 2}, {4, 4, 3}, {rowCount - 5, 4, 2}, {rowCount - 3, 4, 3},//第五行
{0, 6, 2}, {6, 6, 3}, {rowCount - 7, 6, 2}, {rowCount - 1, 6, 3},//第七行
{0, rowCount - 7, 1}, {6, rowCount - 7, 0},//倒数第一列
// {2, rowCount - 5, 1}, {4, rowCount - 5, 0},//倒数第三列
// {2, rowCount - 3, 2}, {4, rowCount - 3, 3},//倒数第五列
{0, rowCount - 1, 2}, {6, rowCount - 1, 3},//倒数第七列
};
for (int i = 0; i < list0.length; i++) {
graphics.setColor(Color.WHITE);
graphics.fillRect(list0[i][0] * rowHeight, list0[i][1] * rowHeight, rowHeight, rowHeight);
graphics.setColor(Color.BLACK);
graphics.fillArc(
(list0[i][0] - (list0[i][2] == 0 || list0[i][2] == 3 ? 1 : 0)) * rowHeight,
(list0[i][1] - (list0[i][2] > 1 ? 1 : 0)) * rowHeight,
rowHeight * 2, rowHeight * 2,
list0[i][2] * 90, 90);
}
int[][] list1 = {
{2, 2, 1}, {4, 2, 0}, {rowCount - 5, 2, 1}, {rowCount - 3, 2, 0},
{2, 4, 2}, {4, 4, 3}, {rowCount - 5, 4, 2}, {rowCount - 3, 4, 3},
{2, rowCount - 5, 1}, {4, rowCount - 5, 0},
{2, rowCount - 3, 2}, {4, rowCount - 3, 3},
};
for (int i = 0; i < list1.length; i++) {
graphics.setColor(Color.WHITE);
graphics.fillRect(list1[i][0] * rowHeight, list1[i][1] * rowHeight, rowHeight, rowHeight);
graphics.setColor(new Color(14, 149, 228));
graphics.fillArc(
(list1[i][0] - (list1[i][2] == 0 || list1[i][2] == 3 ? 1 : 0)) * rowHeight,
(list1[i][1] - (list1[i][2] > 1 ? 1 : 0)) * rowHeight,
rowHeight * 2, rowHeight * 2,
list1[i][2] * 90, 90);
}
int[][] list2 = {
{3, 2}, {rowCount - 4, 2},
{2, 3}, {3, 3}, {4, 3}, {rowCount - 3, 3}, {rowCount - 4, 3}, {rowCount - 5, 3},
{3, 4}, {rowCount - 4, 4},
{3, rowCount - 5},
{2, rowCount - 4}, {3, rowCount - 4}, {4, rowCount - 4},
{3, rowCount - 3},
};
graphics.setColor(new Color(14, 149, 228));
for (int i = 0; i < list2.length; i++) {
graphics.fillRect(list2[i][0] * rowHeight, list2[i][1] * rowHeight, rowHeight, rowHeight);
}
int[][] list3 = {
{1, 1, 1}, {5, 1, 0}, {rowCount - 6, 1, 1}, {rowCount - 2, 1, 0},
{1, 5, 2}, {5, 5, 3}, {rowCount - 6, 5, 2}, {rowCount - 2, 5, 3},
{1, rowCount - 6, 1}, {5, rowCount - 6, 0},
{1, rowCount - 2, 2}, {5, rowCount - 2, 3},
};
for (int i = 0; i < list3.length; i++) {
graphics.setColor(Color.BLACK);
graphics.fillRect(list3[i][0] * rowHeight, list3[i][1] * rowHeight, rowHeight, rowHeight);
graphics.setColor(Color.WHITE);
graphics.fillArc(
(list3[i][0] - (list3[i][2] == 0 || list3[i][2] == 3 ? 1 : 0)) * rowHeight,
(list3[i][1] - (list3[i][2] > 1 ? 1 : 0)) * rowHeight,
rowHeight * 2, rowHeight * 2,
list3[i][2] * 90, 90);
}
graphics.dispose();
result.flush();
} catch (
Exception e) {
log.info("二维码美化失败");
}
return result;
}
private static BufferedImage beautifyQrCode(BufferedImage qr_code) {
BufferedImage result = null;
try {
int qr_codeWidth = qr_code.getWidth();
int qr_codeHeight = qr_code.getHeight();
result = new BufferedImage(qr_codeWidth + rowHeight * 8, qr_codeHeight + rowHeight * 8, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D graphics = result.createGraphics();
//消除文字锯齿
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, qr_codeWidth + rowHeight * 8, qr_codeHeight + rowHeight * 8);
graphics.drawImage(qr_code, rowHeight * 4, rowHeight * 4, qr_codeWidth, qr_codeHeight, null);
graphics.setColor(new Color(14, 149, 228));
int[][] list0 = {
{4, 5, 0},
{rowCount + 8 - 9, 5, 0},
{4, 5, rowCount + 8 - 1},
{rowCount + 8 - 9, 5, rowCount + 8 - 1}
};
for (int i = 0; i < list0.length; i++) {
graphics.fillRect(
list0[i][0] * rowHeight,
list0[i][2] * rowHeight,
rowHeight * list0[i][1],
rowHeight);
graphics.fillRect(
list0[i][2] * rowHeight,
list0[i][0] * rowHeight,
rowHeight,
rowHeight * list0[i][1]);
}
int[][] list1 = {
//(列,行,角度/90)
{0, 0, 1},//左上角
{rowCount, 0, 0},//右上角
{0, rowCount, 2},//左下角
{rowCount, rowCount, 3},
};
for (int i = 0; i < list1.length; i++) {
graphics.setColor(new Color(14, 149, 228));
graphics.fillArc(
list1[i][0] * rowHeight,
list1[i][1] * rowHeight,
rowHeight * 8, rowHeight * 8,
list1[i][2] * 90, 90);
graphics.setColor(Color.WHITE);
graphics.fillArc(
(list1[i][0] + 1) * rowHeight,
(list1[i][1] + 1) * rowHeight,
rowHeight * 6, rowHeight * 6,
list1[i][2] * 90, 90);
}
graphics.dispose();
result.flush();
} catch (
Exception e) {
log.info("二维码美化失败");
}
return result;
}
public static BufferedImage addImgLogo(BufferedImage qr_img, String logoUrl) {
logoUrl = logoUrl != null && logoUrl != "" ? logoUrl : LOGO_PATH;
BufferedImage result = null;
try {
//读取logo图片
BufferedImage logo = ImageIO.read(new URL(logoUrl));
//读取二维码图片
result = qr_img;
//获取画笔
Graphics2D graphics = result.createGraphics();
//消除文字锯齿
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//设置二维码大小,太大,会覆盖二维码,此处1/6
int logoWidth = logo.getWidth(null) > result.getWidth() / 6 ? (result.getWidth() / 6) : logo.getWidth(null);
int logoHeight = logo.getHeight(null) > result.getHeight() / 6 ? (result.getHeight() / 6) : logo.getHeight(null);
// 确定二维码的中心位置坐标,设置logo图片放置的位置
int x = (result.getWidth() - logoWidth) / 2;
int y = (result.getHeight() - logoHeight) / 2;
//开始合并绘制图片
//圆角logo
//BufferedImage bufferedImage = setRadius(logo, logoWidth, 0, 0);
//圆形logo
BufferedImage bufferedImage = getRoundImg(logo);
//绘制logo
graphics.drawImage(bufferedImage, x, y, logoWidth, logoHeight, null);
//设置logo边框大小
//graphics.setStroke(new BasicStroke(5));
//设置logo边框颜色
//graphics.setColor(Color.WHITE);
//graphics.drawRect(x, y, logoWidth, logoHeight);
graphics.dispose();
logo.flush();
result.flush();
} catch (Exception e) {
log.info("二维码绘制logo失败");
}
return result;
}
public static BufferedImage addQRCodeTitle(BufferedImage qr_img, String title) {
if (title == null || title.equals("")) return qr_img;
BufferedImage result = null;
try {
result = drawTextLines(qr_img, title, 40, true);
} catch (Exception e) {
log.info("二维码绘制标题失败");
}
return result;
}
public static BufferedImage addQRCodeDescription(BufferedImage qr_img, String description) {
if (description == null || description.equals("")) return qr_img;
BufferedImage result = null;
try {
result = drawTextLines(qr_img, description, 25, false);
} catch (Exception e) {
log.info("二维码绘制描述失败");
}
return result;
}
private static BufferedImage addPadding(BufferedImage bufferedImage) {
BufferedImage result = null;
try {
int border = 150;
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
result = new BufferedImage(width + border, height+border, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D graphics = result.createGraphics();
//消除文字锯齿
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, width + border, height+ border);
graphics.drawImage(bufferedImage, border / 2, border / 2, width, height, null);
graphics.dispose();
result.flush();
} catch (Exception e) {
log.info("二维码绘制边框失败");
}
return result;
}
public static BufferedImage transparent(BufferedImage QrImg) {
BufferedImage image = QrImg;
ImageIcon imageIcon = new ImageIcon(image);
BufferedImage bufferedImage = new BufferedImage(
imageIcon.getIconWidth(), imageIcon.getIconHeight(),
BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();
//消除文字锯齿
g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2D.drawImage(imageIcon.getImage(), 0, 0,
imageIcon.getImageObserver());
int alpha = 0;
for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage
.getHeight(); j1++) {
for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage
.getWidth(); j2++) {
int rgb = bufferedImage.getRGB(j2, j1);
if (colorInRange(rgb))
alpha = 0;
else
alpha = 255;
rgb = (alpha << 24) | (rgb & 0x00ffffff);
bufferedImage.setRGB(j2, j1, rgb);
}
}
g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver());
return bufferedImage;
}
public static boolean colorInRange(int color) {
int red = (color & 0xff0000) >> 16;
int green = (color & 0x00ff00) >> 8;
int blue = (color & 0x0000ff);
if (red >= color_range && green >= color_range && blue >= color_range)
return true;
return false;
}
public static int color_range = 210;
public static Pattern pattern = Pattern.compile("[0-9]*");
public static boolean isNo(String str) {
return pattern.matcher(str).matches();
}
/**
* 图片设置圆角
*
* @param srcImage
* @param radius
* @param border
* @param padding
* @return
* @throws IOException
*/
public static BufferedImage setRadius(BufferedImage srcImage, int radius, int border, int padding) throws IOException {
int width = srcImage.getWidth();
int height = srcImage.getHeight();
int canvasWidth = width + padding * 2;
int canvasHeight = height + padding * 2;
BufferedImage image = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = image.createGraphics();
//消除文字锯齿
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setComposite(AlphaComposite.Src);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setColor(Color.WHITE);
graphics.fill(new RoundRectangle2D.Float(0, 0, canvasWidth, canvasHeight, radius, radius));
graphics.setComposite(AlphaComposite.SrcAtop);
graphics.drawImage(setClip(srcImage, radius), padding, padding, null);
if (border != 0) {
graphics.setColor(Color.GRAY);
graphics.setStroke(new BasicStroke(border));
graphics.drawRoundRect(padding, padding, canvasWidth - 2 * padding, canvasHeight - 2 * padding, radius, radius);
}
graphics.dispose();
return image;
}
/**
* 图片设置圆角
*
* @param srcImage
* @return
* @throws IOException
*/
public static BufferedImage setRadius(BufferedImage srcImage) throws IOException {
int radius = (srcImage.getWidth() + srcImage.getHeight()) / 6;
return setRadius(srcImage, radius, 2, 5);
}
/**
* 图片切圆角
*
* @param srcImage
* @param radius
* @return
*/
public static BufferedImage setClip(BufferedImage srcImage, int radius) {
int width = srcImage.getWidth();
int height = srcImage.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = image.createGraphics();
//消除文字锯齿
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setClip(new RoundRectangle2D.Double(0, 0, width, height, radius, radius));
graphics.drawImage(srcImage, 0, 0, null);
graphics.dispose();
return image;
}
public static BufferedImage getRoundImg(BufferedImage avatarImage) throws Exception {
int width = avatarImage.getWidth();
// 透明底的图片
BufferedImage formatAvatarImage = new BufferedImage(width, width, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D graphics = formatAvatarImage.createGraphics();
//消除画图锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//把图片切成一个圓
//留一个像素的空白区域,这个很重要,画圆的时候把这个覆盖
int border = 10;
//图片是一个圆型
Ellipse2D.Double shape = new Ellipse2D.Double(border, border, width - border * 2, width - border * 2);
//需要保留的区域
graphics.setClip(shape);
graphics.drawImage(avatarImage, border, border, width - border * 2, width - border * 2, null);
graphics.dispose();
//在圆图外面再画一个圆
//新创建一个graphics,这样画的圆不会有锯齿
graphics = formatAvatarImage.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//画笔是4.5个像素,BasicStroke的使用可以查看下面的参考文档
//使画笔时基本会像外延伸一定像素,具体可以自己使用的时候测试
Stroke s = new BasicStroke(4.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
graphics.setStroke(s);
graphics.setColor(Color.WHITE);
graphics.drawOval(border, border, width - border * 2, width - border * 2);
graphics.dispose();
return formatAvatarImage;
}
private static BufferedImage drawTextLines(BufferedImage qr_img, String content, int fontSize, boolean top) {
//设置字体字号
Font font = new Font("微软雅黑", Font.PLAIN, fontSize);
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
int height = metrics.getHeight();//计算高
int qr_imgWidth = qr_img.getWidth();
int qr_imgHeight = qr_img.getHeight();
java.util.List<String> textLines = getTextLines(qr_imgWidth, font, content);
int textViewHeight = height * (2 + textLines.size());
int graphics_height = qr_imgHeight + textViewHeight;
BufferedImage result = new BufferedImage(qr_imgWidth, graphics_height, BufferedImage.TYPE_INT_BGR);
Graphics2D graphics = result.createGraphics();
//消除文字锯齿
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
//消除画图锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//设置文字
Color color = new Color(0, 0, 0);
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
//设置背影为白色
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, qr_imgWidth, graphics_height);
graphics.setFont(font);
graphics.setColor(color);
for (int i = 0; i < textLines.size(); i++) {
String text = textLines.get(i);
int width = getWordWidth(font, text);//计算图片的宽
graphics.drawString(text, (qr_imgWidth - width) / 2, (top ? 0 : qr_imgHeight) + height * (2 + i));//图片上写文字
}
graphics.drawImage(qr_img, 0, top ? textViewHeight : 0, qr_imgWidth, qr_imgHeight, null);
graphics.dispose();
result.flush();
return result;
}
private static List<String> getTextLines(int qr_imgWidth, Font font, String content) {
int contentWidth = getWordWidth(font, content);
int size = contentWidth / qr_imgWidth + 1;
int length = content.length() / size;
java.util.List<String> textLines = new ArrayList<>();
for (int i = 0; i < size; i++) {
if (i + 1 == size)
textLines.add(content.substring(length * i));
else
textLines.add(content.substring(length * i, length * (i + 1)));
}
return textLines;
}
public static int getWordWidth(Font font, String content) {
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
int width = 0;
for (int i = 0; i < content.length(); i++) {
width += metrics.charWidth(content.charAt(i));
}
return width;
}
private static int getRowHeight(BufferedImage result) {
int RowHeight = 0;
for (int pos = 0; pos < result.getWidth(); pos++) {
int rgb = result.getRGB(pos, pos);
String s = Integer.toHexString(rgb);
// log.info("rgb"+rgb);
// log.info(" Integer.toHexString(rgb);"+ Integer.toHexString(rgb));
if (rgb > 0) {
RowHeight = pos;
break;
}
}
return RowHeight;
}
}
java
注:部分实现参考互联网分享,仅供学习





