前言
场景: 一、推广海报贴上二维码,用户扫码跳转
二、二维码中间贴logo
eg:这里使用展示第一种场景
一、使用工具
Google开源项目ZXing(二维条码编解码)。
二、使用步骤
1.引入依赖
代码如下(示例):
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
2.使用工具类
代码如下(示例):
public class QRCodeUtil {
private static final String CHARSET = "utf-8";
private static final String FORMAT_NAME = "JPG";
// 二维码尺寸大小
private static final int QRCODE_SIZE = 300;
// LOGO贴图位置宽度
private static final int WIDTH = 400;
// LOGO贴图位置高度
private static final int HEIGHT = 400;
// LOGO开始位置宽度
private static final int LEFT = 50;
// LOGO开始位置高度
private static final int UP = 50;
private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {
Map<EncodeHintType, Object> hints = new ConcurrentHashMap();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
if (imgPath == null || "".equals(imgPath)) {
return image;
}
// 插入图片
QRCodeUtil.insertImage(image, imgPath, needCompress);
return image;
}
private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
File file = new File(imgPath);
if (!file.exists()) {
System.err.println("" + imgPath + " 该文件不存在!");
return;
}
Image src = ImageIO.read(new File(imgPath));
int width = src.getWidth(null);
int height = src.getHeight(null);
if (needCompress) { // 压缩LOGO
if (width > WIDTH) {
width = WIDTH;
}
if (height > HEIGHT) {
height = HEIGHT;
}
Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 绘制缩小后的图
g.dispose();
src = image;
}
// 插入LOGO
Graphics2D graph = source.createGraphics();
int x = (QRCODE_SIZE - width) / 2;
int y = (QRCODE_SIZE - height) / 2;
graph.drawImage(src, x, y, width, height, null);
Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
graph.setStroke(new BasicStroke(3f));
graph.draw(shape);
graph.dispose();
}
public static void encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {
BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
mkdirs(destPath);
ImageIO.write(image, FORMAT_NAME, new File(destPath));
}
public static BufferedImage encode(String content, String imgPath, boolean needCompress) throws Exception {
BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
return image;
}
public static void mkdirs(String destPath) {
File file = new File(destPath);
// 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
if (!file.exists() && !file.isDirectory()) {
file.mkdirs();
}
}
public static void encode(String content, String imgPath, String destPath) throws Exception {
QRCodeUtil.encode(content, imgPath, destPath, false);
}
public static byte[] getQRCodeImage(String content) throws WriterException, IOException {
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE);
ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
MatrixToImageWriter.writeToStream(bitMatrix, FORMAT_NAME, pngOutputStream);
byte[] pngData = pngOutputStream.toByteArray();
return pngData;
}
public static void encode(String content, String destPath) throws Exception {
QRCodeUtil.encode(content, null, destPath, false);
}
public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)
throws Exception {
BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
ImageIO.write(image, FORMAT_NAME, output);
}
public static void encode(String content, OutputStream output) throws Exception {
QRCodeUtil.encode(content, null, output, false);
}
public static String decode(File file) throws Exception {
BufferedImage image;
image = ImageIO.read(file);
if (image == null) {
return null;
}
BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result;
Hashtable hints = new Hashtable();
hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
result = new MultiFormatReader().decode(bitmap, hints);
String resultStr = result.getText();
return resultStr;
}
public static String decode(String path) throws Exception {
return QRCodeUtil.decode(new File(path));
}
//二维码中间插入图片
public static ByteArrayOutputStream encodeIO(String content, String imgPath, Boolean needCompress) throws Exception {
BufferedImage image = QRCodeUtil.createImage(content, imgPath,
needCompress);
//创建储存图片二进制流的输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//将二进制数据写入ByteArrayOutputStream
ImageIO.write(image, "jpg", baos);
return baos;
}
private static BufferedImage createFromImage(String content, BufferedImage outer, boolean needCompress) throws Exception {
Map<EncodeHintType, Object> hints = new ConcurrentHashMap();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
// 插入图片
QRCodeUtil.insertFromImage(outer, image, needCompress);
return outer;
}
private static void insertFromImage(BufferedImage src,BufferedImage qrCode, boolean needCompress) throws Exception {
Image image = null;
int width = qrCode.getWidth(null);
int height = qrCode.getHeight(null);
if (needCompress) { // 压缩LOGO
if (width > WIDTH) {
width = WIDTH;
}
if (height > HEIGHT) {
height = HEIGHT;
}
image = qrCode.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 绘制缩小后的图
g.dispose();
}
// 插入LOGO
Graphics2D graph = src.createGraphics();
graph.drawImage(image, LEFT, UP, null);
graph.setColor(Color.WHITE);
graph.dispose();
}
//图片中插入二维码
public static ByteArrayOutputStream encodeIOWith(String content, BufferedImage outer, Boolean needCompress) throws Exception {
//插入二维码
BufferedImage image = QRCodeUtil.createFromImage(content, outer,
needCompress);
//添加文字水印
addText(image, content);
//创建储存图片二进制流的输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//将二进制数据写入ByteArrayOutputStream
ImageIO.write(image, "jpg", baos);
return baos;
}
public static void addText(BufferedImage image,String text){
Graphics2D graph = image.createGraphics();
// graph.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
// 5、设置水印文字颜色
graph.setColor(Color.black);
graph.setFont(new Font("宋体", Font.BOLD, 15));
// 文字增加清晰度
graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
// 6、设置文字水印内容
graph.drawString("邀请码:", 240, 450);
graph.drawString(text, 220, 470);
graph.dispose();
}
}
3.调用
try {
//二维码内容
String content = "https://www.csdn.net/";
String ossPath="poster1.jpg";
//sso获取图片位数据
byte[] download = ossSupport.download(ossPath);
BufferedImage outerImg = ImageIO.read(new ByteArrayInputStream(download));
//是否根据贴图位置空间压缩二维码
Boolean needCompress = true;
//图片海报outerImg中插入二维码和文字水印
ByteArrayOutputStream out = QRCodeUtil.encodeIOWith(content, outerImg, needCompress);
//返回二维码
response.setCharacterEncoding("UTF-8");
response.setContentType("image/jpeg;charset=UTF-8");
response.setContentLength(out.size());
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(out.toByteArray());
outputStream.flush();
outputStream.close();
}catch (Exception e){
e.printStackTrace();
}