Java生成带小图标的二维码-google zxing 工具类

  近期一直忙于开发微信商城项目,应客户要求,要开发个有图标的二维码。经过两次改版,终于实现了该功能(第一次没有小图标,这次才整合好的),如下是完整代码 。

  该代码使用Java7开发,另外使用 core-2.2.jar jar[http://pan.baidu.com/s/1skTwHQ1] 包 。

  1 package com.rick.common.utils;
  2 
  3 
  4 import java.awt.Color;
  5 import java.awt.Graphics2D;
  6 import java.awt.Image;
  7 import java.awt.geom.AffineTransform;
  8 import java.awt.image.AffineTransformOp;
  9 import java.awt.image.BufferedImage;
 10 import java.io.File;
 11 import java.io.IOException;
 12 import java.util.Date;
 13 import java.util.HashMap;
 14 import java.util.Map;
 15 
 16 import javax.imageio.ImageIO;
 17 
 18 import com.google.zxing.BarcodeFormat;
 19 import com.google.zxing.EncodeHintType;
 20 import com.google.zxing.MultiFormatWriter;
 21 import com.google.zxing.WriterException;
 22 import com.google.zxing.common.BitMatrix;
 23 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 24 
 25 /**
 26  * 二维码生成工具类【带小图标】
 27  * <br> QRCodeUtils 类的提升版本
 28  * @author bxw
 29  * @time 2016-07-17 22:13:45
 30  * @version v1.1
 31  */
 32 public class BarcodeFactory {
 33     
 34     /**
 35      * 图片格式定义
 36      * @value Array
 37      */
 38     private static String[] IMAGE_TYPE = {"BMP", "bmp", "jpg", "JPG", "wbmp", "jpeg", "png", "PNG", "JPEG", "WBMP", "GIF", "gif","ICON","icon"};
 39     
 40     /**
 41      * 二维码宽度
 42      */
 43     public static final int WIDTH = 260;
 44     
 45     /**
 46      * 二维码高度
 47      */
 48     public static final int HEIGHT = 260;
 49         
 50     /**
 51      * 图标宽度
 52      */
 53     private static final int IMAGE_WIDTH = 68;
 54     /**
 55      * 图标高度
 56      */
 57     private static final int IMAGE_HEIGHT = 68;
 58     /**
 59      * 底图大小【正方形】
 60      */
 61     private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2;
 62     /**
 63      * 底图边框
 64      */
 65     private static final int FRAME_WIDTH = 5;
 66 
 67     /**
 68      * 二维码写码器
 69      */
 70     private static MultiFormatWriter mutiWriter = new MultiFormatWriter();
 71 
 72     /**
 73      * 二维码生成-方法入口
 74      * @param content 内容
 75      * @param width 宽度
 76      * @param height 高度
 77      * @param iconImagePath 图标原路径
 78      * @param qrcodeImagePath 二维码存放路径
 79      * @param hasFiller 
 80      *             比例不对时是否需要补白:true为补白; false为不补白
 81      * @return 
 82      *         成功:返回输出图片绝对路径;失败:返回null
 83      */
 84     public static String encode(String content, int width, int height,
 85             String iconImagePath, String qrcodeImagePath,boolean hasFiller) {
 86         try {
 87             /**
 88              * 图标格式校验
 89              */
 90             File icon = new File(iconImagePath);
 91             if(!icon.exists()){
 92                 System.err.println("系统找不到图标所在文件 !");
 93                 return null;
 94             }
 95             String iconFileName = icon.getName();
 96             // 得到上传文件的扩展名
 97             String fileExtName = iconFileName.substring(iconFileName.lastIndexOf(".") + 1);
 98             if(!checkIMGType(fileExtName)){
 99                 System.err.println("图标格式有误 !");
100                 return null;
101             }
102             
103             if(width<260||height<260){
104                 width = BarcodeFactory.WIDTH;
105                 height = BarcodeFactory.HEIGHT;
106             }
107             ImageIO.write(genBarcode(content, width, height, iconImagePath,hasFiller),
108                     "png", new File(qrcodeImagePath));
109             System.err.println("二维码已生成  "+qrcodeImagePath);
110             return qrcodeImagePath;
111         } catch (IOException e) {
112             System.err.println("图片读取异常 : "+e.getMessage());
113         } catch (WriterException e) {
114             System.err.println("图片输出异常 :"+e.getMessage());
115         }
116         return null;
117     }
118 
119     /**
120      * 图片处理方法
121      * @param content
122      * @param width
123      * @param height
124      * @param iconImagePath
125      * @param hasFiller 
126      *             比例不对时是否需要补白:true为补白; false为不补白;
127      * @return
128      * @throws WriterException
129      * @throws IOException
130      */
131     private static BufferedImage genBarcode(String content, int width,
132             int height, String iconImagePath,boolean hasFiller) throws WriterException,
133             IOException {
134         // 读取源图像
135         BufferedImage scaleImage = scale(iconImagePath, IMAGE_WIDTH,
136                 IMAGE_HEIGHT, hasFiller);
137         int[][] srcPixels = new int[IMAGE_WIDTH][IMAGE_HEIGHT];
138         for (int i = 0; i < scaleImage.getWidth(); i++) {
139             for (int j = 0; j < scaleImage.getHeight(); j++) {
140                 srcPixels[i][j] = scaleImage.getRGB(i, j);
141             }
142         }
143 
144         Map<EncodeHintType, Object> hint = new HashMap<EncodeHintType, Object>();
145         hint.put(EncodeHintType.CHARACTER_SET, "utf-8");
146         hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
147         // 生成二维码
148         BitMatrix matrix = mutiWriter.encode(content, BarcodeFormat.QR_CODE,
149                 width, height, hint);
150 
151         // 二维矩阵转为一维像素数组
152         int halfW = matrix.getWidth() / 2;
153         int halfH = matrix.getHeight() / 2;
154         int[] pixels = new int[width * height];
155 
156         for (int y = 0; y < matrix.getHeight(); y++) {
157             for (int x = 0; x < matrix.getWidth(); x++) {
158                 // 读取图片
159                 if (x > halfW - IMAGE_HALF_WIDTH
160                         && x < halfW + IMAGE_HALF_WIDTH
161                         && y > halfH - IMAGE_HALF_WIDTH
162                         && y < halfH + IMAGE_HALF_WIDTH) {
163                     pixels[y * width + x] = srcPixels[x - halfW
164                             + IMAGE_HALF_WIDTH][y - halfH + IMAGE_HALF_WIDTH];
165                 } 
166                 // 在图片四周形成边框
167                 else if ((x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH
168                         && x < halfW - IMAGE_HALF_WIDTH + FRAME_WIDTH
169                         && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH
170                         + IMAGE_HALF_WIDTH + FRAME_WIDTH)
171                         || (x > halfW + IMAGE_HALF_WIDTH - FRAME_WIDTH
172                                 && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
173                                 && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH
174                                 + IMAGE_HALF_WIDTH + FRAME_WIDTH)
175                         || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH
176                                 && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
177                                 && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH
178                                 - IMAGE_HALF_WIDTH + FRAME_WIDTH)
179                         || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH
180                                 && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
181                                 && y > halfH + IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH
182                                 + IMAGE_HALF_WIDTH + FRAME_WIDTH)) {
183                     pixels[y * width + x] = 0xfffffff;
184                 } else {
185                     // 此处可以修改二维码的颜色,可以分别制定二维码和背景的颜色;
186                     pixels[y * width + x] = matrix.get(x, y) ? 0xff000000
187                             : 0xfffffff;
188                 }
189             }
190         }
191 
192         BufferedImage image = new BufferedImage(width, height,
193                 BufferedImage.TYPE_INT_RGB);
194         image.getRaster().setDataElements(0, 0, width, height, pixels);
195         
196         return image;
197     }
198 
199     /**
200      * 把传入的原始图像按高度和宽度进行缩放,生成符合要求的图标
201      * 
202      * @param iconImagePath
203      *            小图标源文件地址
204      * @param height
205      *            目标高度
206      * @param width
207      *            目标宽度
208      * @param hasFiller
209      *            比例不对时是否需要补白:true为补白; false为不补白;
210      * @throws IOException
211      */
212     private static BufferedImage scale(String iconImagePath, int height,
213             int width, boolean hasFiller) throws IOException {
214         double ratio = 0.0; // 缩放比例
215         File file = new File(iconImagePath);
216         BufferedImage srcImage = ImageIO.read(file);
217         Image destImage = srcImage.getScaledInstance(width, height,
218                 BufferedImage.SCALE_SMOOTH);
219         // 计算比例
220         if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {
221             if (srcImage.getHeight() > srcImage.getWidth()) {
222                 ratio = (new Integer(height)).doubleValue()
223                         / srcImage.getHeight();
224             } else {
225                 ratio = (new Integer(width)).doubleValue()
226                         / srcImage.getWidth();
227             }
228             AffineTransformOp op = new AffineTransformOp(
229                     AffineTransform.getScaleInstance(ratio, ratio), null);
230             destImage = op.filter(srcImage, null);
231         }
232         if (hasFiller) {// 补白
233             BufferedImage image = new BufferedImage(width, height,
234                     BufferedImage.TYPE_INT_RGB);
235             Graphics2D graphic = image.createGraphics();
236             graphic.setColor(Color.white);
237             graphic.fillRect(0, 0, width, height);
238             if (width == destImage.getWidth(null))
239                 graphic.drawImage(destImage, 0,
240                         (height - destImage.getHeight(null)) / 2,
241                         destImage.getWidth(null), destImage.getHeight(null),
242                         Color.white, null);
243             else
244                 graphic.drawImage(destImage,
245                         (width - destImage.getWidth(null)) / 2, 0,
246                         destImage.getWidth(null), destImage.getHeight(null),
247                         Color.white, null);
248             graphic.dispose();
249             destImage = image;
250             System.err.println("INFO 图标补白已完成 ");
251         }
252         return (BufferedImage) destImage;
253     }
254 
255     /**
256      * 图片格式校验
257      * @param fileExtName
258      * @return
259      */
260     private static boolean checkIMGType(String fileExtName){
261         boolean flag = false;
262         for (String type : IMAGE_TYPE) {
263             //-- 图片格式正确
264             if(type.toLowerCase().equals(fileExtName.toLowerCase())){
265                 flag = true;
266                 break;
267             }
268         }
269         //------------图片格式校验结束
270         return flag;
271     }
272     
273     /**
274      * 测试主方法入口
275      * @param args
276      */
277     public static void main(String[] args) {
278         String codeIconPath = "C:/Users/rick/Desktop/1.jpg";
279         String codePath = "C:/Users/rick/Desktop/"+new Date().getTime()+".png";
280         
281         /**
282          * 测试方法入口
283          */
284         BarcodeFactory.encode("项目:晚餐定制",300, 300, codeIconPath, codePath,false);
285     }
286 }

  著名: 代码只作为学习用途,谢谢 !

原文地址:https://www.cnblogs.com/rick168/p/5679830.html