介绍基于java的中间带有logo的二维码生成方法
所需jar包:QRCode.jar
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import jp.sourceforge.qrcode.QRCodeDecoder;
import com.swetake.util.Qrcode;
public class QRCodeUtils
{
private static final int WIDTH = 30;
private static final int HEIGHT = 30;
/**
* encoderQRCode(生成二维码)
* @param content 生成的二维码内容
* @param imgPath 生成的二维码文件路径
* @param logoPath logo文件路径
* @param needCompress logo是否需要压缩
*/
public void encoderQRCode(String content, String imgPath, String logoPath, boolean needCompress)
{
this.encoderQRCode(content, imgPath, "png", logoPath, 7, needCompress);
}
/**
* encoderQRCode(生成二维码)
* @param content 生成的二维码内容
* @param imgPath 生成的二维码文件路径
* @param logoPath logo文件路径
*/
public void encoderQRCode(String content, String imgPath, String logoPath)
{
this.encoderQRCode(content, imgPath, "png", logoPath, 7, true);
}
/**
* encoderQRCode(生成二维码)
* @param content 生成的二维码内容
* @param os 生成二维码文件流
* @param logoPath logo文件路径
*/
public void encoderQRCode(String content, OutputStream os, String logoPath)
{
this.encoderQRCode(content, os, "png", logoPath, 7, true);
}
/**
* encoderQRCode(生成二维码)
* @param content 生成的二维码内容
* @param os 生成二维码文件流
* @param imgType 生成的二维码文件类型
* @param logoPath logo文件路径
* @param needCompress logo是否需要压缩
*/
public void encoderQRCode(String content, OutputStream os, String imgType,
String logoPath, boolean needCompress)
{
this.encoderQRCode(content, os, imgType, logoPath, 7, needCompress);
}
/**
* encoderQRCode(生成二维码)
* @param content 生成的二维码内容
* @param imgPath 生成的二维码文件路径
* @param imgType 生成的二维码文件类型
* @param logoPath logo文件路径
* @param size 二维码版本号
* @param needCompress logo是否需要压缩
*/
public void encoderQRCode(String content, String imgPath, String imgType, String logoPath,
int size, boolean needCompress)
{
try
{
BufferedImage image = this.drawImageCode(content, imgType, logoPath, size, needCompress);
File imgFile = new File(imgPath);
ImageIO.write(image, imgType, imgFile);
}
catch (IOException e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
}
/**
* encoderQRCode(生成二维码)
* @param content
* @param os 二维码文件流
* @param imgType 二维码文件类型
* @param logoPath logo图片路径
* @param size 二维码版本号
* @param needCompress logo是否需要压缩
*/
public void encoderQRCode(String content, OutputStream os, String imgType, String logoPath,
int size, boolean needCompress)
{
try
{
BufferedImage image = this.drawImageCode(content, imgType, logoPath, size, needCompress);
ImageIO.write(image, imgType, os);
}
catch (IOException e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
}
/**
* drawImageCode(创建二维码)
* @param content 生成的二维码内容
* @param imgType 生成的二维码格式
* @param logoPath 二维码logo路径
* @param size 二维码版本号
* @param needCompress 是否压缩logo图片
*/
public BufferedImage drawImageCode(String content, String imgType, String logoPath, int size, boolean needCompress)
{
BufferedImage image = null;
try
{
Qrcode qrCode = new Qrcode();
//设置二维码的纠错率,包括L(7%)、M(15%)、Q(25%)、H(30%),默认为M
//纠错率设置的越高,允许的内容越少:L允许的数组长度为156,M允许的数组长度为124,Q允许的数组长度为88,M允许的数组长度为66
qrCode.setQrcodeErrorCorrect('M');
//设置二维码的编码方式,有A,B, N三个可选,默认为B
qrCode.setQrcodeEncodeMode('B');
//设置二维码版本号,象征二维码信息容量,可选为1-40.粗略可理解为二维码的长宽
qrCode.setQrcodeVersion(size);
byte[] contentBytes = content.getBytes("utf-8");
int imgSize = 67 + 12 * (size - 1);
image = new BufferedImage(imgSize, imgSize, BufferedImage.TYPE_INT_RGB);
Graphics2D gs = image.createGraphics();
gs.setBackground(Color.WHITE);
gs.clearRect(0, 0, imgSize, imgSize);
gs.setColor(Color.BLACK);
//设置偏移量
int pixoff = 2;
if(contentBytes.length > 0 && contentBytes.length < 800)
{
boolean[][] codeOut = qrCode.calQrcode(contentBytes);
for(int x=0; x<codeOut.length; x++)
{
for(int y=0; y<codeOut.length; y++)
{
if(codeOut[y][x])
{
gs.fillRect(y*3+pixoff, x*3+pixoff, 3, 3);
}
}
}
}
insertImage(image, logoPath, needCompress);
}
catch(Exception e)
{
e.printStackTrace();
}
return image;
}
/**
* insertImage(向二维码中插入logo)
* @param image 二维码对象
* @param logoPath logo图片路径
* @param needCompress 是否需要压缩logo
*/
private void insertImage(BufferedImage image, String logoPath, boolean needCompress) throws IOException
{
File file = new File(logoPath);
if(!file.exists())
{
System.err.print("该文件不存在"+logoPath);
}
Image src = ImageIO.read(file);
int width = src.getWidth(null);
int height = src.getHeight(null);
if(needCompress)
{
if(width > WIDTH)
{
width = WIDTH;
}
if(height > HEIGHT)
{
height = HEIGHT;
}
}
Image img = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics gs = bufImg.getGraphics();
gs.drawImage(img, 0, 0, null);
gs.dispose();
src = img;
//插入logo
Graphics2D gs2d = image.createGraphics();
int x = (image.getWidth() - width) / 2;
int y = (image.getHeight() - height) / 2;
gs2d.drawImage(src, x, y, width, height, null);
Shape shape = new RoundRectangle2D.Float(x, y, width, height, 6, 6);
gs2d.setStroke(new BasicStroke(3f));
gs2d.draw(shape);
gs2d.dispose();
}
/**
* decodeQRCode(以文件形式解析二维码)
* @param imgPath 二维码文件路径
*/
public String decodeQRCode(String imgPath)
{
File imgFile = new File(imgPath);
BufferedImage image = null;
String content = null;
try {
image = ImageIO.read(imgFile);
QRCodeDecoder decoder = new QRCodeDecoder();
content = new String(decoder.decode(new QRCodeImages(image)), "utf-8");
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
return content;
}
/**
* @param decodeQRCode(以文件流形式解析二维码)
* @param is 二维码文件输入流
*/
public String decodeQRCode(InputStream is)
{
BufferedImage image = null;
String content = null;
try
{
image = ImageIO.read(is);
QRCodeDecoder decoder = new QRCodeDecoder();
content = new String(decoder.decode(new QRCodeImages(image)), "utf-8");
}
catch (IOException e)
{
e.printStackTrace();
}
return content;
}
}
import java.awt.image.BufferedImage;
import jp.sourceforge.qrcode.data.QRCodeImage;
public class QRCodeImages implements QRCodeImage
{
private BufferedImage image;
public QRCodeImages(BufferedImage image)
{
this.image = image;
}
public int getHeight()
{
return image.getHeight();
}
public int getPixel(int i, int j)
{
return image.getRGB(i, j);
}
public int getWidth()
{
return image.getWidth();
}
}
import java.io.File;
public class QRCodeTest
{
public static void main(String[] args)
{
QRCodeUtils tdc = new QRCodeUtils();
String content = "Hello World";
String imgPath = "d:"+File.separator+"new.png";
String logoPath = "d:/123.jpg";
tdc.encoderQRCode(content, imgPath, logoPath, true);
String filePath = "d:"+File.separator+"new3.png";
String fileContent = tdc.decodeQRCode(filePath);
System.out.println(fileContent);
}
}
注:1.生成二维码时文件内容的大小有限制,具体在代码中有注释说明;
2.方法有简单的封装,如有需要,可自行扩展;
3.用Zxing.jar 这个工具类生成的二维码内容大小好像限制不是特别大,具体还没有研究,后续准备研究之后发上来;
4.本文是在学习前人的基础上整合起来的,如有雷同,纯属应该。