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

1 篇文章 0 订阅
基于 google zxing

[b]1.添加Maven依赖:[/b]


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


[b]2.封装二维码对象[/b]


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;
}
}


[b]3.工具类[/b]

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;
}
}
}

[b]4.效果图[/b]

[img]http://dl2.iteye.com/upload/attachment/0117/5252/9b0632fc-91c5-3fe7-bfb5-df35e5fb266a.jpg[/img]
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值