java实现二维码的生成与解析
Posted 苏克俊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java实现二维码的生成与解析相关的知识,希望对你有一定的参考价值。
二维码的生成及解析的低层实现并不简单,我们只需要知道怎么使用就可以了,参考博客:https://blog.csdn.net/jam_fanatic/article/details/82818857
1.maven中jar包引用com.google.zxing;
2.创建QRCodeUtil二维码工具类,使用谷歌提供的帮助类BufferedImageLuminanceSource绘制二维码。
生成二维码:QRCodeUtil.encode(编码到二维码中的内容, 嵌入二维码的图片路径, 生成的二维码的存放路径, 图片是否进行压缩);
解析二维码:QRCodeUtil.decode(要解析的二维码的存放路径);
注意事项:如果你想让别人扫描后跳转一个页面的话,直接在编码的方法里,将编码内容改为一个地址就可以了,这样别人扫描二维码后会自动跳转。二维码存的信息越多,二维码图片也就越复杂,容错率也就越低,识别率也越低,并且二维码能存的内容大小也是有限的(大概500个汉字左右)
1 package com.gsafety.consumer.util; 2 3 import java.awt.Graphics; 4 import java.awt.Graphics2D; 5 import java.awt.Image; 6 import java.awt.Shape; 7 import java.awt.geom.RoundRectangle2D; 8 import java.awt.image.BufferedImage; 9 import java.io.File; 10 import java.io.OutputStream; 11 import java.util.Hashtable; 12 13 import javax.imageio.ImageIO; 14 15 import com.google.zxing.BarcodeFormat; 16 import com.google.zxing.BinaryBitmap; 17 import com.google.zxing.DecodeHintType; 18 import com.google.zxing.EncodeHintType; 19 import com.google.zxing.MultiFormatReader; 20 import com.google.zxing.MultiFormatWriter; 21 import com.google.zxing.Result; 22 import com.google.zxing.client.j2se.BufferedImageLuminanceSource; 23 import com.google.zxing.common.BitMatrix; 24 import com.google.zxing.common.HybridBinarizer; 25 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 26 27 import lombok.extern.slf4j.Slf4j; 28 29 /** 30 * 二维码工具类 31 */ 32 @Slf4j 33 public class QRCodeUtil { 34 35 36 37 private static final String CHARSET = "utf-8"; 38 private static final String FORMAT_NAME = "JPG"; 39 // 二维码尺寸 40 private static final int QRCODE_SIZE = 250; 41 // LOGO宽度 42 private static final int WIDTH = 50; 43 // LOGO高度 44 private static final int HEIGHT = 50; 45 static SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(0,0); 46 private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception { 47 Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>(); 48 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); 49 hints.put(EncodeHintType.CHARACTER_SET, CHARSET); 50 hints.put(EncodeHintType.MARGIN, 0); 51 BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, 52 hints); 53 int width = bitMatrix.getWidth(); 54 int height = bitMatrix.getHeight(); 55 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 56 for (int x = 0; x < width; x++) { 57 for (int y = 0; y < height; y++) { 58 image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); 59 } 60 } 61 if (imgPath == null || "".equals(imgPath)) { 62 return image; 63 } 64 // 插入图片 65 QRCodeUtil.insertImage(image, imgPath, needCompress); 66 return image; 67 } 68 /** 69 * 插入LOGO 70 * @param source 二维码图片 71 * @param imgPath LOGO图片地址 72 * @param needCompress 是否压缩 73 * @throws Exception 74 */ 75 private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception { 76 File file = new File(imgPath); 77 if (!file.exists()) { 78 log.info("{}该文件不存在!",imgPath); 79 return; 80 } 81 Image src = ImageIO.read(new File(imgPath)); 82 int width = src.getWidth(null); 83 int height = src.getHeight(null); 84 if (needCompress) { // 压缩LOGO 85 if (width > WIDTH) { 86 width = WIDTH; 87 } 88 if (height > HEIGHT) { 89 height = HEIGHT; 90 } 91 Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH); 92 BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 93 Graphics g = tag.getGraphics(); 94 g.drawImage(image, 0, 0, null); // 绘制缩小后的图 95 g.dispose(); 96 src = image; 97 } 98 // 插入LOGO 99 Graphics2D graph = source.createGraphics(); 100 int x = (QRCODE_SIZE - width) / 2; 101 int y = (QRCODE_SIZE - height) / 2; 102 // graph.setClip(new RoundRectangle2D.Double(0, 0, width, height, 90, 90)); 103 graph.drawImage(src, x, y, width, height, null); 104 Shape shape = new RoundRectangle2D.Float(x, y, width, width, 90,90); 105 // graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 106 // graph.setStroke(new BasicStroke(-1f)); 107 graph.draw(shape); 108 graph.dispose(); 109 } 110 111 /** 112 * 113 * 生成二维码(内嵌LOGO) 114 * @param content 内容 115 * @param imgPath LOGO地址 116 * @param destPath 存放目录 117 * @param needCompress 是否压缩LOGO 118 * @throws Exception 119 */ 120 121 public static String encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception { 122 BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress); 123 mkdirs(destPath); 124 String random = snowflakeIdWorker.nextId(); 125 String file = random + ".jpg"; 126 ImageIO.write(image, FORMAT_NAME, new File(destPath + "/" + file)); 127 return "/consumer_qrcode/"+file; 128 } 129 130 /** 131 * 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常) 132 * @author 133 * @date 2013-12-11 上午10:16:36 134 * @param destPath 存放目录 135 */ 136 public static void mkdirs(String destPath) { 137 File file = new File(destPath); 138 // 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常) 139 if (!file.exists() && !file.isDirectory()) { 140 file.mkdirs(); 141 } 142 } 143 144 /** 145 * 146 * 生成二维码(内嵌LOGO) 147 * @param content 内容 148 * @param imgPath LOGO地址 149 * @param destPath 存储地址 150 * @throws Exception 151 */ 152 public static void encode(String content, String imgPath, String destPath) throws Exception { 153 QRCodeUtil.encode(content, imgPath, destPath, false); 154 } 155 156 /** 157 * 158 * 生成二维码 159 * @param content 内容 160 * @param destPath 存储地址 161 * @param needCompress 是否压缩LOGO 162 * @throws Exception 163 */ 164 public static void encode(String content, String destPath, boolean needCompress) throws Exception { 165 QRCodeUtil.encode(content, null, destPath, needCompress); 166 } 167 168 /** 169 * 170 * 生成二维码 171 * @param content 内容 172 * @param destPath 存储地址 173 * @throws Exception 174 */ 175 public static void encode(String content, String destPath) throws Exception { 176 QRCodeUtil.encode(content, null, destPath, false); 177 } 178 179 /** 180 * 181 * 生成二维码(内嵌LOGO) 182 * @param content 内容 183 * @param imgPath LOGO地址 184 * @param output 输出流 185 * @param needCompress 是否压缩LOGO 186 * @throws Exception 187 */ 188 public static void encode(String content, String imgPath, OutputStream output, boolean needCompress) 189 throws Exception { 190 BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress); 191 ImageIO.write(image, FORMAT_NAME, output); 192 } 193 194 /** 195 * 196 * 生成二维码 197 * @param content 内容 198 * @param output 输出流 199 * @throws Exception 200 */ 201 public static void encode(String content, OutputStream output) throws Exception { 202 QRCodeUtil.encode(content, null, output, false); 203 } 204 205 /** 206 * 207 * 解析二维码 208 * @param file 二维码图片 209 * @return 210 * @throws 211 * Exception 212 */ 213 public static String decode(File file) throws Exception { 214 BufferedImage image; 215 image = ImageIO.read(file); 216 if (image == null) { 217 return null; 218 } 219 BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image); 220 BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); 221 Result result; 222 Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(); 223 // 解码设置编码方式为:utf-8, 224 hints.put(DecodeHintType.CHARACTER_SET, CHARSET); 225 //优化精度 226 hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); 227 //复杂模式,开启PURE_BARCODE模式 228 hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE); 229 result = new MultiFormatReader().decode(bitmap, hints); 230 231 String resultStr = result.getText(); 232 return resultStr; 233 } 234 235 /** 236 * 237 * 238 * 解析二维码 239 * @param path 二维码图片地址 240 * @return 241 * @throws Exception 242 */ 243 public static String decode(String path) throws Exception { 244 return QRCodeUtil.decode(new File(path)); 245 } 246 247 public static void main(String[] args) throws Exception { 248 String text = "爱你一万年"; // 二维码内容 249 String logoPath = "D:\\\\work\\\\二维码.png"; //嵌入二维码的图片路径 250 String destPath = "D:\\\\work";//生成二维码的地址 251 QRCodeUtil.encode(text, logoPath, destPath, false);//生成二维码 252 // String decode = QRCodeUtil.decode("D:\\\\work/659518998202810368.jpg");//解析二维码 253 // System.out.println(decode);//答应解析二维码的内容 254 } 255 }
待补充。。。
以上是关于java实现二维码的生成与解析的主要内容,如果未能解决你的问题,请参考以下文章