前言

Java后端生成二维码 底部 侧面带有标题,可调节字号

参考文章

使用Java生成二维码图片(亲测)
Reborn_YY使用Java生成二维码图片
图标素材库
Java后台生成图片,前台实现图片下载

jar

保持和spring同时期版本即可

 <!-- https://mvnrepository.com/artifact/com.google.zxing/core --><!-- 二维码生成工具--><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version></dependency><dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.3.3</version></dependency>

工具类缓冲图像


import com.google.zxing.LuminanceSource;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
public class BufferedImageLuminanceSource extends LuminanceSource {private final BufferedImage image;private final int left;private final int top;public BufferedImageLuminanceSource(BufferedImage image) {this(image, 0, 0, image.getWidth(), image.getHeight());}public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) {super(width, height);int sourceWidth = image.getWidth();int sourceHeight = image.getHeight();if (left + width > sourceWidth || top + height > sourceHeight) {throw new IllegalArgumentException("Crop rectangle does not fit within image data.");}for (int y = top; y < top + height; y++) {for (int x = left; x < left + width; x++) {if ((image.getRGB(x, y) & 0xFF000000) == 0) {image.setRGB(x, y, 0xFFFFFFFF); // = white}}}this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);this.image.getGraphics().drawImage(image, 0, 0, null);this.left = left;this.top = top;}@Overridepublic byte[] getRow(int y, byte[] row) {if (y < 0 || y >= getHeight()) {throw new IllegalArgumentException("Requested row is outside the image: " + y);}int width = getWidth();if (row == null || row.length < width) {row = new byte[width];}image.getRaster().getDataElements(left, top + y, width, 1, row);return row;}@Overridepublic byte[] getMatrix() {int width = getWidth();int height = getHeight();int area = width * height;byte[] matrix = new byte[area];image.getRaster().getDataElements(left, top, width, height, matrix);return matrix;}@Overridepublic boolean isCropSupported() {return true;}@Overridepublic LuminanceSource crop(int left, int top, int width, int height) {return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height);}@Overridepublic boolean isRotateSupported() {return true;}@Overridepublic LuminanceSource rotateCounterClockwise() {int sourceWidth = image.getWidth();int sourceHeight = image.getHeight();AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);Graphics2D g = rotatedImage.createGraphics();g.drawImage(image, transform, null);g.dispose();int width = getWidth();return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);}
}

工具类设置

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 org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang3.StringUtils;
import sun.font.FontDesignMetrics;import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Hashtable;
import java.util.UUID;/*** 二维码生成类** @author 18316**/
public class QRCodeUtils {private static final String CHARSET = "utf-8";private static final String FORMAT_NAME = "jpg";// 二维码尺寸private static final int QRCODE_SIZE = 300;// LOGO宽度private static final int WIDTH = 60;// LOGO高度private static final int HEIGHT = 60;// 字体大小private static final int FONT_SIZE = 18;/*** 生成包含 标题说明 LOGO 的二维码图片** @param title        标题 底部显示* @param content      二维码内容* @param imgPath      LOGO文件路径* @param needCompress LOGO 是否压缩* @return 二维码图片流* @throws Exception*/private static BufferedImage createImage(String title, String content, String imgPath, boolean needCompress) throws Exception {Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);hints.put(EncodeHintType.CHARACTER_SET, CHARSET);hints.put(EncodeHintType.MARGIN, 1);BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,hints);int width = bitMatrix.getWidth();int height = bitMatrix.getHeight();int tempHeight = height;// 二维码图片大小 有文字放大boolean notEmptyTitle = StringUtils.isNotEmpty(title);if (notEmptyTitle) {tempHeight += 20;}BufferedImage image = new BufferedImage(width, tempHeight, BufferedImage.TYPE_INT_RGB);for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);}}// 插入图片LOGOif (StringUtils.isNotEmpty(imgPath)) {QRCodeUtils.insertImage(image, imgPath, needCompress);}//插入文字if (notEmptyTitle) {addFontImage(image, "【" + title + "】");}return image;}/*** 添加 底部图片文字** @param source      图片源* @param declareText 文字本文*/private static void addFontImage(BufferedImage source, String declareText) {//设置文本图片宽高BufferedImage textImage = strToImage(declareText, QRCODE_SIZE, 40);Graphics2D graph = source.createGraphics();//开启文字抗锯齿graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);int width = textImage.getWidth(null);int height = textImage.getHeight(null);Image src = textImage;//画图 文字图片最终显示位置 在Y轴偏移量 从上往下算graph.drawImage(src, 0, QRCODE_SIZE - 20, width, height, null);graph.dispose();}/*** 处理文字大小 生成文字图片** @param str* @param width* @param height* @return 文本图片*/private static BufferedImage strToImage(String str, int width, int height) {BufferedImage textImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g2 = (Graphics2D) textImage.getGraphics();//开启文字抗锯齿g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);g2.setBackground(Color.WHITE);g2.clearRect(0, 0, width, height);g2.setPaint(Color.BLACK);FontRenderContext context = g2.getFontRenderContext();Font font = new Font("微软雅黑", Font.BOLD, FONT_SIZE);g2.setFont(font);LineMetrics lineMetrics = font.getLineMetrics(str, context);FontMetrics fontMetrics = FontDesignMetrics.getMetrics(font);float offset = (width - fontMetrics.stringWidth(str)) / 2;float y = (height + lineMetrics.getAscent() - lineMetrics.getDescent() - lineMetrics.getLeading()) / 2;g2.drawString(str, (int) offset, (int) y);return textImage;}/*** 插入LOGO** @param source       二维码图片* @param imgPath      LOGO图片地址* @param needCompress 是否压缩* @throws Exception*/private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {File file = new File(imgPath);if (!file.exists()) {System.err.println("" + imgPath + "   该文件不存在!");return;}Image src = ImageIO.read(new File(imgPath));int width = src.getWidth(null);int height = src.getHeight(null);if (needCompress) { // 压缩LOGOif (width > WIDTH) {width = WIDTH;}if (height > HEIGHT) {height = HEIGHT;}Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g = tag.getGraphics();g.drawImage(image, 0, 0, null); // 绘制缩小后的图g.dispose();src = image;}// 插入LOGOGraphics2D graph = source.createGraphics();int x = (QRCODE_SIZE - width) / 2;int y = (QRCODE_SIZE - height) / 2;graph.drawImage(src, x, y, width, height, null);Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);graph.setStroke(new BasicStroke(3f));graph.draw(shape);graph.dispose();}/*** 生成二维码(内嵌LOGO) 本地保存** @param content      内容* @param imgPath      LOGO地址* @param destPath     存放目录* @param needCompress 是否压缩LOGO* @throws Exception*/public static String encode(String content, String imgPath, String destPath, boolean needCompress)throws Exception {BufferedImage image = QRCodeUtils.createImage(null,content, imgPath, needCompress);mkdirs(destPath);// 随机生成二维码图片文件名String file = UUID.randomUUID() + ".jpg";ImageIO.write(image, FORMAT_NAME, new File(destPath + "/" + file));return destPath + file;}/*** 创建二维码 底部有标题 LOGO** @param title        标题* @param content      二维码内容* @param imgPath      图片地址* @param needCompress LOGO是否压缩 推荐为True* @param response     响应流*/public static void createTitleImage(String title, String content, String imgPath, boolean needCompress, HttpServletResponse response) {BufferedImage image = null;ImageOutputStream imageOutput = null;long length = 0;try {//创建二维码image = QRCodeUtils.createImage(title, content, imgPath, needCompress);//步骤一:BufferedImage 转 InputStreamByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();imageOutput = ImageIO.createImageOutputStream(byteArrayOutputStream);ImageIO.write(image, "png", imageOutput);//步骤二:获得文件长度length = imageOutput.length();// 文件名 类型需要注明String fileName = "6S-【" + title + "】点检.png";//设置文件长度response.setContentLength((int) length);//输入流InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());//步骤三:传入文件名、输入流、响应fileDownload(fileName, inputStream, response);} catch (Exception e) {throw new RuntimeException(e);}}//文件下载方法,工具类public static void fileDownload(String filename, InputStream input, HttpServletResponse response) {try {byte[] buffer = new byte[input.available()];input.read(buffer);input.close();// 清空responseresponse.reset();// 设置response的Headerresponse.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes("utf-8"), "ISO-8859-1"));OutputStream toClient = new BufferedOutputStream(response.getOutputStream());response.setContentType("application/octet-stream");toClient.write(buffer);toClient.flush();//关闭,即下载toClient.close();}catch (Exception e){e.printStackTrace();}}/*** 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)** @author lanyuan Email: mmm333zzz520@163.com* @date 2013-12-11 上午10:16:36* @param destPath 存放目录*/public static void mkdirs(String destPath) {File file = new File(destPath);// 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)if (!file.exists() && !file.isDirectory()) {file.mkdirs();}}}

调用

有无LOGO调用

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;public class Test {//二维码内容private  static   String content = "https://www.baidu.com";// 二维码保存的路径private   static String path = "D:/Test/";//LOGO本地路径private   static String logopath = "D:/Test/6s1.png";public static void main(String[] args) {//创建有LOGO的二维码System.out.println("开始生成...");QRCode();QRCodeLogo();System.out.println("生成完毕!");//创建有标题的二维码QRCodeUtils.createTitleImage("压机上线工序","https://www.baidu.com","",true,response);}/*** 生成带有LOGO的二维码*/public static void QRCodeLogo() {try {System.out.println(QRCodeUtils.encode(content,logopath,path,true));} catch (WriterException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}catch (Exception e){}}/*** 生成纯二维码*/public static void QRCode() {try {String codeName = UUID.randomUUID().toString();// 二维码的图片名String imageType = "jpg";// 图片类型MultiFormatWriter multiFormatWriter = new MultiFormatWriter();Map<EncodeHintType, String> hints = new HashMap<EncodeHintType, String>();hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, 400, 400, hints);File file1 = new File(path, codeName + "." + imageType);MatrixToImageWriter.writeToFile(bitMatrix, imageType, file1);} catch (WriterException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}catch (Exception e){}}
}


竖版字体(可调字号)

java 字体大小 像素_字体的大小(pt)和像素(px)如何转换?

     /*** 生成包含 标题说明 LOGO 的二维码图片** @param title        标题 底部显示* @param content      二维码内容* @param imgPath      LOGO文件路径* @param needCompress LOGO 是否压缩* @return 二维码图片流* @throws Exception*/private static BufferedImage createImage(String title, String content, String imgPath, boolean needCompress) throws Exception {Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);hints.put(EncodeHintType.CHARACTER_SET, CHARSET);hints.put(EncodeHintType.MARGIN, 1);BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);int width = bitMatrix.getWidth();int height = bitMatrix.getHeight();int tempWidth = width;// 二维码图片大小 有文字按照所在位置加长加宽boolean notEmptyTitle = StringUtils.isNotEmpty(title);if (notEmptyTitle) {tempWidth+=50;}//制作白板 填充二维码BufferedImage image = new BufferedImage(tempWidth, height, BufferedImage.TYPE_INT_RGB);for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);}}// 插入图片LOGOif (StringUtils.isNotEmpty(imgPath)) {QRCodeUtils.insertImage(image, imgPath, needCompress);}//插入文字if (notEmptyTitle) {addFontImage(image, "︻" + title + "︼");}return image;}/*** 添加 底部图片文字** @param source      图片源* @param declareText 文字本文*/private static void addFontImage(BufferedImage source, String declareText) {//设置文本图片宽高BufferedImage textImage = strToImage(declareText, 50, QRCODE_SIZE);Graphics2D graph = source.createGraphics();//开启文字抗锯齿graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);int width = textImage.getWidth(null);int height = textImage.getHeight(null);Image src = textImage;//画图 文字图片最终显示位置 在Y轴偏移量 从上往下算graph.drawImage(src, QRCODE_SIZE, 0, width, height, null);graph.dispose();}/*** 处理文字大小 生成文字图片** @param str* @param width* @param height* @return 文本图片*/private static BufferedImage strToImage(String str, int width, int height) {BufferedImage textImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g2 = (Graphics2D) textImage.getGraphics();//开启文字抗锯齿g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);g2.setBackground(Color.GREEN);g2.clearRect(0, 0, width, height);g2.setPaint(Color.BLACK);int length = str.length();//字体大小int fontSize=0;//字体间距 最多支持32个字 超长可追加设置int fontSpacing=0;if(length<8) {fontSize=FONT_SIZE;fontSpacing=5;}else if(8<length&&length<16){fontSize=12;fontSpacing=3;}else if(16<length&&length<32){fontSize=7;fontSpacing=1;}//加入字体Font font = new Font("微软雅黑", Font.BOLD, fontSize);g2.setFont(font);//字体像素大小  1/2.8float fontPx= (float)(fontSize/72.0)*96;//计算第一个文字书写Y轴位置 从上往下float y=height/2-((length/2) *fontPx);//X轴补偿系数 留白 保证对齐float offset=(width-fontPx)/2;//截取单个字符 循环排列每个字竖坐标String[] split = str.split("");for (String fontStr : split) {g2.drawString(fontStr, (int) offset, (int) y);//下一个字体位置y+=(fontPx+fontSpacing);}return textImage;}

下载

及时性生成推荐IO流,没必要本地存储

     /*** 测试下载* @param response*/@ApiOperation("下载二维码")@GetMapping("/downloadQRImag")public void downloadQRImag(HttpServletResponse response){try {QRCodeUtils.downloadQRImag("https://www.baidu.com","D:/Test/6s3.png",response,true);}catch (Exception e){logger.error(e.getMessage());}}

注意

二维码的复杂程度决定了是否能填充完全

Java生成二维码带LOGO底部标题竖版字体相关推荐

  1. [Java] Java生成二维码带LOGO, LOGO加圆角白框

    先来看看效果: 实现: 生成指定文字内容的二维码 二维码中间嵌入LOGO 二维码做圆角和白色边框处理 新需求不断, 这不, 又来了个想生成带用户头像的需求. 蛮简单的- 在这里造完轮子分享给大家 因为 ...

  2. java生成二维码(带logo)

    利用hutool工具实现java二维码生成 官网链接:https://www.hutool.cn/ 添加依赖 <dependency><groupId>cn.hutool< ...

  3. ZXing3.3.3 生成二维码带logo

    一.前言 我们这里对ZXing不做过多介绍,不清楚的小伙伴可以自行百度. 直接进入正题,这里会封装成工具使用: 二.Hutool工具包+ZXing 这里我们使用Hutool工具包+ZXing,Huto ...

  4. asp.net 生成二维码,带logo,带下方文字

    目标可以生成带网址的信息的二维码,可以是带logo 或者不带logo,或者下方带一行说明文字 nuget 下载二维码管理包 public static Bitmap GenerateQrCode(st ...

  5. vue 生成二维码(带logo)与条形码

    1.生成二维码安装 npm install  --save qrcodejs 实现代码 <template><div><qrcode :url="jmc&quo ...

  6. zxing 生成二维码 带logo

    ·1生成带logo的二维码,并转base64 public static String generateBase64Img(String code_url,int width,int height,S ...

  7. Java生成二维码底部带文字并且返回前端使用img接收

    目录 1.java生成二维码工具类 2.web测试 3.前端处理 4.测试结果 背景 本demo主要针对jdk1.6版本的,但是高版本的同样可以用,如果觉得不舒服可以自行添加高版本的依赖包. 准备工具 ...

  8. java 生成二维码后叠加LOGO并转换成base64

    1.代码 见文末推荐 2.测试 测试1:生成base64码 public static void main(String[] args) throws Exception {String data = ...

  9. Java 生成二维码 zxing生成二维码 条形码 服务端生成二维码 Java生成条形码

    Java 生成二维码 zxing生成二维码 条形码 服务端生成二维码 Java生成条形码 一.关于ZXing 1.ZXing是谷歌开源的支持二维码.条形码 等图形的生成类库:支持生成.和解码功能. G ...

最新文章

  1. Fourinone2.0对分布式文件的简化操作
  2. 《研磨设计模式》chap2 简单工厂simplefactory
  3. 【MM系列】SAP ABAP 编辑字段出现:对象编辑中的错误
  4. 流媒体通信协议HLS与DASH的对比
  5. 第十二届 2021年1月 蓝桥杯青少年组省赛C++组 第1题--第3题(python3实现)
  6. VS2013常用设置和其他
  7. 单片机串口通信与同步异步通信
  8. window下批处理:打开命令窗口且执行后不关闭
  9. javascript的规范
  10. 贝壳找房的深度学习模型迭代及算法优化
  11. 信息产业部颁发计算机网络工程师查询,网络工程师证书查询验证网址及方法
  12. div左对齐与里面的内容偏左但是距离左边有点儿距离
  13. ONL/Debian 和 Ubuntu 版本的对应关系
  14. 如何申请Office 365 E5开发者账号,开通OneDrive 5T空间教程
  15. 谁在“盘”物联网的“网”?
  16. 【NOI2015】BZOJ4199品酒大会题解(SAM+树形DP)
  17. android webview 播放视频总结,Android WebView 播放视频总结~
  18. 基于Qt的收银点餐系统之小票打印(二)
  19. 笔记 vue3 如何引入第三方字体
  20. C++开源游戏推荐,铁路运输大亨OpenTTD

热门文章

  1. 九宫格切图器(每天一个python小项目)
  2. Oracle WebLogic Server 12c: Node Manager配置与使用
  3. wkhtmltopdf(thead)分页问题
  4. 2020年五大学科竞赛国家队成员名单,保送清华仅7人!
  5. 5.5 除法的运算过程
  6. 有道单词导入 大量有道单词 生词本 批量导入 添加 有道单词XML 背单词
  7. Excel分列时拒绝让超过15位的数字变成科学计数法
  8. 细思极恐!大数据和机器学习揭示十二星座的真实面目
  9. 逍遥模拟器(8.0.x版本,系统安卓7.1)安装xposed
  10. 重读《拿破仑传》有感