生成二维码工具类:
1 import java.awt.geom.AffineTransform; 2 import java.awt.image.AffineTransformOp; 3 import java.awt.image.BufferedImage; 4 import java.io.ByteArrayOutputStream; 5 import java.io.IOException; 6 import java.util.Hashtable; 7 8 import javax.imageio.ImageIO; 9 10 import org.apache.commons.codec.binary.Base64; 11 12 import com.google.zxing.BarcodeFormat; 13 import com.google.zxing.EncodeHintType; 14 import com.google.zxing.common.BitMatrix; 15 import com.google.zxing.qrcode.QRCodeWriter; 16 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 17 18 public class QRCodeUtil 19 { 20 21 private static final int BLACK = 0xFF000000; 22 23 private static final int WHITE = 0xFFFFFFFF; 24 25 /** 26 * 生成二维码图片 27 * @param content 28 * @param width 29 * @param height 30 * @param hints 31 * @return 32 * @throws Exception 33 */ 34 35 private static BufferedImage getQrCodeImage(String content, int width, int height, Hashtable hints) throws Exception 36 { 37 // 使用zxing生成二维码图片数据类BitMatrix 38 QRCodeWriter writer = new QRCodeWriter(); 39 40 if (hints == null) 41 { 42 hints = new Hashtable(); 43 hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); 44 } 45 //编码信息,生成二维码 46 BitMatrix matrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints); 47 48 // 修改默认生成的二维码白边 49 BitMatrix newMatrix = updateFrameWidth(matrix, 0); 50 51 // 缩放图片(因为裁剪了空白的边框) 52 BufferedImage bi = toBufferedImage(newMatrix); 53 54 // 计算x轴y轴缩放比例 55 double sx = (double)width / bi.getWidth(); 56 double sy = (double)height / bi.getHeight(); 57 58 BufferedImage zoomImage = zoomInImage(bi, sx, sy); 59 60 return zoomImage; 61 } 62 63 /** 64 * 将google zxing生成的二维码数据结构BitMatrix的内容写入图片缓冲区BufferedImage 65 * @param matrix 66 * @return 67 */ 68 69 public static BufferedImage toBufferedImage(BitMatrix matrix) 70 { 71 72 int width = matrix.getWidth(); 73 int height = matrix.getHeight(); 74 75 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 76 77 for (int x = 0; x < width; x++) 78 { 79 for (int y = 0; y < height; y++) 80 { 81 image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); 82 } 83 } 84 85 return image; 86 } 87 88 /** 89 * 90 * 获取二维码字节流 91 * @param content 92 * @param width 93 * @param height 94 * @return 95 * @throws Exception 96 */ 97 98 public static byte[] getQrCodeImageBytes(String content, int width, int height, Hashtable hints) throws Exception 99 { 100 101 // 二维码输出质量,0:L(低), 1:M(中等), 2:Q, 3:H(高) 102 int level = 3; 103 104 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.forBits(3)); 105 hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); 106 107 // 生成二维码图片 108 BufferedImage zoomImage = getQrCodeImage(content, width, height, hints); 109 110 // 转为二进制字节 111 ByteArrayOutputStream out = new ByteArrayOutputStream(); 112 113 if (!ImageIO.write(zoomImage, "png", out)) 114 { 115 throw new IOException("Could not write an image of format png"); 116 } 117 118 byte[] binaryData = out.toByteArray(); 119 120 return binaryData; 121 } 122 123 /** 124 * 进行Base64编码 125 * @param content 126 * @param width 127 * @param height 128 * @param hints 129 * @return 130 * @throws Exception 131 */ 132 133 public static String getQrCodeImageBase64String(String content, int width, int height, Hashtable hints) throws Exception 134 { 135 // 生成二维码图片的二进制字节 136 byte[] binaryData = getQrCodeImageBytes(content, width, height, hints); 137 138 // 将二进制字节进行Base64编码 139 String ret = new String(Base64.encodeBase64(binaryData), "UTF-8"); 140 141 return ret; 142 } 143 144 /** 145 * 指定缩放比例,进行图片缩放 146 * @param originalImage 147 * @param sx 148 * @param sy 149 * @return 150 */ 151 public static BufferedImage zoomInImage(BufferedImage originalImage, double sx, double sy) 152 { 153 AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(sx, sy), null); 154 BufferedImage newImage = op.filter(originalImage, null); 155 156 return newImage; 157 } 158 159 /** 160 * 自定义修改二维码的白边宽度 161 * @param matrix 162 * @param margin 163 * @return 164 */ 165 public static BitMatrix updateFrameWidth(BitMatrix matrix, int margin) 166 { 167 int tempM = margin * 2; 168 169 // 二维码的实际尺寸 170 int[] whitesTopLeft = getFrameWidthOfTopLeft(matrix); 171 int[] whitesBottomRight = getFrameWidthOfBottomRight(matrix); 172 173 int whiteWidth = whitesTopLeft[0] + whitesBottomRight[0]; 174 int whiteHeight = whitesTopLeft[1] + whitesBottomRight[1]; 175 176 int height = matrix.getHeight() - whiteWidth + tempM; 177 int width = matrix.getWidth() - whiteHeight + tempM; 178 179 // 按照自定义边框生成新的BitMatrix 180 BitMatrix resMatrix = new BitMatrix(width, height); 181 resMatrix.clear(); 182 183 // 循环,将二维码图案绘制到新的bitMatrix中 184 for (int i = margin; i < width - margin; i++) 185 { 186 for (int j = margin; j < height - margin; j++) 187 { 188 if (matrix.get(i - margin + whitesTopLeft[0], j - margin + whitesTopLeft[1])) 189 { 190 // 新的二维码 191 resMatrix.set(i, j); 192 } 193 } 194 } 195 196 return resMatrix; 197 } 198 199 /** 200 * 二维码左上角白边的尺寸 201 * @param matrix 202 * @return 203 */ 204 private static int[] getFrameWidthOfTopLeft(BitMatrix matrix) 205 { 206 // 二维码的尺寸 207 int height = matrix.getHeight(); 208 int width = matrix.getWidth(); 209 210 // 循环,遇到第一个黑点,就返回 211 for (int i = 0; i < width; i++) 212 { 213 for (int j = 0; j < height; j++) 214 { 215 if (matrix.get(i, j) == true) 216 { 217 int[] ret = {i, j}; 218 return ret; 219 } 220 } 221 } 222 223 int[] ret = {0, 0}; 224 return ret; 225 } 226 227 /** 228 * 二维码右下角白边的尺寸 229 * @param matrix 230 * @return 231 */ 232 private static int[] getFrameWidthOfBottomRight(BitMatrix matrix) 233 { 234 // 二维码的尺寸 235 int height = matrix.getHeight(); 236 int width = matrix.getWidth(); 237 238 // 备注:不能直接查找右下角的第一个黑点,而必须分别查找右上角、左下角的第一个黑点,然后返回右下角坐标 239 int right = -1; 240 241 // 从右上角开始循环,遇到第一个黑点,就得到右边空白宽度 242 for (int i = width; i > 0; i--) 243 { 244 for (int j = 0; j < height; j++) 245 { 246 if (matrix.get(i - 1, j) == true) 247 { 248 right = width - i; 249 break; 250 } 251 } 252 253 if (right >= 0) 254 { 255 break; 256 } 257 } 258 259 // 从左下角开始循环,遇到第一个黑点,就得到下边空白宽度,返回 260 for (int i = 0; i < width; i++) 261 { 262 for (int j = height; j > 0; j--) 263 { 264 if (matrix.get(i, j - 1) == true) 265 { 266 int[] ret = {right, height - j}; 267 return ret; 268 } 269 } 270 } 271 272 int[] ret = {0, 0}; 273 return ret; 274 } 275 276 }