使用google zxing生成二维码图片

生成二维码工具类:

  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 }