java zxing怎麼合成複雜二維碼圖片
整體思路:
引入zxing成熟的二維碼生成接口,生成標準二維碼文件,透過java圖形圖像處理API為二維碼添加相關文字描述,根據需要,可以為合成後的圖片添加相關背景。範例如下圖所示:
1.先拿點位圖來說,產生二維碼圖片核心程式碼如下
/** * 定义二维码的参数 */ HashMap<EncodeHintType, Object> hints = new HashMap(); //指定字符编码为“utf-8” hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); //指定二维码的纠错等级为中级 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); //设置图片的边距 hints.put(EncodeHintType.MARGIN, 1); /** * 生成二维码 */ try { BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_WIDTH, QRCODE_HEIGHT, hints); Path file = new File(filePath).toPath(); MatrixToImageWriter.writeToPath(bitMatrix, format, file); } catch (Exception e) { log.error("二维码生成出错:/permitDownload: error", e); }
2.為二維碼新增文字
/** * 给二维码下方添加说明文字 * * @param image 原二维码 * @param topText 顶部说明文字 * @param downText 底部说明文字 * @return 带说明文字的二维码 */ private static BufferedImage addNote(BufferedImage image, String topText, String downText) { Image src = image.getScaledInstance(QRCODE_WIDTH, QRCODE_HEIGHT, Image.SCALE_DEFAULT); BufferedImage tag = new BufferedImage(QRCODE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = tag.createGraphics();//设置文字 g2.setColor(Color.BLACK); g2.setBackground(Color.WHITE); g2.clearRect(0,0,QRCODE_WIDTH, IMAGE_HEIGHT); //设置顶部文本并计算坐标 // 保证操作系统包含“宋体”字体,如果没有上传字体至JAVA_HOME/jre/lib/fonts下 FontMetrics fm = getFontByWidth(new Font("宋体", Font.PLAIN, DEFAULT_FONT_SIZE), topText, g2); //文字的宽度 int fontWidth = fm.stringWidth(topText); //文字高度 int fontHeight = fm.getHeight(); /** * 顶部添加文字并居中 */ g2.drawString(topText, (QRCODE_WIDTH - fontWidth) / 2, (TEXT_DEFAULT_HEIGHT - fontHeight) / 2 + fm.getFont().getSize()); /** * 绘制二维码 */ g2.drawImage(src, 0, TEXT_DEFAULT_HEIGHT, null); // 设置底部文字字体并计算坐标 // 保证操作系统包含“宋体”字体,如果没有上传字体至JAVA_HOME/jre/lib/fonts下 fm = getFontByWidth(new Font("宋体", Font.PLAIN, DEFAULT_FONT_SIZE), downText, g2); //文字的宽度 fontWidth = fm.stringWidth(downText); //文字高度 fontHeight = fm.getHeight(); /** * 添加底部文字 */ g2.drawString(downText, (QRCODE_WIDTH - fontWidth) / 2, QRCODE_HEIGHT + TEXT_DEFAULT_HEIGHT+(TEXT_DEFAULT_HEIGHT - fontHeight) / 2 + fm.getFont().getSize()); g2.dispose(); image = tag; image.flush(); return image; }
知識點: 底部文字長度會變,目前設計只放一行文字,所以根據字數多少會動態改變文字大小在一個合理區間(不至於太小無法識別),使用FontMetrics 對象,這個點會對多數同學有幫助
3.動態修改字體及大小
/** * 根据文字长度改变文字大小 * * @param font 默认字体 * @param note 文字内容 * @param g2 图像画布 * @return 处理后的字体封装 */ private static FontMetrics getFontByWidth(Font font, String note, Graphics2D g2) { FontMetrics fm = g2.getFontMetrics(font); int textWidth = fm.stringWidth(note);//文字的宽度 if (textWidth > QRCODE_WIDTH) { int fontSize = (int) ((TEMP_PARAM / textWidth) * font.getSize()); font = new Font(font.getName(), font.getStyle(), fontSize); } g2.setFont(font); return g2.getFontMetrics(font); }
4.最後一步將藍色底圖與二維碼圖片合成,就可以了。
圖片合成四部曲
第一步:建立畫布,需要設定畫布的寬、高,單位應該是像素
BufferedImage tag = new BufferedImage(QRCODE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
第二步驟: 在畫布上建立圖形物件Graphics2D,可以根據你對圖像知識點的了解設定如背景、前景、邊框、寬度等資訊
Graphics2D g2 = tag.createGraphics();//设置文字
第三步: 合成圖片,過程中的圖片新增順序、圖片大小、座標位置會影響最終的呈現效果,如果最終效果沒有達到設計需求,調整這三個參數一定會有所幫助
Image src = image.getScaledInstance(QRCODE_WIDTH, QRCODE_HEIGHT, Image.SCALE_DEFAULT); ... /** * 绘制二维码 */ g2.drawImage(src, 0, TEXT_DEFAULT_HEIGHT, null);
第四步: 產生最終的新圖片
/** * 给二维码图片添加背景图片 * * @param qrPic 二维码 * @param backImage 背景图片 */ private static void createNewPng(File qrPic, BufferedImage backImage) { try { if (!qrPic.isFile()) { log.error("二维码临时路径不存在!"); } /** * 读取背景图片,并构建绘图对象--画布 */ Graphics2D g = backImage.createGraphics(); /** * 读取二维码图片 */ BufferedImage qrcodeImage = ImageIO.read(qrPic); //开始绘制图片 g.drawImage(qrcodeImage, 48, 120, qrcodeImage.getWidth(), qrcodeImage.getHeight(), null); g.dispose(); ImageIO.write(backImage, "png", qrPic); } catch (Exception e) { log.error("绘制二维码出错!"); } }
第二張圖片和第一張圖片產生過程相同,只是將文中【2. 為二維碼新增文字】中的順序由上、中、下變為左、右即可
踩過的坑
背景圖片像素、大小需要和二維碼匹配,否則會出現二維碼與背景比例嚴重失調或二維碼顯示不完整
二維碼新增文字亂碼開發環境(windows),測試環境(centos 伺服器版)。本機開發測試沒有任何問題,打包部署至伺服器後所有中文字元出現亂碼(各種轉碼,字體設置,調試整了很久),問題仍然沒有任何變化。最終靈光一現懷疑是系統字體問題,查了測試環境(centos)字體資訊確實沒有“宋體”,設定成系統自有或預設的字體,問題還在。最後從(c:\windows\fonts\simsun.ttc)開發系統中copy字體至測試系統(JAVA_HOME/jre/libs/fonts)後重新啟動應用,問題已完美解決。系統安裝部署要準備字體有點麻煩,不知道還有沒有更好的方法,字體有邏輯字體和實體字體,愛、先這樣吧。
背景圖片載入問題項目為springboot項目,背景圖片存放在resources資料夾下,本地開發測試未見異常,打包部署至伺服器後背景圖片無法找到,原始程式碼如下
String backFilePath = "template/down.png"; ClassPathResource resource = new ClassPathResource(backFilePath); File file = resource.getFile();
在網路上找載入圖片的方法都使用過,沒有效果,最後修改為輸入流,圖片合成正常,程式碼如下
/** * 必须通过流方式,否则不同操作系统无法拿到背景图片信息 */ String backFilePath = "template/down.png"; ClassPathResource resource = new ClassPathResource(backFilePath); BufferedImage bi = ImageIO.read(resource.getInputStream());
以上是java zxing怎麼合成複雜二維碼圖片的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4
