com.google.zxing生成的二维码自定义白边大小

com.google.zxing提供的定义白边大小试了好多次不起作用:        hints.put(EncodeHintType.MARGIN, 0);//设置白边宽度,取值0~4,


本人的解决思路是:

建好二维码后,再建一个比二维码大一点的空白图片,然后把二维码图片加到空白图片上,这样白边大小就可以自己控制了。




import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;


import javax.servlet.http.HttpServletRequest;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;


public class PayQrcodeUtil {
private static final Log log = LogFactory.getLog(PayQrcodeUtil.class);
    private static final int QRCOLOR = 0xFF000000;   //默认是黑色
    private static final int BGWHITE = 0xFFFFFFFF;   //背景颜色


    public static void main(String[] args)// throws WriterException  
    {    
/*     try {
   
    BufferedImage image = ImageIO.read(new File("D:\\work\\tmp\\0.png"));
    System.out.println(image);
    } catch (IOException e ) {e.printStackTrace();}*/
        try  
        {  


       
        //获取系统中可用的字体的名字  
           GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();  
           String[] fontName = e.getAvailableFontFamilyNames();  
           for(int i = 0; i            {  
               log.info("font:"+fontName[i]);  
           }  
//            getLogoQRCode("http://www.163.com/", null, "设备编号:NO.8888801",550,550);
        }  
        catch (Exception e)  
        {  
            e.printStackTrace();  
        }  
    }  


    /**
     * 生成带二维码的支付卡台图片
     * @param qrPic
     *  @param logoPic 
     */
    public static BufferedImage getQRCodeAndBaseImg(String qrUrl, String payNo, HttpServletRequest request, vvps vvps, int width, int height)
    {
        String content = qrUrl;
        try
        {
            PayQrcodeUtil zp = new PayQrcodeUtil();
            //先生成二维码
            BufferedImage bim = zp.getQR_CODEBufferedImage(content, BarcodeFormat.QR_CODE, width, height, zp.getDecodeHintType());
            //把二维码加到支付卡台图片上
            return zp.addQRCode_BaseImg(bim, request, new LogoConfig(), vvps, payNo);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }


/**
* 将二维码添加到支付卡台图片上
* @param bim 二维码
* @param vvps 信息
*/
    public BufferedImage addQRCode_BaseImg(BufferedImage bim, HttpServletRequest request, LogoConfig logoConfig, vvps vvps, String payNo)
    {
        try
        {
            /** 读取二维码图片,并构建绘图对象 */
            BufferedImage Qrcode = bim;
            Graphics2D QrcodeG = bim.createGraphics();


            /** * 读取LOGO图片 */
        String logoFilePath = request.getSession().getServletContext().getRealPath("/") + "image/yzglogo.jpg";
            FileInputStream logofis = new FileInputStream(new File(logoFilePath));
            BufferedImage logoImg = javax.imageio.ImageIO.read(logofis);


            if(logoImg != null){
             /** * 设置logo的大小,设置为二维码图片的20%,因为过大会盖掉二维码 */
                int widthLogo = logoImg.getWidth(null)>Qrcode.getWidth()*2/10?(Qrcode.getWidth()*2/10):logoImg.getWidth(null), 
                    heightLogo = logoImg.getHeight(null)>Qrcode.getHeight()*2/10?(Qrcode.getHeight()*2/10):logoImg.getWidth(null);


                /** * logo放在中心 */
                 int x = (Qrcode.getWidth() - widthLogo) / 2;
                 int y = (Qrcode.getHeight() - heightLogo) / 2;


                 //开始绘制图片
                 QrcodeG.drawImage(logoImg, x, y, widthLogo, heightLogo, null);
                 QrcodeG.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15);
                 QrcodeG.setStroke(new BasicStroke(logoConfig.getBorder()));
                 QrcodeG.setColor(logoConfig.getBorderColor());
                 QrcodeG.drawRect(x, y, widthLogo, heightLogo);
                 QrcodeG.dispose();
            }
            
            //给二维码图片加上白框
            int whiteMarginX = 15;
            int whiteMarginY = 15;
            int widthQrcode = Qrcode.getWidth();
            int heightQrcode = Qrcode.getWidth();
            //生成空白的图片
            BufferedImage qrcodeWhiteFrame = qrcodeAddFrame(Qrcode, whiteMarginX);
            //把二维码加到空白的图片上
            Graphics2D qrcodeFrameG = qrcodeWhiteFrame.createGraphics();
            qrcodeFrameG.drawImage(Qrcode, whiteMarginX, whiteMarginY, widthQrcode, heightQrcode, null);
            qrcodeFrameG.drawRoundRect(whiteMarginX, whiteMarginY, widthQrcode, heightQrcode, 15, 15);
            qrcodeFrameG.setStroke(new BasicStroke(logoConfig.getBorder()));
            qrcodeFrameG.setColor(logoConfig.getBorderColor());
            qrcodeFrameG.drawRect(whiteMarginX, whiteMarginY, widthQrcode, heightQrcode);
            qrcodeFrameG.dispose();
            
            
//          File file = new File("d:\\work\\tmp\\logo.jpg");
//          ImageIO.write(Qrcode, "jpg", file);


            /** * 读取支付卡台背景图片 */
        String baseFilePath = request.getSession().getServletContext().getRealPath("/") + "image/Base.jpg";
//         String baseFilePath = "D:\\work\\workspace\\src\\main\\webapp\\image\\Base.jpg";
        log.info(baseFilePath);
            FileInputStream fis = new FileInputStream(new File(baseFilePath));


            BufferedImage baseImg = javax.imageio.ImageIO.read(fis);//ImageIO.read(new File("D:\\Users\\WorkSpaces\\vpsOnlinePayService\\src\\main\\webapp\\images\\yzglogo.jpg"));


            if(baseImg!=null){
                /** 支付台卡图片,并构建绘图对象 */
            Graphics2D baseG = baseImg.createGraphics();


            /** 设置二维码的大小 */
            int widthQrcodeFrame = qrcodeWhiteFrame.getWidth(), 
                    heightQrcodeFrame = qrcodeWhiteFrame.getHeight();


            /** * 二维码图片放在支付台卡中心 */
            int x = (baseImg.getWidth() - qrcodeWhiteFrame.getWidth()) / 2 + 10;
            int y = (baseImg.getHeight() - qrcodeWhiteFrame.getHeight()) / 2 + 30;


            //开始绘制图片
            baseG.drawImage(qrcodeWhiteFrame, x, y, widthQrcodeFrame, heightQrcodeFrame, null);
            baseG.drawRoundRect(x, y, widthQrcodeFrame, heightQrcodeFrame, 15, 15);
            baseG.setStroke(new BasicStroke(logoConfig.getBorder()));
            baseG.setColor(logoConfig.getBorderColor());
            baseG.drawRect(x, y, widthQrcodeFrame, heightQrcodeFrame);


            //把编号添加到支付卡台上
            if (StringUtil.isNotEmptyStr("12131231")) {
            //画文字到新的面板
            baseG.setColor(Color.WHITE);
            //字体、字型、字号 
            baseG.setFont(new Font("Arial Unicode MS", Font.PLAIN, 45)); 
            //画文字
            baseG.drawString("NO. " + payNo, 80, 430);
            }
            //把姓名添加到支付卡台上
            if (StringUtil.isNotEmptyStr("name")) {
            //画文字到新的面板
            baseG.setColor(Color.BLACK);
            //字体、字型、字号 
            String fontPath = request.getSession().getServletContext().getRealPath("/") + "font/SIMSUN.TTC";
            Font font = loadFont(fontPath, 50f);//调用
            baseG.setFont(font);
//             baseG.setFont(new Font("SansSerif", Font.PLAIN, 50)); 
            //画文字
            baseG.drawString("姓名 : " +"name", 160, 1780);
            }
            //把名称添加到支付卡台上
            if (StringUtil.isNotEmptyStr("name")) {
            //画文字到新的面板
            baseG.setColor(Color.BLACK);
            //字体、字型、字号 
            String fontPath = request.getSession().getServletContext().getRealPath("/") + "font/SIMSUN.TTC";
            Font font = loadFont(fontPath, 50f);//调用
            baseG.setFont(font); 
//             baseG.setFont(new Font("Serif", Font.PLAIN, 50)); 
            //画文字
            baseG.drawString("名称 : " + "name", 160, 1850);
            }
            baseG.dispose();


            }


            if(baseImg!=null){
            baseImg.flush();
            }
            Qrcode.flush();
            qrcodeWhiteFrame.flush();
//            ByteArrayOutputStream baos = new ByteArrayOutputStream();
//            baos.flush();
//            File file = new File("d:\\work\\tmp\\1112.jpg");
//            ImageIO.write(baseImg, "jpg", baos);
//            ImageIO.write(baseImg, "jpg", file);


            //二维码生成的路径,但是实际项目中,我们是把这生成的二维码显示到界面上的,因此下面的折行代码可以注释掉
            //可以看到这个方法最终返回的是这个二维码的imageBase64字符串
            //前端用 其中${imageBase64QRCode}对应二维码的imageBase64字符串
        //    ImageIO.write(image, "png", new File("C:/Users/xuxiaogen/Desktop/TDC-"  + "test.png")); //TODO 


//            String imageBase64QRCode =  Base64.encodeBase64String(baos.toByteArray());
      //      System.out.println(imageBase64QRCode);
//            baos.close();
            return baseImg;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }




    /** * 构建初始化二维码 * * @param bm * @return */
    public BufferedImage fileToBufferedImage(BitMatrix bm)
    {
        BufferedImage image = null;
        try
        {
            int w = bm.getWidth(), h = bm.getHeight();
            image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
            for (int x = 0; x < w; x++)
            {
                for (int y = 0; y < h; y++)
                {
                    image.setRGB(x, y, bm.get(x, y) ? 0xFF000000 : 0xFFCCDDEE);
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return image;
    }


    /** * 生成二维码bufferedImage图片 * * @param content * 编码内容 * @param barcodeFormat * 编码类型 * @param width * 图片宽度 * @param height * 图片高度 * @param hints * 设置参数 * @return */
    public BufferedImage getQR_CODEBufferedImage(String content, BarcodeFormat barcodeFormat, int width, int height, Map hints)
    {
        MultiFormatWriter multiFormatWriter = null;
        BitMatrix bm = null;
        BufferedImage image = null;
        try
        {
            multiFormatWriter = new MultiFormatWriter();
            // 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
            bm = multiFormatWriter.encode(content, barcodeFormat, width, height, hints);
            bm = deleteWhite(bm);//删除白边
            int w = bm.getWidth();
            int h = bm.getHeight();
            image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);


            // 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色
            for (int x = 0; x < w; x++)
            {
                for (int y = 0; y < h; y++)
                {
                    image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);
                }
            }
/*            File file = new File("d:\\work\\tmp\\111.jpg");
            ImageIO.write(image, "jpg", file);*/
        }


        catch (Exception e)
        {
            e.printStackTrace();
        }
        return image;
    }


    /** * 设置二维码的格式参数 * * @return */
    public static Map getDecodeHintType()
    {
        // 用于设置QR二维码参数
        Map hints = new HashMap();
        // 设置QR二维码的纠错级别(H为最高级别)具体级别信息
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 设置编码方式
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.MARGIN, 0);
        hints.put(EncodeHintType.MAX_SIZE, 350);
        hints.put(EncodeHintType.MIN_SIZE, 100);


        return hints;
    }
    
    
    public static Font loadFont(String fontFileName, float fontSize)  //第一个参数是外部字体名,第二个是字体大小
{
try
{
File file = new File(fontFileName);
FileInputStream aixing = new FileInputStream(file);
Font dynamicFont = Font.createFont(Font.TRUETYPE_FONT, aixing);
Font dynamicFontPt = dynamicFont.deriveFont(fontSize);
aixing.close();
return dynamicFontPt;
}
catch(Exception e)//异常处理
{
e.printStackTrace();
return new java.awt.Font("宋体", Font.PLAIN, 14);
}
}


    //删除白边
    public static BitMatrix deleteWhite(BitMatrix matrix) {
        int[] rec = matrix.getEnclosingRectangle();
        int resWidth = rec[2] + 1;
        int resHeight = rec[3] + 1;


        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        resMatrix.clear();
        for (int i = 0; i < resWidth; i++) {
            for (int j = 0; j < resHeight; j++) {
                if (matrix.get(i + rec[0], j + rec[1]))
                    resMatrix.set(i, j);
            }
        }
        return resMatrix;
    }
    


    
    //给二维码图片加上白框
    public static BufferedImage qrcodeAddFrame(BufferedImage qrcode, int widthFrame){
    BufferedImage result = null;
    try {
    int width = qrcode.getWidth() + widthFrame * 2;
    int height = qrcode.getHeight() + widthFrame * 2;
    result = getWhiteQR_CODEBufferedImage("http://", BarcodeFormat.QR_CODE, width, height, getDecodeHintType());
} catch (Exception e) {
        log.info("qrcodeAddFrame exception" + e);
}
return result;
    }
    
    //生成一张空白的二维码图片
    public static BufferedImage getWhiteQR_CODEBufferedImage(String content, BarcodeFormat barcodeFormat, int width, int height, Map hints)
    {
        MultiFormatWriter multiFormatWriter = null;
        BitMatrix bm = null;
        BufferedImage image = null;
        try
        {
            multiFormatWriter = new MultiFormatWriter();
            // 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
            bm = multiFormatWriter.encode(content, barcodeFormat, width, height, hints);
//            bm = deleteWhite(bm);//删除白边
            int w = bm.getWidth();
            int h = bm.getHeight();
            image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);


            // 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色
            for (int x = 0; x < w; x++)
            {
                for (int y = 0; y < h; y++)
                {
                    image.setRGB(x, y, BGWHITE);
                }
            }
        }


        catch (Exception e)
        {
        log.info("getWhiteQR_CODEBufferedImage exception" + e);
        }
        return image;
    }
}




/*
class LogoConfig
{
    // logo默认边框颜色
    public static final Color DEFAULT_BORDERCOLOR = Color.WHITE;
    // logo默认边框宽度
    public static final int DEFAULT_BORDER = 2;
    // logo大小默认为照片的1/5
    public static final int DEFAULT_LOGOPART = 5;


    private final int border = DEFAULT_BORDER;
    private final Color borderColor;
    private final int logoPart;


    *//** * Creates a default config with on color {@link #BLACK} and off color * {@link #WHITE}, generating normal black-on-white barcodes. *//*
    public LogoConfig()
    {
        this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART);
    }


    public LogoConfig(Color borderColor, int logoPart)
    {
        this.borderColor = borderColor;
        this.logoPart = logoPart;
    }


    public Color getBorderColor()
    {
        return borderColor;
    }


    public int getBorder()
    {
        return border;
    }


    public int getLogoPart()
    {
        return logoPart;
    }
}*/

你可能感兴趣的:(com.google.zxing生成的二维码自定义白边大小)