zoukankan      html  css  js  c++  java
  • 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 }

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

  • 相关阅读:
    第六周
    第五周
    第四周
    第二周学习记录
    实验一 Linux初步认识
    java实验四
    java实验三
    为什么无密码认证能够有效
    关于父元素,子元素,同级元素的DOM操作技巧
    高效设计构建软件的十三条建议
  • 原文地址:https://www.cnblogs.com/rick168/p/5679830.html
Copyright © 2011-2022 走看看