关于java生成二维码(可内嵌logo)


首先上工具类(其实不是所有方法全用到):

  1  2 import java.awt.BasicStroke;
  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.IOException;    
 11 import java.util.HashMap;    
 12 import java.util.Hashtable;
 13 import java.util.Map;    
 14     
 15 import javax.imageio.ImageIO;    
 16     
 17 import com.google.zxing.BarcodeFormat;    
 18 import com.google.zxing.BinaryBitmap;    
 19 import com.google.zxing.DecodeHintType;    
 20 import com.google.zxing.EncodeHintType;    
 21 import com.google.zxing.MultiFormatReader;    
 22 import com.google.zxing.MultiFormatWriter;    
 23 import com.google.zxing.NotFoundException;    
 24 import com.google.zxing.Result;    
 25 import com.google.zxing.client.j2se.BufferedImageLuminanceSource;    
 26 import com.google.zxing.client.j2se.MatrixToImageConfig;    
 27 import com.google.zxing.client.j2se.MatrixToImageWriter;    
 28 import com.google.zxing.common.BitMatrix;    
 29 import com.google.zxing.common.HybridBinarizer;    
 30 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 
 31 public class ZxingUtil {    
 32     private ZxingUtil(){}    
 33     private static final String CHARSET = "utf-8";  
 34     private static final String FORMAT_NAME = "JPG";  
 35     // 二维码尺寸  
 36     private static final int QRCODE_SIZE = 300;  
 37     // LOGO宽度  
 38     private static final int WIDTH = 60;  
 39     // LOGO高度  
 40     private static final int HEIGHT = 60;  
 41     /**  
 42      * 为二维码图片增加logo头像  
 43      * @see 其原理类似于图片加水印  
 44      * @param imagePath 二维码图片存放路径(含文件名)  
 45      * @param logoPath  logo头像存放路径(含文件名)  
 46      */    
 47     private static void overlapImage(String imagePath, String logoPath) throws IOException {    
 48         BufferedImage image = ImageIO.read(new File(imagePath));    
 49         int logoWidth = image.getWidth()/5;   //设置logo图片宽度为二维码图片的五分之一    
 50         int logoHeight = image.getHeight()/5; //设置logo图片高度为二维码图片的五分之一    
 51         int logoX = (image.getWidth()-logoWidth)/2;   //设置logo图片的位置,这里令其居中    
 52         int logoY = (image.getHeight()-logoHeight)/2; //设置logo图片的位置,这里令其居中    
 53         Graphics2D graphics = image.createGraphics();    
 54         graphics.drawImage(ImageIO.read(new File(logoPath)), logoX, logoY, logoWidth, logoHeight, null);    
 55         graphics.dispose();    
 56         ImageIO.write(image, imagePath.substring(imagePath.lastIndexOf(".") + 1), new File(imagePath));    
 57     }    
 58     
 59         
 60     /**  
 61      * 生成二维码  
 62      * @param content   二维码内容  
 63      * @param charset   编码二维码内容时采用的字符集(传null时默认采用UTF-8编码)  
 64      * @param imagePath 二维码图片存放路径(含文件名)  
 65      * @param width     生成的二维码图片宽度  
 66      * @param height    生成的二维码图片高度  
 67      * @param logoPath  logo头像存放路径(含文件名,若不加logo则传null即可)  
 68      * @return 生成二维码结果(true or false)  
 69      */    
 70     public static boolean encodeQRCodeImage(String content, String charset, String imagePath, int width, int height, String logoPath) {    
 71         Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();    
 72         //指定编码格式    
 73         //hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");    
 74         //指定纠错级别(L--7%,M--15%,Q--25%,H--30%)    
 75         hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);    
 76         //编码内容,编码类型(这里指定为二维码),生成图片宽度,生成图片高度,设置参数    
 77         BitMatrix bitMatrix = null;    
 78         try {    
 79             bitMatrix = new MultiFormatWriter().encode(new String(content.getBytes(charset==null?"UTF-8":charset), "ISO-8859-1"), BarcodeFormat.QR_CODE, width, height, hints);    
 80         } catch (Exception e) {    
 81             System.out.println("编码待生成二维码图片的文本时发生异常,堆栈轨迹如下");    
 82             e.printStackTrace();    
 83             return false;    
 84         }    
 85         //生成的二维码图片默认背景为白色,前景为黑色,但是在加入logo图像后会导致logo也变为黑白色,至于是什么原因还没有仔细去读它的源码    
 86         //所以这里对其第一个参数黑色将ZXing默认的前景色0xFF000000稍微改了一下0xFF000001,最终效果也是白色背景黑色前景的二维码,且logo颜色保持原有不变    
 87         MatrixToImageConfig config = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);    
 88         //这里要显式指定MatrixToImageConfig,否则还会按照默认处理将logo图像也变为黑白色(如果打算加logo的话,反之则不须传MatrixToImageConfig参数)    
 89         try {    
 90             MatrixToImageWriter.writeToFile(bitMatrix, imagePath.substring(imagePath.lastIndexOf(".") + 1), new File(imagePath), config);    
 91         } catch (IOException e) {    
 92             System.out.println("生成二维码图片[" + imagePath + "]时遇到异常,堆栈轨迹如下");    
 93             e.printStackTrace();    
 94             return false;    
 95         }    
 96         //此时二维码图片已经生成了,只不过没有logo头像,所以接下来根据传入的logoPath参数来决定是否加logo头像    
 97         if(null == logoPath){    
 98             return true;    
 99         }else{    
100             //如果此时最终生成的二维码不是我们想要的,那么可以扩展MatrixToImageConfig类(反正ZXing提供了源码)    
101             //扩展时可以重写其writeToFile方法,令其返回toBufferedImage()方法所生成的BufferedImage对象(尽管这种做法未必能解决为题,故需根据实际情景测试)    
102             //然后替换这里overlapImage()里面的第一行BufferedImage image = ImageIO.read(new File(imagePath));    
103             //即private static void overlapImage(BufferedImage image, String imagePath, String logoPath)    
104             try {    
105                 //这里不需要判断logoPath是否指向了一个具体的文件,因为这种情景下overlapImage会抛IO异常    
106                 overlapImage(imagePath, logoPath);    
107                 return true;    
108             } catch (IOException e) {    
109                 System.out.println("为二维码图片[" + imagePath + "]添加logo头像[" + logoPath + "]时遇到异常,堆栈轨迹如下");    
110                 e.printStackTrace();    
111                 return false;    
112             }    
113         }    
114     }    
115         
116         
117     /**  
118      * 解析二维码  
119      * @param imagePath 二维码图片存放路径(含文件名)  
120      * @param charset   解码二维码内容时采用的字符集(传null时默认采用UTF-8编码)  
121      * @return 解析成功后返回二维码文本,否则返回空字符串  
122      */    
123     public static String decodeQRCodeImage(String imagePath, String charset) {    
124         BufferedImage image = null;    
125         try {    
126             image = ImageIO.read(new File(imagePath));    
127         } catch (IOException e) {    
128             e.printStackTrace();    
129             return "";    
130         }    
131         if(null == image){    
132             System.out.println("Could not decode QRCodeImage");    
133             return "";    
134         }    
135         BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image)));    
136         Map<DecodeHintType, String> hints = new HashMap<DecodeHintType, String>();    
137         hints.put(DecodeHintType.CHARACTER_SET, charset==null ? "UTF-8" : charset);    
138         Result result = null;    
139         try {    
140             result = new MultiFormatReader().decode(bitmap, hints);    
141             return result.getText();    
142         } catch (NotFoundException e) {    
143             System.out.println("二维码图片[" + imagePath + "]解析失败,堆栈轨迹如下");    
144             e.printStackTrace();    
145             return "";    
146         }    
147     }    
148     static BufferedImage createImage(String content, String imgPath,  
149             boolean needCompress) throws Exception {  
150         Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();  
151         hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);  
152         hints.put(EncodeHintType.CHARACTER_SET, CHARSET);  
153         // hints.put(EncodeHintType.MARGIN, 1);  
154         BitMatrix bitMatrix = new MultiFormatWriter().encode(content,  
155                 BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);  
156         int width = bitMatrix.getWidth();  
157         int height = bitMatrix.getHeight();  
158         BufferedImage image = new BufferedImage(width, height,  
159                 BufferedImage.TYPE_INT_RGB);  
160         for (int x = 0; x < width; x++) {  
161             for (int y = 0; y < height; y++) {  
162                 image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000  
163                         : 0xFFFFFFFF);  
164             }  
165         }  
166         if (imgPath == null || "".equals(imgPath)) {  
167             return image;  
168         }  
169         // 插入图片  
170         ZxingUtil.insertImage(image, imgPath, needCompress);  
171         return image;  
172     }
173 
174 
175     /** 
176      * 插入LOGO 
177      *  
178      * @param source 
179      *            二维码图片 
180      * @param imgPath 
181      *            LOGO图片地址 
182      * @param needCompress 
183      *            是否压缩 
184      * @throws Exception 
185      */  
186     private static void insertImage(BufferedImage source, String imgPath,  
187             boolean needCompress) throws Exception {  
188         File file = new File(imgPath);  
189         if (!file.exists()) {  
190             System.err.println("" + imgPath + "   该文件不存在!");  
191             return;  
192         }  
193         Image src = ImageIO.read(new File(imgPath));  
194         int width = src.getWidth(null);  
195         int height = src.getHeight(null);  
196         if (needCompress) { // 压缩LOGO  
197             if (width > WIDTH) {  
198                 width = WIDTH;  
199             }  
200             if (height > HEIGHT) {  
201                 height = HEIGHT;  
202             }  
203             Image image = src.getScaledInstance(width, height,  
204                     Image.SCALE_SMOOTH);  
205             BufferedImage tag = new BufferedImage(width, height,  
206                     BufferedImage.TYPE_INT_RGB);  
207             Graphics g = tag.getGraphics();  
208             g.drawImage(image, 0, 0, null); // 绘制缩小后的图  
209             g.dispose();  
210             src = image;  
211         }  
212         // 插入LOGO  
213         Graphics2D graph = source.createGraphics();  
214         int x = (QRCODE_SIZE - width) / 2;  
215         int y = (QRCODE_SIZE - height) / 2;  
216         graph.drawImage(src, x, y, width, height, null);  
217         Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);  
218         graph.setStroke(new BasicStroke(3f));  
219         graph.draw(shape);  
220         graph.dispose();  
221     }
222 }    

而后调用实现:

 1 import java.awt.Color;
 2 import java.awt.Font;
 3 import java.awt.Graphics;
 4 import java.awt.Image;
 5 import java.awt.image.BufferedImage;
 6 import java.io.File;
 7 import java.io.FileOutputStream;
 8 
 9 import javax.imageio.ImageIO;
10 
11 
12 import org.junit.Test;
13 
14 import com.sun.image.codec.jpeg.JPEGCodec;
15 import com.sun.image.codec.jpeg.JPEGImageEncoder;
16 
17 
18 public class generatePicture {
19 
20     @Test
21     public void test() {
22         String ewm = "http://t.cn/RSFurq5";//压缩后的地址,即二维码地址
23         //头像地址
24         String logo = "F:\\办公\\关于项目\\头像\\朱胜男.jpg";
25         File logoFile =new File(logo);//头像
26 //         File bgFile =new File("c:\\qr_code.jpg");
27         //背景图地址
28          File bgFile =new File("F:\\办公\\关于项目\\qr_code.jpg");
29          //生成后的二维码存放地址
30          String outputPath = "F:/办公/关于项目/test/test.png";
31         
32         try {
33            BufferedImage biQR = ZxingUtil.createImage(ewm, logo, true);    //输出二维码到缓冲区
34            //BufferedImage biQR2 = ZxingUtil.encode(ewm, logo, outputPath, true);
35            Image bgSrc = ImageIO.read(bgFile);
36            Image logoSrc = ImageIO.read(logoFile);
37            int width = bgSrc.getWidth(null);
38            int height = bgSrc.getHeight(null);
39            BufferedImage image = new BufferedImage(width, height,
40                    BufferedImage.TYPE_INT_RGB);
41            Graphics g = image.createGraphics();
42            g.drawImage(bgSrc, 0, 0, width, height, null);                                            // 绘制背景图
43            //g.drawImage(logoSrc, 277, 283, 162,162, null);    // 绘制微信头像logo
44            //参数分别为image,x,y, width, height,  x表示离背景图左边框距离,y表示离下边框距离,w和h表示二维码大小,大致是这样
45            g.drawImage(biQR, 90, 260, 540, 540, null);// 绘制二维码
46            g.setColor(Color.BLACK);
47            Font f = new Font("宋体",Font.BOLD,45);//bold表示粗体,后面45是字体大小
48            Color mycolor = new Color(136, 135, 135);//new Color(0, 0, 255);
49            g.setColor(mycolor);  
50            g.setFont(f);  
51            g.drawString("共享专车",260,840);
52 //           g.drawString(("我是"+xm),360,210);
53 //           g.drawString("我为元翔专车代言",360,260);
54            g.dispose();
55            
56            FileOutputStream out = new FileOutputStream(outputPath);
57            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
58            encoder.encode(image);
59            out.close();
60         } catch (Exception e) {
61             e.printStackTrace();
62         }
63     }
64     
65 }

以上是个人整理之后的,参考链接:http://blog.csdn.net/mmm333zzz/article/details/17259513


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM