`

java web 二维码生成 工具类 内嵌图片 背景图片 彩色二维码

阅读更多
基于 google zxing

1.添加Maven依赖:

<dependency>
			<groupId>net.glxn.qrgen</groupId>
			<artifactId>javase</artifactId>
			<version>2.0</version>
		</dependency>


2.封装二维码对象

import java.io.InputStream;
import java.io.Serializable;

/**
 * Created by Gjh on 2016/5/18.
 * 封装生成二维码数据传输对象
 */
public class QrCodeDTO implements Serializable {

    /**
     * 背景图流
     */
    private InputStream backImageStream;
    /**
     * 内嵌图流
     */
    private InputStream innerImageStream;
    /**
     * 二维码内容
     */
    private String content;
    /**
     * 生成二维码宽度
     */
    private int imageWidth = 300;
    /**
     * 生成二维码高度
     */
    private int imageHeight = 300;
    /**
     * 生成图片宽度
     */
    private int outerImageWidth;
    /**
     * 生成图片高度
     */
    private int outerImageHeight;
    /**
     * 生成二维码边框宽度(默认边框:2)
     */
    private int frameWidth = 2;
    /**
     * 内嵌图片宽度
     */
    private int innerImageWidth;
    /**
     * 内嵌图片高度
     */
    private int innerImageHeight;
    /**
     * 二维码颜色(ARGB)(默认值:0xff000000)
     */
    private int argb = 0xff000000;

    public QrCodeDTO() {
    }

    /**
     * 构建二维码数据传输对象
     * @param content
     *          内容
     * @param imageWidth
     *          生成宽度
     * @param imageHeight
     *          生成高度
     */
    public QrCodeDTO(String content, int imageWidth, int imageHeight) {
        this.content = content;
        this.imageWidth = imageWidth;
        this.imageHeight = imageHeight;
    }

    /**
     * 构建带有内嵌图片的二维码数据传输对象
     * @param innerImageStream
     *          内嵌图片流
     * @param content
     *          二维码内容
     * @param imageWidth
     *          生成图片宽度
     * @param imageHeight
     *          生成图片高度
     * @param innerImageWidth
     *          内嵌图片的宽度
     * @param innerImageHeight
     *          内嵌图片的高度
     */
    public QrCodeDTO(InputStream innerImageStream, String content, int imageWidth, int imageHeight, int innerImageWidth, int innerImageHeight) {
        this.innerImageStream = innerImageStream;
        this.content = content;
        this.imageWidth = imageWidth;
        this.imageHeight = imageHeight;
        this.innerImageWidth = innerImageWidth;
        this.innerImageHeight = innerImageHeight;
    }

    /**
     * 构建带有背景图 内嵌图的 二维码数据传输对象
     * @param backImageStream
     * @param innerImageStream
     * @param content
     * @param imageWidth
     * @param imageHeight
     * @param outterImageWidth
     * @param outterImageHeight
     * @param frameWidth
     * @param innerImageWidth
     * @param innerImageHeight
     * @param argb
     */
    public QrCodeDTO(InputStream backImageStream, InputStream innerImageStream, String content, int imageWidth, int imageHeight, int outterImageWidth, int outterImageHeight, int frameWidth, int innerImageWidth, int innerImageHeight, int argb) {
        this.backImageStream = backImageStream;
        this.innerImageStream = innerImageStream;
        this.content = content;
        this.imageWidth = imageWidth;
        this.imageHeight = imageHeight;
        this.outerImageWidth = outterImageWidth;
        this.outerImageHeight = outterImageHeight;
        this.frameWidth = frameWidth;
        this.innerImageWidth = innerImageWidth;
        this.innerImageHeight = innerImageHeight;
        this.argb = argb;
    }

    public InputStream getBackImageStream() {
        return backImageStream;
    }

    public void setBackImageStream(InputStream backImageStream) {
        this.backImageStream = backImageStream;
    }

    public InputStream getInnerImageStream() {
        return innerImageStream;
    }

    public void setInnerImageStream(InputStream innerImageStream) {
        this.innerImageStream = innerImageStream;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getImageWidth() {
        return imageWidth;
    }

    public void setImageWidth(int imageWidth) {
        this.imageWidth = imageWidth;
    }

    public int getImageHeight() {
        return imageHeight;
    }

    public void setImageHeight(int imageHeight) {
        this.imageHeight = imageHeight;
    }

    public int getOuterImageWidth() {
        return outerImageWidth;
    }

    public void setOuterImageWidth(int outerImageWidth) {
        this.outerImageWidth = outerImageWidth;
    }

    public int getOuterImageHeight() {
        return outerImageHeight;
    }

    public void setOuterImageHeight(int outerImageHeight) {
        this.outerImageHeight = outerImageHeight;
    }

    public int getFrameWidth() {
        return frameWidth;
    }

    public void setFrameWidth(int frameWidth) {
        this.frameWidth = frameWidth;
    }

    public int getInnerImageWidth() {
        return innerImageWidth;
    }

    public void setInnerImageWidth(int innerImageWidth) {
        this.innerImageWidth = innerImageWidth;
    }

    public int getInnerImageHeight() {
        return innerImageHeight;
    }

    public void setInnerImageHeight(int innerImageHeight) {
        this.innerImageHeight = innerImageHeight;
    }

    public int getArgb() {
        return argb;
    }

    public void setArgb(int argb) {
        this.argb = argb;
    }
}


3.工具类
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;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Gjh on 2016/5/18.
 * 二维码生成工具
 */
public class QrGenUtils {

    // 二维码写码器
    private static MultiFormatWriter mutiWriter = new MultiFormatWriter();

    //Test
    public static void main(String[] args) {
        try {
            //新建二维码数据传输对象(内容,二维码 宽度 高度)
            QrCodeDTO code = new QrCodeDTO("http://www.baidu.com", 270, 270);
            code.setArgb(0xffaaee44);       //设置二维码颜色(可选)
            code.setFrameWidth(10);         //设置二维码边框宽度(可选)

            //添加背景(可选)
            code.setBackImageStream(new FileInputStream(new File("D:\\back.png")));
            code.setOuterImageWidth(300);
            code.setOuterImageHeight(300);

            //添加内嵌图片(可选)
            code.setInnerImageStream(new FileInputStream(new File("D:\\logo.png")));
            code.setInnerImageHeight(80);
            code.setInnerImageWidth(80);

            //生成二维码,并写入指定文件
            encode(code, "D:\\qrcode.jpg");

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

    /**
     * 生成二维码 并存盘到指定文件
     * @param code
     *          封装二维码信息 QrCode
     * @param targetFile
     *          生成二维码文件(文件格式 jpg)
     */
    public static void encode(QrCodeDTO code, String targetFile) {
        try {
            ImageIO.write(genBarcode(code), "jpg", new File(targetFile));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成二维码 返回内存流
     * @param code
     *          封装QrCode对象
     * @return
     *          返回图片流
     */
    public static OutputStream encode(QrCodeDTO code) {
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(genBarcode(code), "jpg", os);
            InputStream is = new ByteArrayInputStream(os.toByteArray());
            return  os;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据QrCode 生成二维码图片
     * @param code
     * @return
     */
    private static BufferedImage genBarcode(QrCodeDTO code) {
        try {
            //二维码内容是必须的
            if(StringUtils.isBlank( code.getContent())){
                throw new Exception("二维码内容不能为空!");
            }

            if(code.getInnerImageStream() != null && (code.getInnerImageHeight() > code.getImageHeight()
                    || code.getInnerImageWidth() > code.getImageWidth() || code.getInnerImageWidth() == 0 || code.getInnerImageHeight() == 0)){
                throw new Exception("内嵌图片长宽(必须设置)不能大于二维码图片长宽");
            }

            if(code.getBackImageStream() != null && (code.getOuterImageHeight() < code.getImageHeight()
                    || code.getOuterImageWidth() < code.getImageWidth() || code.getOuterImageHeight() == 0 || code.getOuterImageWidth() == 0)){
                throw new Exception("背景图长宽(必须设置)不能小于二维码图片长宽");
            }

            if((float)code.getInnerImageWidth() / code.getImageWidth() > 0.3 || (float)code.getInnerImageHeight() / code.getImageHeight() > 0.3){
                throw new Exception("内嵌图大小不能超过二维码图片的30%,否则生成的二维码不容易识别");
            }

            //声明二维码内容编码及错误修正级别
            Map<EncodeHintType, Object> hint = new HashMap<EncodeHintType, Object>();
            hint.put(EncodeHintType.CHARACTER_SET, "utf-8");
            hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            hint.put(EncodeHintType.MARGIN, 1);

            //获取缩放后 背景图的像素点集合
            int[][] outerPixels = null;
            if(code.getBackImageStream() != null){
                //定比例缩放或放大背景图
                BufferedImage outerImage = scale(code.getBackImageStream(), code.getOuterImageHeight(), code.getOuterImageWidth(), true);
                outerPixels = new int[code.getOuterImageWidth()][code.getOuterImageHeight()];
                for (int i = 0; i < outerImage.getWidth(); i++) {
                    for (int j = 0; j < outerImage.getHeight(); j++) {
                        outerPixels[i][j] = outerImage.getRGB(i, j);
                    }
                }
            }

            //获取缩放后 内嵌图的像素点集合
            int[][] innerPixels = null;
            if(code.getInnerImageStream() != null){
                //定比例缩放或放大背景图
                BufferedImage innerImage = scale(code.getInnerImageStream(), code.getInnerImageHeight(), code.getInnerImageWidth(), true);
                innerPixels = new int[code.getInnerImageWidth()][code.getInnerImageHeight()];
                for (int i = 0; i < innerImage.getWidth(); i++) {
                    for (int j = 0; j < innerImage.getHeight(); j++) {
                        innerPixels[i][j] = innerImage.getRGB(i, j);
                    }
                }
            }

            // 生成二维码
            BitMatrix matrix = mutiWriter.encode(code.getContent(), BarcodeFormat.QR_CODE, code.getImageWidth(), code.getImageHeight(), hint);

            if(innerPixels != null || outerPixels != null) {
                if(innerPixels != null && outerPixels == null){
                    // 二维矩阵转为一维像素数组
                    int halfW = matrix.getWidth() / 2;
                    int halfH = matrix.getHeight() / 2;
                    int[] pixels = new int[code.getImageWidth() * code.getImageHeight()];
                    int frameWidth = code.getFrameWidth();
                    int innerHalfW = code.getInnerImageWidth() / 2;

                    for (int y = 0; y < matrix.getHeight(); y++) {
                        for (int x = 0; x < matrix.getWidth(); x++) {
                            // 读取图片
                            if (x > halfW - innerHalfW && x < halfW + innerHalfW && y > halfH - innerHalfW
                                    && y < halfH + innerHalfW) {
                                pixels[y * code.getImageWidth() + x] = innerPixels[x - halfW + innerHalfW][y - halfH + innerHalfW];
                            }

                            // 在图片四周形成边框
                            else if ((x > halfW - innerHalfW - frameWidth && x < halfW - innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth && y < halfH + innerHalfW + frameWidth)
                                    || (x > halfW + innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth
                                    && y < halfH + innerHalfW + frameWidth)
                                    || (x > halfW - innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth
                                    && y < halfH - innerHalfW + frameWidth)
                                    || (x > halfW - innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH + innerHalfW - frameWidth
                                    && y < halfH + innerHalfW + frameWidth)) {
                                pixels[y * code.getImageWidth() + x] = 0xfffffff;
                            } else {
                                // 此处可以修改二维码的颜色,可以分别制定二维码和背景的颜色;
                                pixels[y * code.getImageWidth() + x] = matrix.get(x, y) ? code.getArgb() : 0xfffffff;
                            }
                        }
                    }
                    BufferedImage image = new BufferedImage(code.getImageWidth(), code.getImageHeight(), BufferedImage.TYPE_INT_RGB);
                    image.getRaster().setDataElements(0, 0, code.getImageWidth(), code.getImageHeight(), pixels);
                    return image;
                } else if(outerPixels != null){
                    // 二维矩阵转为一维像素数组
                    int halfW = code.getOuterImageWidth() / 2;
                    int halfH = code.getOuterImageHeight() / 2;
                    int[] pixels = new int[code.getOuterImageWidth() * code.getOuterImageHeight()];
                    int frameWidth = code.getFrameWidth();
                    int innerHalfW = matrix.getWidth() / 2;
                    int iconHalfW = code.getInnerImageWidth() / 2;

                    for (int y = 0; y < code.getOuterImageHeight(); y++) {
                        for (int x = 0; x < code.getOuterImageWidth(); x++) {
                            // 绘制二维码
                            if (x > halfW - innerHalfW && x < halfW + innerHalfW && y > halfH - innerHalfW && y < halfH + innerHalfW) {
                                pixels[y * code.getOuterImageWidth() + x] = matrix.get((x - halfW + innerHalfW), (y - halfH + innerHalfW))? (outerPixels[x][y]) : 0xfffffff;
                                if(innerPixels != null) {
                                    if(x > halfW - iconHalfW && x < halfW + iconHalfW && y > halfH - iconHalfW && y < halfH + iconHalfW) {
                                        pixels[y * code.getOuterImageWidth() + x] = innerPixels[x - halfW +iconHalfW][y - halfH +iconHalfW];
                                    }
                                }
                            }
                            // 在图片四周形成边框
                            else if ((x > halfW - innerHalfW - frameWidth && x < halfW - innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth && y < halfH + innerHalfW + frameWidth)
                                    || (x > halfW + innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth
                                    && y < halfH + innerHalfW + frameWidth)
                                    || (x > halfW - innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth
                                    && y < halfH - innerHalfW + frameWidth)
                                    || (x > halfW - innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH + innerHalfW - frameWidth
                                    && y < halfH + innerHalfW + frameWidth)) {
                                pixels[y * code.getOuterImageWidth() + x] = outerPixels[x][y];//0xfffffff;
                            } else {
                                //背景图绘制
                                pixels[y * code.getOuterImageWidth() + x] = outerPixels[x][y];
                            }
                        }
                    }
                    BufferedImage image = new BufferedImage(code.getOuterImageWidth(), code.getOuterImageHeight(), BufferedImage.TYPE_INT_RGB);
                    image.getRaster().setDataElements(0, 0, code.getOuterImageWidth(), code.getOuterImageHeight(), pixels);
                    return image;
                }
            } else {
                int[] pixels = new int[code.getImageWidth() * code.getImageHeight()];
                for (int y = 0; y < matrix.getHeight(); y++) {
                    for (int x = 0; x < matrix.getWidth(); x++) {
                        pixels[y * code.getImageWidth() + x] = matrix.get(x, y) ? code.getArgb() : 0xfffffff;
                    }
                }
                BufferedImage image = new BufferedImage(code.getImageWidth(), code.getImageHeight(), BufferedImage.TYPE_INT_RGB);
                image.getRaster().setDataElements(0, 0, code.getImageWidth(), code.getImageHeight(), pixels);
                return image;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 把传入的原始图像按高度和宽度进行缩放,生成符合要求的图标
     *
     * @param inputStream
     *            图片流
     * @param height
     *            目标高度
     * @param width
     *            目标宽度
     * @param hasFiller
     *            比例不对时是否需要补白:true为补白; false为不补白;
     * @throws IOException
     */
    private static BufferedImage scale(InputStream inputStream, int height, int width, boolean hasFiller)
            throws IOException {
        double ratio = 0.0; // 缩放比例
        BufferedImage srcImage = ImageIO.read(inputStream);
        if(srcImage.getWidth() != width || srcImage.getHeight() != height) {
            if(width == 0 ) width = srcImage.getWidth();
            if(height == 0) height = srcImage.getHeight();
            Image destImage = srcImage.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);
            // 计算比例
            if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {
                if (srcImage.getHeight() > srcImage.getWidth()) {
                    ratio = (new Integer(height)).doubleValue() / srcImage.getHeight();
                } else {
                    ratio = (new Integer(width)).doubleValue() / srcImage.getWidth();
                }
                AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
                destImage = op.filter(srcImage, null);
            }
            if (hasFiller) {// 补白
                BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                Graphics2D graphic = image.createGraphics();
                graphic.setColor(Color.white);
                graphic.fillRect(0, 0, width, height);
                if (width == destImage.getWidth(null))
                    graphic.drawImage(destImage, 0, (height - destImage.getHeight(null)) / 2, destImage.getWidth(null),
                            destImage.getHeight(null), Color.white, null);
                else
                    graphic.drawImage(destImage, (width - destImage.getWidth(null)) / 2, 0, destImage.getWidth(null),
                            destImage.getHeight(null), Color.white, null);
                graphic.dispose();
                destImage = image;
            }
            return (BufferedImage) destImage;
        } else {
            return srcImage;
        }
    }
}

4.效果图


  • 大小: 20.2 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics