最近项目中有一个需求,要将一个URL链接转成二维码,并合成到一个固定的背景图片上的指定位置。其实将二维码合成到图片上还是将图片合成到二维码上,都是同一个道理。
需要采用google提供的 jar 包来将URL转化成二维码图片。
Maven项目直接引用以下依赖:
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
以下工具方法复制即可使用。
将URL转化成二维码图片:
/**
* 二维码图片的生成
* @param content 链接
* @param qrcode_width 二维码宽
* @param qrcode_height 二维码高
* @return
* @throws Exception
*/
public static BufferedImage createImage(String content, int qrcode_width, int qrcode_height) throws Exception {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
BarcodeFormat.QR_CODE, qrcode_width, qrcode_height, 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);
}
}
return image;
}
将链接二维码放入背景图指定位置:
/**
* 合成图片,将链接转为二维码并放入背景图指定位置
* @param url 二维码链接
* @param path 背景图片地址
* @param startX 二维码在背景图片的X轴位置
* @param startY 二维码在背景图片的Y轴位置
* @param codeWidth 二维码宽度
* @param codeHeight 二维码高度
* @return 合成的图片
*/
public static BufferedImage compositeImage(String url, String path, int startX, int startY, int codeWidth, int codeHeight) {
try {
BufferedImage headImage = createImage(url, codeWidth, codeHeight);
FileInputStream fileInputStream = new FileInputStream(path);
String backBIS64 = ImageUtil.GetImageStr(fileInputStream);
// 读取背景图片
InputStream in = new ByteArrayInputStream(ImageUtil.GenerateImage(backBIS64));
Image backImage = ImageIO.read(in);
int alphaType = BufferedImage.TYPE_INT_RGB;
if (hasAlpha(backImage)) {
alphaType = BufferedImage.TYPE_INT_ARGB;
}
BufferedImage back = new BufferedImage(backImage.getWidth(null), backImage.getHeight(null), alphaType);
// 画图
Graphics2D g = back.createGraphics();
g.drawImage(backImage, 0, 0, null);
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
g.drawImage(headImage, startX, backImage.getHeight(null) - startY, headImage.getWidth(null), headImage.getHeight(null), null);
g.dispose();
return back;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 是否开启alpha通道
*
* @param image
* @return
*/
public static boolean hasAlpha(Image image) {
if (image instanceof BufferedImage) {
BufferedImage bimage = (BufferedImage) image;
return bimage.getColorModel().hasAlpha();
}
PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
try {
pg.grabPixels();
} catch (InterruptedException e) {
}
ColorModel cm = pg.getColorModel();
return cm.hasAlpha();
}
将Logo图片合成到链接二维码正中:
/**
* 合成图片,将LOGO放入链接二维码正中间
* @param url 连接地址
* @param path LOGO存储路径
* @param codeWidth 二维码宽度
* @param codeHeight 二维码高度
* @param logoPer LOGO占二维码图片的百分比
* @return
*/
public static BufferedImage compositeLogoImage(String url, String logoPath, int codeWidth, int codeHeight, int logoWidth, int logoHeight) {
try {
// 创建链接二维码
BufferedImage urlImage = createImage(url, codeWidth, codeHeight);
// 读取LOGO
FileInputStream fileInputStream = new FileInputStream(logoPath);
Image logoImage = ImageIO.read(fileInputStream);
// 加载背景图片
int alphaType = BufferedImage.TYPE_INT_RGB;
if (ImageUtil.hasAlpha(urlImage)) {
alphaType = BufferedImage.TYPE_INT_ARGB;
}
BufferedImage back = new BufferedImage(urlImage.getWidth(), urlImage.getHeight(), alphaType);
// 画图
Graphics2D g = back.createGraphics();
g.drawImage(urlImage, 0, 0, null);
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
g.drawImage(logoImage, getLogoPosition(urlImage.getWidth(), logoWidth), getLogoPosition(urlImage.getHeight(), logoHeight),
logoWidth, logoHeight, null);
g.dispose();
return back;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static int getLogoPosition(int backWidth, double logoWidth) {
Double d = (backWidth - logoWidth)/2;
return d.intValue();
}
附:BufferedImage 的使用
//通过ImageIO提供的方法可以操作BufferedImage类的写入写出
ImageIO.write(BufferedImage bufferImage, String formatName, OutputStream output);
BufferedImage bufferImage = ImageIO.read(InputStream input);
//输出到前端
ImageIO.write(bufferImage, "png", response.getOutputStream());