如题:
Java代码生成二维码图片,同时在二维码上面嵌入logo小图片。涉及到图片的压缩,两张图片如何嵌入到一起,坐标的计算等知识点
三段代码:
1.这是entity类,封装了二维码中包含的数据。 参数类。
import lombok.Data;
/**
* 二维码参数
*
*/
@Data
public class QRCodeParameter {
private String qrcodeUrlPrefix;
private String qrcodeInitValue;
private Long houseId;
}
2. 核心代码,生成二维码图片,其中包括
2.1. 二维码所包含的url数据编码
2.2 根据文本数据生成图片,二维码的生成
2.3 怎么获取图片的宽带,高度等图片信息
2.4 图片的压缩,比如 200x300 的图片,压缩到 20x30 大小
2.5 两张图片怎么叠加在一起
2.6 两张图片叠加在一起,位置的计算
2.7 目录集合的创建
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 lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class QrTest {
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 = 60;
// LOGO高度(嵌入的小图片的高度)
private static final int HEIGHT = 60;
// 临时目录
public final String TMP_DIR = "E:/tmp";
// 二维码文件名称
public final String QRCODE_FILE_PATH = "E:/tmp/qrCode_%s.jpg";
// 生成二维码图片,返回生成好的图片路径
public String generateQRCode(QRCodeParameter qrcodeParameters, String logoImgPath) {
String text = generateUrl4QRCode(qrcodeParameters);
log.info("text:" + text);
// 生成的二维码的路径及名称
File file = new File(TMP_DIR);
if (! file.exists()) file.mkdir();
// 生成的二维码图片存储路径
String destPath = String.format(QRCODE_FILE_PATH, qrcodeParameters.getHouseId());
log.info(" QRCode path ,destPath :{}", destPath);
File qrCodefile = new File(destPath);
if (qrCodefile.exists()) qrCodefile.delete();
try {
_generateQRCode(text, logoImgPath, destPath, true);
} catch (Exception e) {
log.error("generateQRCode ,occurred exception ");
throw new RuntimeException("生成二维码失败");
}
return destPath;
}
// url编码处理. http://aaa.b.com?id=100 url进行字符编码处理
public static String urlEncoder(String urlPrefix, List<NameValuePair> parameters) {
String charset = "utf-8";
String result = URLEncodedUtils.format(parameters, charset);
String url = urlPrefix + "?" + result;
return url;
}
/**
* 生成二维码的公网url地址。扫码了二维码跳转到的目的地址
* @param qrcodeParameters
* @return
*/
public static String generateUrl4QRCode(QRCodeParameter qrcodeParameters) {
String urlPrefix = qrcodeParameters.getQrcodeUrlPrefix();
String houseIdValue = String.valueOf(qrcodeParameters.getHouseId());
String ordinalValue = qrcodeParameters.getQrcodeOrdinalValue();
List<NameValuePair> parameters = new ArrayList<>();
BasicNameValuePair item = new BasicNameValuePair("houseId", houseIdValue);
parameters.add(item);
item = new BasicNameValuePair("ordinal", ordinalValue);
parameters.add(item);
String url = urlEncoder(urlPrefix, parameters);
log.info("url: {}", url);
return url;
}
// 生成二维码图片
public static void _generateQRCode(String content, String logoImgPath, String destPath, boolean needCompress) throws Exception {
BufferedImage image = createImage(content, logoImgPath, needCompress);
mkdirs(destPath);
// String file = new Random().nextInt(99999999)+".jpg";
// ImageIO.write(image, FORMAT_NAME, new File(destPath+"/"+file));
ImageIO.write(image, FORMAT_NAME, new File(destPath));
}
/**
* 生成二维码图片
* @param content 二维码内容
* @param logoImgPath 二维码图片上要嵌入的其他图片路径
* @param needCompress 是否要压缩,即嵌入的图片是否要压缩嵌入到二维码上面
* @return
* @throws Exception
*/
private static BufferedImage createImage(String content, String logoImgPath, boolean needCompress) throws Exception {
Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
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 (logoImgPath == null || "".equals(logoImgPath)) {
return image;
}
// 插入图片
insertImage(image, logoImgPath, needCompress);
return image;
}
// 两张图片嵌入在一起
private static void insertImage(BufferedImage source, String logoImgPath, boolean needCompress) throws Exception {
File file = new File(logoImgPath);
if (!file.exists()) {
System.err.println("" + logoImgPath + " 该文件不存在!");
log.error("" + logoImgPath + " 该文件不存在!");
return;
}
Image src = ImageIO.read(new File(logoImgPath));
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 mkdirs(String destPath) {
File file = new File(destPath);
// 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
if (!file.exists() && !file.isDirectory()) {
file.mkdirs();
}
}
}
3. main方法调用,在本地生成二维码图片
public static void main(String[] args) {
QrTest test = new QrTest();
QRCodeParameter parameter = new QRCodeParameter();
parameter.setHouseId(101L);
parameter.setQrcodeInitValue("index");
parameter.setQrcodeUrlPrefix("http://www.baidu.com/a/b");
// logoImgPath 表示在二维码上要嵌入的另外一张图片的路径 ,比如二维码图片上嵌入了一张人物头像
/// String logoImgPath = null;
String logoImgPath = "E:/tmp/logo.jpg";
// 生成二维码
test.generateQRCode(parameter, logoImgPath);
}
4. 二维码生成效果
4.1 生成的二维码,没有logo
4.2 生成的二维码,带有logo