今天做小程序时遇到一个问题,分享长图。由于某些原因,前端做不了,于是我在后台提供了一个接口来生成长图。 主要用到的类java.awt.image.BufferedImage。在拼接图片过程中需要考虑的问题:
1.图片张数的不同,对拼接后图片的影响
2.图片大小尺寸的不同,造成拼接后的图片参差不齐的问题
第一个问题,需要循环增加拼接图片的长度(一般做纵向拼接)。针对第二个问题,使用了Thumbnails来解决,将所有图片压缩成同等大小尺寸的图片,这样拼接后图片就不会参差不齐,但是还是有失真的风险,自己把握好尺寸大小和压缩比例。Thumbnails是由谷歌提供的图片处理包,目前版本0.4.8。 可以简洁的实现图片的缩放、压缩、旋转、水印、格式转换等操作。 使用Thumbnails很简单,项目中引入maven依赖
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
以下是一个测试类
public class MergedImages {
/**
* 将多张图片拼接成一张长图
*
* @param strings 原图文件地址或url地址
* @param type 类型,1-文件地址;2-url地址
* @return 拼接后的图片BufferedImage
*/
public static BufferedImage moreToOne(String[] strings, Integer type) {
//传入图片少于1张直接返回
int len = strings.length;
if (len < 1) {
return null;
}
//使用一个数组将图片装起来
BufferedImage[] bufferedImages = new BufferedImage[len];
int[][] imageArrays = new int[len][];
for (int i = 0; i < len; i++) {
try {
if (type == 1) {
//文件地址,可直接转换
bufferedImages[i] = Thumbnails.of(strings[i])
.size(400, 600)
.outputQuality(0.8f)
.asBufferedImage();
}
if (type == 2) {
//url地址,需要先将图片获取
URL url = new URL(strings[i]);
//openStream通过url地址获取图片流
BufferedInputStream in = new BufferedInputStream(url.openStream());
bufferedImages[i] = Thumbnails.of(in)
.size(400, 600)
.outputQuality(0.8f)
.asBufferedImage();
}
} catch (Exception e) {
e.printStackTrace();
}
//获取图片宽高
int width = bufferedImages[i].getWidth();
int height = bufferedImages[i].getHeight();
// 从图片中读取RGB
imageArrays[i] = new int[width * height];
imageArrays[i] = bufferedImages[i].getRGB(0, 0, width, height,
imageArrays[i], 0, width);
}
//拼接图片的宽高
int dstHeight = 0;
int dstWidth = bufferedImages[0].getWidth();
for (BufferedImage bufferedImage : bufferedImages) {
dstWidth = Math.max(dstWidth, bufferedImage.getWidth());
dstHeight += bufferedImage.getHeight();
}
// 生成新图片
BufferedImage imageNew = null;
try {
imageNew = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_RGB);
int newHeight = 0;
for (int i = 0; i < bufferedImages.length; i++) {
imageNew.setRGB(0, newHeight, dstWidth, bufferedImages[i].getHeight(), imageArrays[i], 0, dstWidth);
newHeight += bufferedImages[i].getHeight();
}
} catch (Exception e) {
e.printStackTrace();
}
return imageNew;
}
/**
* 将图片转为base64输出
*
* @param strings 原图文件地址或url地址
* @param type 类型,1-文件地址;2-url地址
* @return 图片的base64编码
*/
public static String outBase64(String[] strings, Integer type) {
BufferedImage bufferedImage = moreToOne(strings, type);
//输出流
ByteArrayOutputStream stream = new ByteArrayOutputStream();
String base64 = null;
try {
if (bufferedImage == null) {
return null;
}
ImageIO.write(bufferedImage, "jpg", stream);
base64 = Base64.getEncoder().encodeToString(stream.toByteArray());
stream.flush();
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
return "data:image/jpg;base64," + base64;
}
/**
* 将图片保存到指定目录地址
*
* @param strings 原图文件地址或url地址
* @param type 类型,1-文件地址;2-url地址
* @param savePath 文件保存地址
*/
public static void saveFile(String[] strings, Integer type, String savePath) {
BufferedImage bufferedImage = moreToOne(strings, type);
int temp = savePath.lastIndexOf(".") + 1;
try {
File outFile = new File(savePath);
if (!outFile.exists()) {
boolean newFile = outFile.createNewFile();
if (newFile && bufferedImage != null) {
ImageIO.write(bufferedImage, savePath.substring(temp), outFile);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
String s1 = "http://127.0.0.1/2/20210906115946680612W1jqbAI263038f250a2e940dd0abd0559ac4badde.jpg";
String s2 = "http://127.0.0.1/5/20210907094432105txYYoNmBefR20e33abc8e586913615d4de6fe7f1b219.jpg";
String s3 = "http://127.0.0.1/5/20210907094551897QOYKyB55Kufq646356585f44a0158db1e117289a71c4.jpg";
String s11 = "C:\\Users\\Administrator\\Pictures\\1.jpg";
String s22 = "C:\\Users\\Administrator\\Pictures\\2.jpg";
String s33 = "C:\\Users\\Administrator\\Pictures\\3.jpg";
String saveFilePath = "C:\\Users\\Administrator\\Pictures\\overlyingImageNew.jpg";
//输出base64
String[] strings = {s1, s2, s3};
System.out.println(outBase64(strings, 2));
//写文件到指定目录
String[] string2 = {s11, s22, s33};
saveFile(string2, 1, saveFilePath);
}
}
简单记录一下,方便后续自己使用