JAVA中生成、解析二维码的方法并不复杂,使用google的zxing包就可以实现。下面的方法包含了生成二维码、在中间附加logo、添加文字功能,并有解析二维码的方法。
一、下载zxing的架包,并导入项目中,如下:
最主要的包都在com.google.zxing.core下。如果是maven项目,maven依赖如下:
1 <dependency> 2 <groupId>com.google.zxing</groupId> 3 <artifactId>core</artifactId> 4 <version>3.3.0</version> 5 </dependency>
二、二维码生成,附上代码例子,如下:
1 public class TestQRcode { 2 3 private static final int BLACK = 0xFF000000; 4 private static final int WHITE = 0xFFFFFFFF; 5 private static final int margin = 0; 6 private static final int LogoPart = 4; 7 8 /** 9 * 生成二维码矩阵信息 10 * @param content 二维码图片内容 11 * @param width 二维码图片宽度 12 * @param height 二维码图片高度 13 */ 14 public static BitMatrix setBitMatrix(String content, int width, int height){ 15 Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>(); 16 hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码 17 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级 18 hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小 19 BitMatrix bitMatrix = null; 20 try { 21 bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); 22 } catch (WriterException e) { 23 e.printStackTrace(); 24 } 25 return bitMatrix; 26 } 27 28 /** 29 * 将二维码图片输出 30 * @param matrix 二维码矩阵信息 31 * @param format 图片格式 32 * @param outStream 输出流 33 * @param logoPath logo图片路径 34 */ 35 public static void writeToFile(BitMatrix matrix, String format, OutputStream outStream, String logoPath) throws IOException { 36 BufferedImage image = toBufferedImage(matrix); 37 // 加入LOGO水印效果 38 if (StringUtils.isNotBlank(logoPath)) { 39 image = addLogo(image, logoPath); 40 } 41 ImageIO.write(image, format, outStream); 42 } 43 44 /** 45 * 生成二维码图片 46 * @param matrix 二维码矩阵信息 47 */ 48 public static BufferedImage toBufferedImage(BitMatrix matrix) { 49 int width = matrix.getWidth(); 50 int height = matrix.getHeight(); 51 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); 52 for (int x = 0; x < width; x++) { 53 for (int y = 0; y < height; y++) { 54 image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); 55 } 56 } 57 return image; 58 } 59 60 /** 61 * 在二维码图片中添加logo图片 62 * @param image 二维码图片 63 * @param logoPath logo图片路径 64 */ 65 public static BufferedImage addLogo(BufferedImage image, String logoPath) throws IOException { 66 Graphics2D g = image.createGraphics(); 67 BufferedImage logoImage = ImageIO.read(new File(logoPath)); 68 // 计算logo图片大小,可适应长方形图片,根据较短边生成正方形 69 int width = image.getWidth() < image.getHeight() ? image.getWidth() / LogoPart : image.getHeight() / LogoPart; 70 int height = width; 71 // 计算logo图片放置位置 72 int x = (image.getWidth() - width) / 2; 73 int y = (image.getHeight() - height) / 2; 74 // 在二维码图片上绘制logo图片 75 g.drawImage(logoImage, x, y, width, height, null); 76 // 绘制logo边框,可选 77 // g.drawRoundRect(x, y, logoImage.getWidth(), logoImage.getHeight(), 10, 10); 78 g.setStroke(new BasicStroke(2)); // 画笔粗细 79 g.setColor(Color.WHITE); // 边框颜色 80 g.drawRect(x, y, width, height); // 矩形边框 81 logoImage.flush(); 82 g.dispose(); 83 return image; 84 } 85 86 /** 87 * 为图片添加文字 88 * @param pressText 文字 89 * @param newImage 带文字的图片 90 * @param targetImage 需要添加文字的图片 91 * @param fontStyle 字体风格 92 * @param color 字体颜色 93 * @param fontSize 字体大小 94 * @param width 图片宽度 95 * @param height 图片高度 96 */ 97 public static void pressText(String pressText, String newImage, String targetImage, int fontStyle, Color color, int fontSize, int width, int height) { 98 // 计算文字开始的位置 99 // x开始的位置:(图片宽度-字体大小*字的个数)/2 100 int startX = (width-(fontSize*pressText.length()))/2; 101 // y开始的位置:图片高度-(图片高度-图片宽度)/2 102 int startY = height-(height-width)/2 + fontSize; 103 try { 104 File file = new File(targetImage); 105 BufferedImage src = ImageIO.read(file); 106 int imageW = src.getWidth(null); 107 int imageH = src.getHeight(null); 108 BufferedImage image = new BufferedImage(imageW, imageH, BufferedImage.TYPE_INT_RGB); 109 Graphics g = image.createGraphics(); 110 g.drawImage(src, 0, 0, imageW, imageH, null); 111 g.setColor(color); 112 g.setFont(new Font(null, fontStyle, fontSize)); 113 g.drawString(pressText, startX, startY); 114 g.dispose(); 115 FileOutputStream out = new FileOutputStream(newImage); 116 ImageIO.write(image, "png", out); 117 out.close(); 118 } catch (Exception e) { 119 e.printStackTrace(); 120 } 121 } 122 123 public static void main(String[] args) { 124 String content = "http://www.baidu.com"; 125 String logoPath = "C:/logo.png"; 126 String format = "jpg"; 127 int width = 180; 128 int height = 220; 129 BitMatrix bitMatrix = setBitMatrix(content, width, height); 130 // 可通过输出流输出到页面,也可直接保存到文件 131 OutputStream outStream = null; 132 String path = "c:/qr"+new Date().getTime()+".png"; 133 try { 134 outStream = new FileOutputStream(new File(path)); 135 writeToFile(bitMatrix, format, outStream, logoPath); 136 outStream.close(); 137 } catch (Exception e) { 138 e.printStackTrace(); 139 } 140 // 添加文字效果 141 int fontSize = 12; // 字体大小 142 int fontStyle = 1; // 字体风格 143 String text = "测试二维码"; 144 String withTextPath = "c:/text"+new Date().getTime()+".png"; 145 pressText(text, withTextPath, path, fontStyle, Color.BLUE, fontSize, width, height); 146 } 147 }
三、生成效果如下:
代码注释比较详细,就不多解释啦,大家可以根据自己的需求进行调整。
PS:
1、如果想生成带文字的二维码,记得要用长方形图片,为文字预留空间。
2、要生成带logo的二维码要注意遮挡率的问题,setBitMatrix()方法中ErrorCorrectionLevel.H这个纠错等级参数决定了二维码可被遮挡率。对应如下:
L水平 | 7%的字码可被修正 |
M水平 | 15%的字码可被修正 |
Q水平 | 25%的字码可被修正 |
H水平 | 30%的字码可被修正 |
四、二维码解析,附上代码例子,如下:
1 /** 2 * 解析二维码图片 3 * @param filePath 图片路径 4 */ 5 public static String decodeQR(String filePath) { 6 if ("".equalsIgnoreCase(filePath) && filePath.length() == 0) { 7 return "二维码图片不存在!"; 8 } 9 String content = ""; 10 EnumMap<DecodeHintType, Object> hints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class); 11 hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码 12 try { 13 BufferedImage image = ImageIO.read(new FileInputStream(filePath)); 14 LuminanceSource source = new BufferedImageLuminanceSource(image); 15 Binarizer binarizer = new HybridBinarizer(source); 16 BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer); 17 MultiFormatReader reader = new MultiFormatReader(); 18 Result result = reader.decode(binaryBitmap, hints); 19 content = result.getText(); 20 } catch (Exception e) { 21 e.printStackTrace(); 22 } 23 return content; 24 }
可以从二维码图片中解析出具体的内容。