JAVA 創建帶個人信息,頭像等內容和可變二維碼的海報
1、添加二維碼依賴包
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
2、寫畫圖工具類
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
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.zyfycs.college.plugin.alibaba.oss.OSS;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* @author Created by 譚健 on 2020/4/23. 星期四. 10:42.
* © All Rights Reserved.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ImageDrawUtils {
/**
* 畫一個海報
*/
public static void drawPoster() throws IOException, WriterException {
// 創建背景
BufferedImage backgroundImage = createImage("https://csxy-public-img.oss-cn-hangzhou.aliyuncs.com/other/timg.jpg");
// 創建頭像
BufferedImage filletImage = fillet(createImage("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1587634370462&di=80a37d1fed5581e4d25d9507322a0324&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201802%2F20%2F20180220165946_RiGPS.thumb.700_0.jpeg"), 120, 120);
// 創建二維碼
BufferedImage qrCodeImage = createQrCodeImage("https://www.baidu.com/", 200, 200);
// 創建畫布
BufferedImage canvas = new BufferedImage(backgroundImage.getWidth(), backgroundImage.getHeight(), BufferedImage.TYPE_INT_RGB);
// 初始化背景
Graphics2D graphics = setBackground(canvas, backgroundImage);
// 把背景畫上去
imageDraw(graphics, new ImageDraw(backgroundImage, 0, 0, backgroundImage.getWidth(), backgroundImage.getHeight()));
// 把頭像畫上去
imageDraw(graphics, new ImageDraw(filletImage, 70, 70, 150, 150));
// 把二維碼畫上去
imageDraw(graphics, new ImageDraw(qrCodeImage, 730, 1250, 200, 200));
graphics.dispose();
OSS.simpleUpload(toInputStream(canvas), "png", "other/", UUID.absolutelyUniqueId());
}
/**
* 設置背景圖片
*
* @param canvas 畫布
* @param backgroundImage 背景圖
* @return
*/
public static Graphics2D setBackground(BufferedImage canvas, BufferedImage backgroundImage) {
Graphics2D graphics = (Graphics2D) canvas.getGraphics();
// 抗鋸齒
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
imageDraw(graphics, new ImageDraw(backgroundImage, 0, 0, backgroundImage.getWidth(), backgroundImage.getHeight()));
return graphics;
}
/**
* 給圖片設置圓角,並留一個白色外圈,用於頭像圓角化
*/
public static BufferedImage fillet(BufferedImage image, int width, int height) {
// 一張空白圖片
BufferedImage blankImage = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D graphics = newCanvas(blankImage);
// 留一像素的空白區域
int border = 1;
Ellipse2D.Double shape = new Ellipse2D.Double(border, border, width - border * 2, width - border * 2);
graphics.setClip(shape);
graphics.drawImage(image, border, border, width - border * 2, width - border * 2, null);
graphics.dispose();
graphics = newCanvas(blankImage);
int roundBorder = 3;
// 畫筆是4.5個像素,BasicStroke的使用可以查看下面的參考文檔
// 使畫筆時基本會像外延伸一定像素,具體可以自己使用的時候測試
Stroke s = new BasicStroke(4.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
graphics.setStroke(s);
graphics.setColor(Color.WHITE);
graphics.drawOval(roundBorder, roundBorder, width - roundBorder * 2, width - roundBorder * 2);
graphics.dispose();
return blankImage;
}
private static Graphics2D newCanvas(BufferedImage image) {
Graphics2D graphics = image.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
return graphics;
}
/**
* 把畫布轉成 InputStream 流
*
* @param canvas 畫布
* @return
* @throws IOException
*/
public static InputStream toInputStream(BufferedImage canvas) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(canvas, "png", os);
return new ByteArrayInputStream(os.toByteArray());
}
/**
* 圖片繪製對象
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
private static class ImageDraw {
/**
* 圖片
*/
private BufferedImage image;
/**
* x軸偏移量
*/
private int x;
/**
* y軸偏移量
*/
private int y;
/**
* 寬度
*/
private int width;
/**
* 高度
*/
private int height;
}
/**
* 文本繪製對象
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
private static class StringDraw {
/**
* 文本類型
*/
private String text;
/**
* x軸偏移量
*/
private int x;
/**
* y軸偏移量
*/
private int y;
/**
* 顏色
*/
private Color color;
/**
* 文字樣式
*/
private Font font;
}
/**
* 創建背景圖像
*/
public static BufferedImage createImage(String ImageUrl) throws IOException {
return ImageIO.read(new URL(ImageUrl));
}
/**
* 創建畫布
*/
public static Graphics2D createCanvas(BufferedImage backgroundImage) {
BufferedImage canvas = new BufferedImage(backgroundImage.getWidth(), backgroundImage.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = (Graphics2D) canvas.getGraphics();
// 抗鋸齒
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
return graphics;
}
/**
* 繪製圖片
*
* @param canvas 畫布
* @param drawInfo 圖片信息
*/
public static void imageDraw(Graphics2D canvas, Object drawInfo) {
ImageDraw imageDraw = (ImageDraw) drawInfo;
canvas.drawImage(imageDraw.getImage().getScaledInstance(imageDraw.getWidth(), imageDraw.getHeight(), Image.SCALE_DEFAULT), imageDraw.getX(), imageDraw.getY(), null);
}
/**
* 繪製文本
*
* @param canvas 畫布
* @param drawInfo 文本信息
*/
public static void stringDraw(Graphics2D canvas, Object drawInfo) {
StringDraw stringDraw = (StringDraw) drawInfo;
canvas.setColor(stringDraw.getColor());
canvas.setFont(stringDraw.getFont());
canvas.drawString(stringDraw.getText(), stringDraw.getX(), stringDraw.getY());
}
/**
* 創建二維碼圖片
*
* @param text 二維碼內容
* @param width 二維碼寬度
* @param height 二維碼高度
* @return
* @throws WriterException
*/
public static BufferedImage createQrCodeImage(String text, int width, int height) throws WriterException {
QRCodeWriter qrCodeWriter = new QRCodeWriter();
Map<EncodeHintType, Object> hints = new HashMap<>(3);
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 0);
BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);
return MatrixToImageWriter.toBufferedImage(bitMatrix);
}
public static void main(String[] args) throws IOException, WriterException {
drawPoster();
}
}
3、運行main 方法
隨便找幾個圖片扔上去,圖片上傳到OSS,得到圖片
運行時間約1-2秒,具體看海報複雜度而定
4、防止重複創建
創建前判斷文件是否存在,如果存在則直接返回圖片地址給到前端