日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

背景图和二维码合成

發布時間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 背景图和二维码合成 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

需求: 類似于做一個碼牌, UI提供背景圖模板, 后端將二維碼合成到背景圖模板中

背景圖模板????????????????????????????????????????? ? ? ? 最終效果圖

開擼

package cc.sunni;import cn.hutool.core.util.StrUtil; import cn.hutool.extra.qrcode.QrCodeUtil; import cn.hutool.extra.qrcode.QrConfig; import org.springframework.core.io.ClassPathResource; import sun.misc.BASE64Encoder;import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream;/*** 碼牌: 將二維碼合成到背景圖片中** @author 江黎* @since 2022-07-21*/ public class QrCodeCard {/*** 二維碼的寬度*/private static final int QR_CODE_WIDTH = 640;/*** 二維碼的高度*/private static final int QR_CODE_HEIGHT = 640;/*** title字體*/private static final Font TITLE_FONT = new Font("宋體", Font.BOLD, 30);/*** desc字體*/private static final Font DESC_FONT = new Font("宋體", Font.PLAIN, 25);/*** bottom字體*/private static final Font BOTTOM_FONT = new Font("宋體", Font.ITALIC, 24);private static final String FORMAT_NAME = "PNG";/*** @param title 標題* @param desc 描述* @param content 二維碼內容* @param bottom 底部文字* @param imgLogo 二維碼中間圖片地址* @param backgroundImage 背景圖片地址* @param imageY 二維碼在背景圖片的Y軸位置, X軸是居中的* @return 返回BufferedImage方便后續處理是生成圖片還是生成base64字符串*/public static BufferedImage createQrCode(String title, String desc, String content, String bottom, String imgLogo, String backgroundImage, int imageY) throws IOException {// 創建主模板圖片int maxWidth = getMaxWidth(title, desc, bottom);int maxHeight = getMaxHeight();BufferedImage image = new BufferedImage(maxWidth, maxHeight, BufferedImage.TYPE_INT_RGB);Graphics2D graphics = image.createGraphics();if (StrUtil.isNotBlank(backgroundImage)) {// 設置圖片的背景色為透明, 需要合成到背景圖片就設置為透明image = graphics.getDeviceConfiguration().createCompatibleImage(maxWidth, maxHeight, Transparency.TRANSLUCENT);} else {// 設置圖片的背景色為白色graphics.setColor(Color.white);}graphics.fillRect(0, 0, maxWidth, maxHeight);// 動態高度int height = 0;// *********************** title ***********************if (StrUtil.isNotBlank(title)) {graphics = image.createGraphics();// 設置字體顏色 black黑 white白graphics.setColor(Color.black);// 設置字體graphics.setFont(TITLE_FONT);graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);// 居中 x開始的位置:(圖片寬度-字體大小*字的個數)/2int x = (maxWidth - (TITLE_FONT.getSize() * title.length())) / 2;int strHeight = getStringHeight(graphics);graphics.drawString(title, x, strHeight);height += strHeight;}// ********************** desc **********************if (StrUtil.isNotBlank(desc)) {graphics = image.createGraphics();// 設置字體顏色,先設置顏色,再填充內容graphics.setColor(Color.black);// 設置字體graphics.setFont(DESC_FONT);graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);// 獲取字符高度int strHeight = getStringHeight(graphics);// 按行居中顯示String[] info = desc.split("\\$"); // 多行文字以 $ 分隔for (int i = 0; i < info.length; i++) {String s = info[i];// x開始的位置:(圖片寬度-字體大小*字的個數)/2int strWidth = graphics.getFontMetrics().stringWidth(s);// 總長度減去文字長度的一半 (居中顯示)int startX = (maxWidth - strWidth) / 2;height += strHeight * (i + 1);graphics.drawString(s, startX, height);}}// ********************** 插入二維碼圖片 **********************Graphics codePic = image.getGraphics();BufferedImage codeImg;QrConfig config = new QrConfig();config.setMargin(2);config.setWidth(QR_CODE_WIDTH);config.setHeight(QR_CODE_HEIGHT);if (StrUtil.isNotBlank(imgLogo)) {config.setImg(imgLogo);}codeImg = QrCodeUtil.generate(content, config);// 繪制二維碼codePic.drawImage(codeImg, (maxWidth - QR_CODE_WIDTH) / 2, height, QR_CODE_WIDTH, QR_CODE_HEIGHT, null);codePic.dispose();// ********************** bottom **********************if (StrUtil.isNotBlank(bottom)) {graphics = image.createGraphics();// 設置字體顏色graphics.setColor(Color.black);// 設置字體graphics.setFont(BOTTOM_FONT);graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);// x開始的位置:(圖片寬度-字體大小*字的個數)/2int startX = (maxWidth - (BOTTOM_FONT.getSize() * bottom.length())) / 2;// 獲取字符高度int footerStrHeight = getStringHeight(graphics);height += QR_CODE_HEIGHT + footerStrHeight;graphics.drawString(bottom, startX, height);}if (StrUtil.isNotBlank(backgroundImage)) {// 加載背景模板ClassPathResource resource = new ClassPathResource(backgroundImage);InputStream inputStream = resource.getInputStream();BufferedImage templateImage = ImageIO.read(inputStream);Graphics graphicsTemplate = templateImage.getGraphics();// 根據模板寬度 - 二維碼寬度 進行居中算出X坐標int widthX = (templateImage.getWidth() - image.getWidth()) / 2;// 添加二維碼graphicsTemplate.drawImage(image, widthX, imageY, null);graphicsTemplate.dispose();return templateImage;} else {return image;}}// 生成圖片文件public static void createImage(BufferedImage image, String fileLocation) {if (image != null) {try {ImageIO.write(image, "png", new File(fileLocation));} catch (IOException e) {e.printStackTrace();}}}// 獲取圖片base64數據public static String base64ImageString(BufferedImage image) throws IOException {ByteArrayOutputStream bos = new ByteArrayOutputStream();//io流ImageIO.write(image, FORMAT_NAME, bos);//寫入流中byte[] bytes = bos.toByteArray();//轉換成字節BASE64Encoder encoder = new BASE64Encoder();String jpgBase64 = encoder.encodeBuffer(bytes).trim();//轉換成base64串jpgBase64 = jpgBase64.replaceAll("\n", "").replaceAll("\r", "");//刪除 \r\nreturn "data:image/jpg;base64," + jpgBase64;}// 字符串總寬度private static int getStringLength(Graphics g, String str) {char[] chars = str.toCharArray();return g.getFontMetrics().charsWidth(chars, 0, str.length());}// 字符高度private static int getStringHeight(Graphics g) {return g.getFontMetrics().getHeight();}// 每一行字符的個數private static int getRowStrNum(int strNum, int rowWidth, int strWidth) {return (rowWidth * strNum) / strWidth;}// 字符行數private static int getRows(int strWidth, int rowWidth) {int rows;if (strWidth % rowWidth > 0) {rows = strWidth / rowWidth + 1;} else {rows = strWidth / rowWidth;}return rows;}// 計算二維碼圖片最大寬度private static int getMaxWidth(String title, String desc, String bottom) {int width = 0;BufferedImage image = new BufferedImage(QR_CODE_WIDTH, QR_CODE_HEIGHT, BufferedImage.TYPE_INT_RGB);Graphics2D graphics = image.createGraphics();if (StrUtil.isNotBlank(title)) {width = Math.max(getStringLength(graphics, title), width);}if (StrUtil.isNotBlank(desc)) {width = Math.max(getStringLength(graphics, desc), width);}if (StrUtil.isNotBlank(bottom)) {width = Math.max(getStringLength(graphics, bottom), width);}return Math.max(QR_CODE_WIDTH, width);}// 計算二維碼圖片最大高度private static int getMaxHeight() {int height = QR_CODE_HEIGHT;BufferedImage image = new BufferedImage(QR_CODE_WIDTH, QR_CODE_HEIGHT, BufferedImage.TYPE_INT_RGB);Graphics2D graphics = image.createGraphics();graphics.setFont(TITLE_FONT);height += getStringHeight(graphics);graphics.setFont(DESC_FONT);height += getStringHeight(graphics);graphics.setFont(BOTTOM_FONT);height += getStringHeight(graphics);return height;}public static void main(String[] args) throws IOException {String title = "碼牌";String desc = "知名互聯網公司CEO";String content = "https://www.baidu.com";String logo = "templates/logo@2x.png";String bottom = "國家認證";String backgroundImage = "templates/announcer.png"; // BufferedImage bufferedImage = createQrCode(null, null, content, logo, null, backgroundImage, 290);BufferedImage bufferedImage = createQrCode(title, desc, content, logo, bottom, backgroundImage, 290);createImage(bufferedImage, "D:/test.png");} }

?附上下載的方法
????

@RestController public class Controller {@PostMapping("/downloadQrCode")public void downloadQrCode(@RequestParam String content, @RequestParam(required = false) String title,@RequestParam(required = false) String desc, @RequestParam(required = false) String bottom,HttpServletResponse response) throws IOException {BufferedImage targetBufferedImage = QrCodeCard.createQrCode(title, desc, content,bottom, "templates/logo@2x.png", "templates/announcer.png", 290);OutputStream os = response.getOutputStream();response.setCharacterEncoding(Charsets.UTF_8.name());response.setContentType("multipart/form-data");response.setHeader("content-type", "image/png");ImageIO.write(targetBufferedImage, "png", os);} }

總結

以上是生活随笔為你收集整理的背景图和二维码合成的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。