二维码生成工具类
1 package com.qbskj.project.util; 2 3 import java.awt.Graphics2D; 4 import java.awt.geom.AffineTransform; 5 import java.awt.image.BufferedImage; 6 import java.io.File; 7 import java.io.IOException; 8 import java.io.OutputStream; 9 import java.util.HashMap; 10 import java.util.Hashtable; 11 import java.util.Map; 12 13 import javax.imageio.ImageIO; 14 import javax.servlet.http.HttpServletResponse; 15 16 import org.slf4j.Logger; 17 import org.slf4j.LoggerFactory; 18 19 import com.google.zxing.BarcodeFormat; 20 import com.google.zxing.Binarizer; 21 import com.google.zxing.BinaryBitmap; 22 import com.google.zxing.DecodeHintType; 23 import com.google.zxing.EncodeHintType; 24 import com.google.zxing.LuminanceSource; 25 import com.google.zxing.MultiFormatReader; 26 import com.google.zxing.MultiFormatWriter; 27 import com.google.zxing.Result; 28 import com.google.zxing.common.BitMatrix; 29 import com.google.zxing.common.HybridBinarizer; 30 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 31 32 /** 33 * <p>Title:QRCodeUtil </p> 34 * <p>Description: 二维码生成工具类</p> 35 * @author Administrator 36 * @version 37 * @since 38 */ 39 public final class QRCodeUtil extends LuminanceSource { 40 41 private static final Logger logger = LoggerFactory.getLogger(QRCodeUtil.class); 42 43 // 二维码颜色 44 private static final int BLACK = 0xFF000000; 45 // 二维码颜色 46 private static final int WHITE = 0xFFFFFFFF; 47 48 49 private final BufferedImage image; 50 private final int left; 51 private final int top; 52 53 public QRCodeUtil(BufferedImage image) { 54 this(image, 0, 0, image.getWidth(), image.getHeight()); 55 } 56 57 public QRCodeUtil(BufferedImage image, int left, int top, int width, int height) { 58 super(width, height); 59 int sourceWidth = image.getWidth(); 60 int sourceHeight = image.getHeight(); 61 if (left + width > sourceWidth || top + height > sourceHeight) { 62 throw new IllegalArgumentException("Crop rectangle does not fit within image data."); 63 } 64 for (int y = top; y < top + height; y++) { 65 for (int x = left; x < left + width; x++) { 66 if ((image.getRGB(x, y) & 0xFF000000) == 0) { 67 image.setRGB(x, y, 0xFFFFFFFF); // = white 68 } 69 } 70 } 71 this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY); 72 this.image.getGraphics().drawImage(image, 0, 0, null); 73 this.left = left; 74 this.top = top; 75 } 76 77 @Override 78 public byte[] getRow(int y, byte[] row) { 79 if (y < 0 || y >= getHeight()) { 80 throw new IllegalArgumentException("Requested row is outside the image: " + y); 81 } 82 int width = getWidth(); 83 if (row == null || row.length < width) { 84 row = new byte[width]; 85 } 86 image.getRaster().getDataElements(left, top + y, width, 1, row); 87 return row; 88 } 89 90 @Override 91 public byte[] getMatrix() { 92 int width = getWidth(); 93 int height = getHeight(); 94 int area = width * height; 95 byte[] matrix = new byte[area]; 96 image.getRaster().getDataElements(left, top, width, height, matrix); 97 return matrix; 98 } 99 100 @Override 101 public boolean isCropSupported() { 102 return true; 103 } 104 105 @Override 106 public LuminanceSource crop(int left, int top, int width, int height) { 107 return new QRCodeUtil(image, this.left + left, this.top + top, width, height); 108 } 109 110 @Override 111 public boolean isRotateSupported() { 112 return true; 113 } 114 115 @Override 116 public LuminanceSource rotateCounterClockwise() { 117 int sourceWidth = image.getWidth(); 118 int sourceHeight = image.getHeight(); 119 AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth); 120 BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY); 121 Graphics2D g = rotatedImage.createGraphics(); 122 g.drawImage(image, transform, null); 123 g.dispose(); 124 int width = getWidth(); 125 return new QRCodeUtil(rotatedImage, top, sourceWidth - (left + width), getHeight(), width); 126 } 127 128 /** 129 * @param matrix 130 * @return 131 */ 132 private static BufferedImage toBufferedImage(BitMatrix matrix) { 133 int width = matrix.getWidth(); 134 int height = matrix.getHeight(); 135 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 136 for (int x = 0; x < width; x++) { 137 for (int y = 0; y < height; y++) { 138 image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); 139 } 140 } 141 return image; 142 } 143 144 /** 145 * 生成二维码图片 146 * 147 * @param matrix 148 * @param format 149 * @param file 150 * @throws IOException 151 */ 152 public static void writeToFile(BitMatrix matrix, String format, File file) throws IOException { 153 BufferedImage image = toBufferedImage(matrix); 154 if (!ImageIO.write(image, format, file)) { 155 throw new IOException("Could not write an image of format " + format + " to " + file); 156 } 157 } 158 159 /** 160 * 生成二维码图片流 161 * 162 * @param matrix 163 * @param format 164 * @param stream 165 * @throws IOException 166 */ 167 public static void writeToStream(BitMatrix matrix, String format, OutputStream stream) throws IOException { 168 BufferedImage image = toBufferedImage(matrix); 169 if (!ImageIO.write(image, format, stream)) { 170 throw new IOException("Could not write an image of format " + format); 171 } 172 } 173 174 /** 175 * 根据内容,生成指定宽高、指定格式的二维码图片 176 * 177 * @param text 内容 178 * @param width 宽 179 * @param height 高 180 * @param format 图片格式 181 * @return 生成的二维码图片路径 182 * @throws Exception 183 */ 184 public static String generateQRCode(String text, int width, int height, String format, String pathName) 185 throws Exception { 186 Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>(); 187 hints.put(EncodeHintType.CHARACTER_SET, "utf-8");// 指定编码格式 188 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);// 指定纠错等级 189 hints.put(EncodeHintType.MARGIN, 1); // 白边大小,取值范围0~4 190 BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints); 191 File outputFile = new File(pathName); 192 writeToFile(bitMatrix, format, outputFile); 193 return pathName; 194 } 195 196 /** 197 * 输出二维码图片流 198 * 199 * @param text 二维码内容 200 * @param width 二维码宽 201 * @param height 二维码高 202 * @param format 图片格式eg: png, jpg, gif 203 * @param response HttpServletResponse 204 * @throws Exception 205 */ 206 public static void generateQRCode(String text, int width, int height, String format, HttpServletResponse response) 207 throws Exception { 208 Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>(); 209 hints.put(EncodeHintType.CHARACTER_SET, "utf-8");// 指定编码格式 210 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);// 指定纠错等级 211 hints.put(EncodeHintType.MARGIN, 1); // 白边大小,取值范围0~4 212 BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints); 213 writeToStream(bitMatrix, format, response.getOutputStream()); 214 } 215 216 /** 217 * 解析指定路径下的二维码图片 218 * 219 * @param filePath 二维码图片路径 220 * @return 221 */ 222 public static String parseQRCode(String filePath) { 223 String content = ""; 224 try { 225 File file = new File(filePath); 226 BufferedImage image = ImageIO.read(file); 227 LuminanceSource source = new QRCodeUtil(image); 228 Binarizer binarizer = new HybridBinarizer(source); 229 BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer); 230 Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>(); 231 hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); 232 MultiFormatReader formatReader = new MultiFormatReader(); 233 Result result = formatReader.decode(binaryBitmap, hints); 234 235 logger.info("result 为:" + result.toString()); 236 logger.info("resultFormat 为:" + result.getBarcodeFormat()); 237 logger.info("resultText 为:" + result.getText()); 238 // 设置返回值 239 content = result.getText(); 240 } catch (Exception e) { 241 logger.error(e.getMessage()); 242 } 243 return content; 244 } 245 246 public static void main(String[] args) { 247 String text = "Very Good!"; // 随机生成验证码 248 System.out.println("随机码: " + text); 249 int width = 150; // 二维码图片的宽 250 int height = 150; // 二维码图片的高 251 String format = "png"; // 二维码图片的格式 252 String path = "D:/pic.png";//图片保存地址 253 254 try { 255 // 生成二维码图片,并返回图片路径 256 String pathName = generateQRCode(text, width, height, format, path); 257 System.out.println("生成二维码的图片路径: " + pathName); 258 259 String content = parseQRCode(pathName); 260 System.out.println("解析出二维码的图片的内容为: " + content); 261 } catch (Exception e) { 262 e.printStackTrace(); 263 } 264 } 265 266 }
成功不是终点,失败也并非末日,重要的是前行的勇气!