java使用谷歌的zxing包进行二维码生成并减少周边白色区域

网上找到一些使用zxing包生成二维码的例子,但是发现周边的白色区域有点大,想减少一点,有写说法是设置参数hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小,感觉没用,不生效,四周的白色区域仍然很大。想了想,既然生成二维码的时候周边白色区域过大,那把二维码对象转为BufferedImage对象的时候,减少一点长宽,不就好了,试了下,感觉还行,生成出来的二维码也能正常用,只是周边的白色区域需要减少多少,就没法定了,需要根据生成二维码图片的width/height,自己一点点尝试。

 

下面的代码是网上别人的,就稍微修改了toBufferedImage的是传入要减少白色区域多少的参数。

<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>core</artifactId>
			<version>3.4.1</version>
		</dependency>
package com.southgroup.psimp.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.Hashtable;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.StringUtils;

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

/**
 * 二维码生成
 * @author Jfei
 *
 */
public class QrCodeUtil {

    private static final int BLACK = 0xFF000000;
    private static final int WHITE = 0xFFFFFFFF;
    private static final int margin = 0;
    private static final int LogoPart = 4;

    /**
     * 生成二维码矩阵信息
     * @param content 二维码图片内容
     * @param width 二维码图片宽度
     * @param height 二维码图片高度
     * @throws WriterException 
     */
    private static BitMatrix setBitMatrix(String content, int width, int height) throws WriterException{
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级
        hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小,感觉没用,不生效,四周的白色区域仍然很大
        BitMatrix bitMatrix = null;
        bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        return bitMatrix;
    }

    /**
     * 将二维码图片输出
     * @param matrix 二维码矩阵信息
     * @param format 图片格式
     * @param outStream 输出流
     * @param logoPath logo图片路径
     */
    private static void writeToFile(BitMatrix matrix, String format, OutputStream outStream, String logoPath,int reduceWhiteArea) throws IOException {
        BufferedImage image = toBufferedImage(matrix,reduceWhiteArea);
        // 加入LOGO水印效果
        if (StringUtils.isNotBlank(logoPath)) {
            image = addLogo(image, logoPath);
        }
        ImageIO.write(image, format, outStream);
    }

    /**
     * 生成二维码图片
     * @param matrix 二维码矩阵信息
     */
    private static BufferedImage toBufferedImage(BitMatrix matrix,int reduceWhiteArea) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width-2*reduceWhiteArea, height-2*reduceWhiteArea, BufferedImage.TYPE_3BYTE_BGR);
        for (int x = reduceWhiteArea; x < width-reduceWhiteArea; x++) {
            for (int y = reduceWhiteArea; y < height-reduceWhiteArea; y++) {
                image.setRGB(x-reduceWhiteArea, y-reduceWhiteArea, matrix.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }

    /**
     * 在二维码图片中添加logo图片
     * @param image 二维码图片
     * @param logoPath logo图片路径
     */
    private static BufferedImage addLogo(BufferedImage image, String logoPath) throws IOException {
        Graphics2D g = image.createGraphics();
        BufferedImage logoImage = ImageIO.read(new File(logoPath));
        // 计算logo图片大小,可适应长方形图片,根据较短边生成正方形
        int width = image.getWidth() < image.getHeight() ? image.getWidth() / LogoPart : image.getHeight() / LogoPart;
        int height = width;
        // 计算logo图片放置位置
        int x = (image.getWidth() - width) / 2;
        int y = (image.getHeight() - height) / 2;
        // 在二维码图片上绘制logo图片
        g.drawImage(logoImage, x, y, width, height, null);
        // 绘制logo边框,可选
//        g.drawRoundRect(x, y, logoImage.getWidth(), logoImage.getHeight(), 10, 10);
        g.setStroke(new BasicStroke(2)); // 画笔粗细
        g.setColor(Color.WHITE); // 边框颜色
        g.drawRect(x, y, width, height); // 矩形边框
        logoImage.flush();
        g.dispose();
        return image;
    }

    /**
     * 为图片添加文字
     * @param pressText 文字
     * @param newImage 带文字的图片
     * @param targetImage 需要添加文字的图片
     * @param fontStyle 字体风格
     * @param color 字体颜色
     * @param fontSize 字体大小
     * @param width 图片宽度
     * @param height 图片高度
     */
    public static void pressText(String pressText, String newImage, String targetImage, int fontStyle, Color color, int fontSize, int width, int height) {
        // 计算文字开始的位置
        // x开始的位置:(图片宽度-字体大小*字的个数)/2
        int startX = (width-(fontSize*pressText.length()))/2;
        // y开始的位置:图片高度-(图片高度-图片宽度)/2
        int startY = height-(height-width)/2 + fontSize;
        try {
            File file = new File(targetImage);
            BufferedImage src = ImageIO.read(file);
            int imageW = src.getWidth(null);
            int imageH = src.getHeight(null);
            BufferedImage image = new BufferedImage(imageW, imageH, BufferedImage.TYPE_INT_RGB);
            Graphics g = image.createGraphics();
            g.drawImage(src, 0, 0, imageW, imageH, null);
            g.setColor(color);
            g.setFont(new Font(null, fontStyle, fontSize));
            g.drawString(pressText, startX, startY);
            g.dispose();
            FileOutputStream out = new FileOutputStream(newImage);
            ImageIO.write(image, "png", out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成二维码
     * @param content
     * @param width
     * @param height
     * @param logoPath  logo的文件路径
     * @reduceWhiteArea 减少二维码图片周边的白色区域,默认0,可以慢慢根据width,height进行调整
     * @return
     * @throws IOException 
     * @throws WriterException 
     */
    public static BufferedImage createQrCode(String content,int width,int height,String logoPath,int reduceWhiteArea) throws IOException, WriterException{
    	BitMatrix bitMatrix = setBitMatrix(content, width, height);
    	BufferedImage image = toBufferedImage(bitMatrix,reduceWhiteArea);
    	if(StringUtils.isNotBlank(logoPath)){
    		 // 加入LOGO水印效果
            if (StringUtils.isNotBlank(logoPath)) {
            	image = addLogo(image, logoPath);
            }
    	}
    	return image;
    }
    
    public static void main(String[] args) throws WriterException {
      //  String content = "http://www.baidu.com";
    	String content = "测试二维码";
        String logoPath = null;
        String format = "jpg";
        int width = 200;
        int height = 200;
        BitMatrix bitMatrix = setBitMatrix(content, width, height);
        // 可通过输出流输出到页面,也可直接保存到文件
        OutputStream outStream = null;
        String path = "e:/qr"+new Date().getTime()+".png";
        try {
            outStream = new FileOutputStream(new File(path));
            writeToFile(bitMatrix, format, outStream, logoPath,10);
            outStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 ​​​​​​​   

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值