1、构建maven项目,导入对应依赖

这里引用谷歌的zxing包实现二维码的编码与解码,导入依赖如下所示

<!-- 谷歌二维码 -->
<dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.0</version>
</dependency>

2、编写编码与解码方法

二维码生成工具类如下所示


import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Base64;
import java.util.Hashtable;
import javax.imageio.ImageIO;import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;public class QrCodeUtil {private static final String CHARSET = "utf-8";private static final String IMAGE_SUFFIX = "JPG";/*** 二维码尺寸*/private static final int QRCODE_SIZE = 300;/*** LOGO宽度*/private static final int WIDTH = 60;/*** LOGO高度*/private static final int HEIGHT = 60;/*** 生成二维码图片, 可自定义容错率* @param content  二维码内容* @param logoPath  logo图片路径* @param needCompress  是否需要压缩* @param level  L-7%  M-15%   Q-25%  H-30%  容错级别* @return* @throws Exception*/private static BufferedImage createImage(String content, String logoPath, boolean needCompress, ErrorCorrectionLevel level) throws Exception {Hashtable hints = new Hashtable();hints.put(EncodeHintType.ERROR_CORRECTION, level);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();BufferedImage image = new BufferedImage(width, 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);}}if (logoPath == null || "".equals(logoPath)) {return image;}// 插入图片,即中间显示的logoinsertImage(image, logoPath, needCompress);return image;}/*** 生成二维码图片* @param content  二维码文字内容* @param logoPath  logo图片路径* @param needCompress  是否需要压缩* @return* @throws Exception*/private static BufferedImage createImage(String content, String logoPath, boolean needCompress) throws Exception {return createImage(content, logoPath, needCompress, ErrorCorrectionLevel.H);}/*** 往二维码插入图片(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 image = ImageIO.read(new File(imgPath));int width = image.getWidth(null);int height = image.getHeight(null);// 压缩LOGOif (needCompress) {width = width > WIDTH ? WIDTH : width;height = height > HEIGHT ? HEIGHT : height;image = image.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();}// 插入LOGOGraphics2D graph = source.createGraphics();int x = (QRCODE_SIZE - width) / 2;int y = (QRCODE_SIZE - height) / 2;graph.drawImage(image, 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();}/*** 编码生成二维码图片,固化到硬盘* @param content  二维码文字内容* @param logoPath  插入的logo路径* @param destPath  生成的二维码输出路径* @param needCompress  是否需要压缩* @param level  容错率* @throws Exception*/public static void encode(String content, String logoPath, String destPath, boolean needCompress, ErrorCorrectionLevel level) throws Exception {mkdirs(destPath);ImageIO.write(createImage(content, logoPath, needCompress, level), IMAGE_SUFFIX, new File(destPath));}/*** 编码生成二维码图片,固化到硬盘* @param content  二维码文字内容* @param logoPath  logo图片路径* @param destPath  生成的二维码输出路径* @param needCompress  是否需要压缩* @throws Exception*/public static void encode(String content, String logoPath, String destPath, boolean needCompress) throws Exception {mkdirs(destPath);ImageIO.write(createImage(content, logoPath, needCompress), IMAGE_SUFFIX, new File(destPath));}/*** 编码生成二维码图片,固化到硬盘* @param content  二维码文字内容* @param logoPath  logo图片路径* @param destPath  生成的二维码输出路径* @throws Exception*/public static void encode(String content, String logoPath, String destPath) throws Exception {encode(content, logoPath, destPath, false);}/*** 编码生成二维码图片,固化到硬盘* @param content  二维码文字内容* @param destPath  生成的二维码输出路径* @throws Exception*/public static void encode(String content, String destPath) throws Exception {encode(content, null, destPath, false);}/*** 编码生成二维码图片,输出到流* @param content  二维码文字内容* @param logoPath  logo图片路径* @param output  输出流* @param needCompress  是否需要压缩* @throws Exception*/public static void encode(String content, String logoPath, OutputStream output, boolean needCompress) throws Exception {ImageIO.write(createImage(content, logoPath, needCompress), IMAGE_SUFFIX, output);}/*** 编码生成二维码图片,输出到流* @param content  二维码文字内容* @param output  输出流* @throws Exception*/public static void encode(String content, OutputStream output) throws Exception {encode(content, null, output, false);}/*** 编码生成二维码图片,转化为base64字符串* @param content  二维码文字内容* @param imgPath  logo图片路径* @param needCompress  是否需要压缩* @param level  容错率* @param imageSuffix  生成的图片后缀* @return* @throws Exception*/public static String encode(String content, String imgPath, boolean needCompress, ErrorCorrectionLevel level, String imageSuffix) throws Exception {imageSuffix = (imageSuffix == null || "".equals(imageSuffix)) ? IMAGE_SUFFIX : imageSuffix;BufferedImage image = createImage(content, imgPath, needCompress, level);ByteArrayOutputStream stream = new ByteArrayOutputStream();ImageIO.write(image, imageSuffix, stream);return Base64.getEncoder().encodeToString(stream.toByteArray());}/*** 编码生成二维码图片,直接返回图片对象* @param content  二维码文字内容* @param logoPath  logo图片路径* @param needCompress  是否需要压缩* @return* @throws Exception*/public static BufferedImage encode(String content, String logoPath, boolean needCompress) throws Exception {return createImage(content, logoPath, needCompress);}/*** 二维码解码读取文字信息* @param image 二维码图片* @return* @throws Exception*/public static String decode(BufferedImage image) throws Exception {if (image == null) { return null; }BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));Hashtable hints = new Hashtable();//设置编码方式hints.put(DecodeHintType.CHARACTER_SET, CHARSET);//优化精度,解决com.google.zxing.NotFoundExceptionhints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);//开启PURE_BARCODE模式(复杂模式)hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);Result result = new MultiFormatReader().decode(bitmap, hints);return result.getText();}/*** 二维码解码读取文字信息* @param file 二维码图片* @return* @throws Exception*/public static String decode(File file) throws Exception {return decode(ImageIO.read(file));}/*** 二维码解码读取文字信息* @param base64Str  二维码图片base64格式字符串* @return* @throws Exception*/public static String decode(String base64Str) throws Exception{return decode(ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(base64Str))));}/*** 创建文件夹* @param destPath  文件夹路径*/public static void mkdirs(String destPath) {File file = new File(destPath);// 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)if (!file.exists() && !file.isDirectory()) {file.mkdirs();}}public static 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);}}
}

主要方法功能描述如下:

  • createImage():生成二维码图片

createImage()重载了两个方法,其中 createImage(String content, String logoPath, boolean needCompress, ErrorCorrectionLevel level)方法可通过level参数调节二维码容错率;createImage(String content, String logoPath, boolean needCompress)方法使用固定的容错率:ErrorCorrectionLevel.H。

  • insertImage():往二维码插入图片(logo),可以调用此方法在二维码中间位置插入一个logo
  • encode():进行二维码编码
    此方法重载了几个方法返回不同的结果,如:直接生成二维码图片固化到硬盘;生成BASE64字符串返回;直接返回BufferedImage图片对象。
  • decode():对二维码进行解码,获取文字内容

3、编写测试代码

编写测试代码进行不同返回对象的测试,测试代码如下所示

public static void main(String[] args) throws Exception {// 存放在二维码中的内容String text = "使用 com.google.zxing 依赖生成二维码图片,encode()方法生成二维码图片,decode()方法将二维码解码获取文字内容\n" ;// 嵌入二维码的图片(logo)路径String imgPath = "E:/templates/0.jpg";// 生成的二维码的路径及名称String destPath = "E:/templates/qrcode/1.jpg";// 生成的二维码的路径及名称String destPath1 = "E:/templates/qrcode/2.jpg";//生成不带logo的二维码QrCodeUtil.encode(text, null, destPath, true, ErrorCorrectionLevel.L);//生成带logo的二维码QrCodeUtil.encode(text, imgPath, destPath1, true, ErrorCorrectionLevel.L);// 解析二维码String str = QrCodeUtil.decode(new File(destPath1));// 打印出解析出的内容System.out.println(str);//图片生成base64字符串String base64 = QrCodeUtil.encode(text, imgPath, true, ErrorCorrectionLevel.L, "png");System.out.println("\nbase64字符串:" + base64);System.out.println("\n二维码解码内容:" + QrCodeUtil.decode(base64));}

4、可能遇到的问题

  1. 解析二维码报错com.google.zxing.NotFoundException
    原因:二维码所有的bit都是0,生成二维码时白色像素使用透明色填充。在显示时因为背景是白色,所以看上去和用手机扫都没有问题,但是在代码识别的时候会把透明色识别为黑色,这样就导致整个二维码图片全是黑色像素,抛出com.google.zxing.NotFoundException异常。
    解决方案:优化精度,解码时配置参数
        //优化精度,解决com.google.zxing.NotFoundExceptionhints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);//开启PURE_BARCODE模式(复杂模式)hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
  1. 扫码时由于文字太多无法识别
    解决方案: 调整ErrorCorrectionLevel 参数,适当调整容错率(7%~30%)。
    对应四个级别:
    ErrorCorrectionLevel.L (7%)
    ErrorCorrectionLevel.M (15%)
    ErrorCorrectionLevel.Q (25%)
    ErrorCorrectionLevel.H (30%)
    容错率越高,二维码的有效像素点越多。

Java实现二维码编码与解码相关推荐

  1. Java利用QRCode.jar包实现二维码编码与解码

    QRcode是日本人94年开发出来的.首先去QRCode的官网http://swetake.com/qrcode/java/qr_java.html,把要用的jar包下下来,导入到项目里去.qrcod ...

  2. 条形码和二维码编码解码工具类源码

    有一个好的工具,会让你的开发事半功倍.再将讲这个工具类之前,我先给小白补充一点条形码和二维码(以下基础知识选自,我本科阶段的一本教材:<物联网导论>(刘云浩 编著).有对物联网感兴趣的,可 ...

  3. java二维码编码生成并转换成流传入前端页面

    java二维码编码生成并转换成流传入前端页面 这里主要用了com.google.zxing的依赖,这个依赖主要可以完成图片叠加.二维码生成和图片加文字等功能. ①添加依赖 <dependency ...

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

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

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

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

  6. java实现二维码生成的几个方法

    java实现二维码生成的几个方法 分类: J2EE2013-06-13 20:32 10390人阅读 评论(1) 收藏 举报 1: 使用SwetakeQRCode在Java项目中生成二维码  http ...

  7. java 生成 二维码

    blog迁移至 : http://www.micmiu.com 周末试用下Android手机的二维码扫描软件,扫描了下火车票.名片等等,觉得非常不错很有意思的.当然Java也可以实现这些,现在就分享下 ...

  8. Java实现二维码生成与识别

    java实现QRCODE二维码的编码与解码实例 众所周知,爪哇,是一种神奇的编程语言,用JAVA 实现某一个功能,只是随便上网找一些对应的实现JAR包即可,于是,有了像JAR114这样专门提供给 爪哇 ...

  9. java 生成二维码 QRCode、zxing 两种方式

    版权声明:本文为 testcs_dn(微wx笑) 原创文章,非商用自由转载-保持署名-注明出处,谢谢. https://blog.csdn.net/testcs_dn/article/details/ ...

最新文章

  1. vue 热更新无反应_不吹不黑谈谈 vue 的 SFC 和 template
  2. Linux kdb命令
  3. stm32f103电子钟心得体会_浅谈STM32_RTC闹钟
  4. android webView的使用
  5. 数据库编程起别名的3中方式
  6. Unity按钮禁用和变灰
  7. Python数据分析学习
  8. 如何在生产环境下用好EFCore
  9. 【BZOJ4774】修路 [斯坦纳树]
  10. ApacheCN 交流社区一周热点 2019.4 wk1
  11. SAP License:SAP中的报表查询
  12. List求交并补集--IEqualityComparer实现
  13. bootstrap框架写手机端app模板也很漂亮
  14. 小白爬虫入门~python爬取职友集招聘职位信息
  15. 如何在WordPress菜单中显示图标[WordPress插件]
  16. 还爱着你心中曾经那朵红玫瑰吗?
  17. 十年带队经验,万字长文分享:如何管理好一个程序员团队?
  18. 如何一次打开多个Word文档
  19. c汇编语言例题,第三章 汇编语言程序设计例题习题
  20. python爬取知乎回答并进行舆情分析:爬取数据部分

热门文章

  1. [附源码]SSM计算机毕业设计中青年健康管理监测系统JAVA
  2. 写给女朋友的3D旋转相册
  3. elasticsearch学习(六):IK分词器
  4. 修改 messagebox 按钮文字
  5. 刚买的新电脑怎么安装软件
  6. Genesis非洲代理与加纳共和国政府正式签订紧密合作协议
  7. python3 下载特定网页上的文件
  8. matlab三维图 魔方,matlab制作魔方图片
  9. 常见功能测试点的测试用例集合--51testing
  10. 免费、高清、无版权图片都从哪里找?