前言
功能说明: java拼接多张图片,生成的格式是jpg、bmp、gif等,如果其他格式则报错或者photoshop或者画图工具打不开
一、拼接多张图片是什么?
将宽高不同的图片拼接在一起生成一张新的图片,可以水平拼接,可以竖直拼接
二、代码展示
1.工具类
代码如下(示例):
package com.example.utils.img;
import com.example.utils.img.bean.MergeBean;
import org.springframework.util.CollectionUtils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @类功能说明: java拼接多张图片,生成的格式是jpg、bmp、gif等,如果其他格式则报错或者photoshop或者画图工具打不开
* @修改人员名: gx
* @修改日期: 2022/1/6 14:40:53
* @创建时间: 2022/1/6 14:40:53
* -------------------------------------------------------------------------------------------
* @版本: V1.0
*/
public class ImgDealUtils {
//测试类
public static void main(String[] args) {
//输入图片地址
//2张图
// String oldUrl = "http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001175/20-4E-F6-EE-F4-EF/20210710-102213_357_1.jpg?imageMogr2/cut/542x385x15x676;http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001175/20-4E-F6-EE-F4-EF/20210710-102213_357_1.jpg?imageMogr2/cut/1001x987x582x75";
//2张图
// String oldUrl = "http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001176/20-4E-F6-EE-F4-EF/20211215-142752_421_596 - 副本.jpg?imageMogr2/cut/740x870x1652x172;http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001176/20-4E-F6-EE-F4-EF/20211215-142752_421_596 - 副本.jpg?imageMogr2/cut/763x1010x2437x50";
//3张图
String oldUrl = "http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001177/20-4E-F6-EE-F4-EF/20210710-102217_710_5.jpg?imageMogr2/cut/537x393x20x673;http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001177/20-4E-F6-EE-F4-EF/20210710-102217_710_5.jpg?imageMogr2/cut/476x140x587x73;http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001177/20-4E-F6-EE-F4-EF/20210710-102217_710_5.jpg?imageMogr2/cut/483x1003x1100x60";
//5张图
// String oldUrl = "http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001175/20-4E-F6-EE-F4-EF/20210710-102213_357_1.jpg?imageMogr2/cut/542x385x15x676;http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001175/20-4E-F6-EE-F4-EF/20210710-102213_357_1.jpg?imageMogr2/cut/1001x987x582x75;http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001177/20-4E-F6-EE-F4-EF/20210710-102217_710_5.jpg?imageMogr2/cut/537x393x20x673;http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001177/20-4E-F6-EE-F4-EF/20210710-102217_710_5.jpg?imageMogr2/cut/476x140x587x73;http://bucket1-1301272873.cos.ap-shanghai.myqcloud.com/202201/900101null/wh/7001177/20-4E-F6-EE-F4-EF/20210710-102217_710_5.jpg?imageMogr2/cut/483x1003x1100x60";
String[] split = oldUrl.split(";");
//新建文件夹(有则不建)
newFolder("d:\\down");
//将远程图片下载到本地
List<String> downLoadFilePath = ImgDealUtils.getDownLoadFilePath(Arrays.asList(split), "d:\\down\\");
//调用方法生成图片>>>>>>>>>>>>>>
//水平拼接
newFolder("D://test");
ImgDealUtils.merge(downLoadFilePath, "D://test//margeHorizontalNew.jpg", true);
//竖直拼接
ImgDealUtils.merge(downLoadFilePath, "D://test//margeVerticalNew.jpg", false);
//删除某文件夹下全部文件
delAllFile("d:\\down");
}
/*
* 描述
*
* @param imgUrl
* @return java.util.List<java.lang.String>
* @author gx
* @date 2022/1/6 14:40:53
* @version 1.0
*/
public static List<String> getDownLoadFilePath(List<String> imgUrlList, String filePath) {
List<String> downLoadFilePathList = new ArrayList<>();
if (!CollectionUtils.isEmpty(imgUrlList)) {
for (int i = 0; i < imgUrlList.size(); i++) {
String newUrl = imgUrlList.get(i);
newUrl = newUrl.split("[?]")[0];
String[] fileStr = newUrl.split("/");
//得到最后一个分隔符后的名字
String fileName = i + fileStr[fileStr.length - 1];
//保存到本地的路径
// String filePath = "d:\\down\\" + fileName;
downloadPicture(imgUrlList.get(i), filePath + fileName);
downLoadFilePathList.add(filePath + fileName);
}
}
return downLoadFilePathList;
}
/*
* 描述 将远程地址下载到本地
*
* @param urlList 远程图片url集合
* @param imageName 下载到本地的图片地址
* @return
* @author gx
* @date 2022/1/6 14:42:17
* @version 1.0
*/
public static void downloadPicture(String urlList, String imageName) {
URL url = null;
boolean var3 = false;
try {
url = new URL(urlList);
DataInputStream dataInputStream = new DataInputStream(url.openStream());
FileOutputStream fileOutputStream = new FileOutputStream(new File(imageName));
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = dataInputStream.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
byte[] context = output.toByteArray();
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
} catch (MalformedURLException var10) {
var10.printStackTrace();
} catch (IOException var11) {
var11.printStackTrace();
}
}
/*
* 描述 多张图片拼接
*
* @param fileUrls 本地地址路径
* @param savePath 拼接图片存放路径
* @param isHorizontal 是否是水平拼接
* true:是(水平拼接) flase:否(竖直拼接)
* @return void
* @author gx
* @date 2022/1/6 14:39:22
* @version 1.0
*/
public static void merge(List<String> fileUrls, String savePath, Boolean isHorizontal) {
try {
List<Integer> widthList = new ArrayList<>();//存放所有图片宽度
List<Integer> heightList = new ArrayList<>();//存放所有图片高度
List<MergeBean> imgInfoList = new ArrayList<>();//存放所有图片信息
//获取图片信息并存放上面定义的变量中
getImageInfoList(fileUrls, widthList, heightList, imgInfoList);
BufferedImage imageResult = null;
if (isHorizontal) {//水平方向
imageResult = buildHorizontalImage(widthList, heightList, imgInfoList);
} else {//垂直方向
imageResult = buildVerticalImage(widthList, heightList, imgInfoList);
}
File outFile = new File(savePath);
if (!outFile.exists()) {
outFile.createNewFile();
}
int temp = savePath.lastIndexOf(".") + 1;
ImageIO.write(imageResult, savePath.substring(temp), outFile);
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 描述
*
* @param fileUrls 图片本地地址
* @param widthList 图片宽度
* @param heightList 图片高度
* @param imgInfoList 图片信息
* @return
* @author gx
* @date 2022/1/6 15:54:11
* @version 1.0
*/
private static void getImageInfoList(List<String> fileUrls, List<Integer> widthList, List<Integer> heightList, List<MergeBean> imgInfoList) throws IOException {
for (String url : fileUrls) {
MergeBean mergeBean = new MergeBean();
/* 1 读取第一张图片 */
File file = new File(url);
BufferedImage imageFirst = ImageIO.read(file);
int width = imageFirst.getWidth();// 图片宽度
int height = imageFirst.getHeight();// 图片高度
int[] imageArray = new int[width * height];// 从图片中读取RGB
imageArray = imageFirst.getRGB(0, 0, width, height, imageArray, 0, width);
widthList.add(width);
heightList.add(height);
mergeBean.setWidth(width);
mergeBean.setHeight(height);
mergeBean.setImageArray(imageArray);
imgInfoList.add(mergeBean);
}
}
/*
* 描述
*
* @param widthList 图片宽度
* @param heightList 图片高度
* @param imgInfoList 图片信息
* @return
* @author gx
* @date 2022/1/6 15:55:39
* @version 1.0
*/
private static BufferedImage buildVerticalImage(List<Integer> widthList, List<Integer> heightList, List<MergeBean> imgInfoList) {
//查找最大的宽度
Integer maxWidth = Collections.max(widthList);
//计算所有图片高度之和
Integer sumHeight = heightList.stream().reduce(Integer::sum).orElse(0);
// 生成新图片 (新图片的宽度之和,新图片的高度,BufferedImage.TYPE_INT_RGB)
BufferedImage imageResult = new BufferedImage(maxWidth, sumHeight, BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < imgInfoList.size(); i++) {
if (i == 0) {//第一张图片
//创建第一张图片
createOneVerticalImg(imageResult, maxWidth, imgInfoList.get(i));
} else {//大于一张图片
int nowHeightNum = getNowHeightNum(imgInfoList, i);//计算上一张图片结束的宽度,当前拼接的图片的开始位置
//创建图片
createOtherVerticalImg(imageResult, maxWidth, imgInfoList.get(i), nowHeightNum);
}
}
return imageResult;
}
/*
* 描述 第二张图片开始创建
*
* @param imageResult 新图的对象
* @param maxWidth 最大宽度
* @param mergeBean 图片信息
* @param nowHeightNum 上一张图片结束时的高度,该图片开始创建的位置
* @return void
* @author gx
* @date 2022/1/6 14:27:20
* @version 1.0
*/
private static void createOtherVerticalImg(BufferedImage imageResult, Integer maxWidth, MergeBean mergeBean, int nowHeightNum) {
int k1 = 0;
for (int i1 = 0; i1 < mergeBean.getHeight(); i1++) {
for (int j1 = 0; j1 < maxWidth; j1++) {
if (mergeBean.getWidth() > j1) {
imageResult.setRGB(j1, i1 + nowHeightNum, mergeBean.getImageArray()[k1]);
k1++;
} else {
imageResult.setRGB(j1, i1 + nowHeightNum, -328966);
}
}
}
}
/*
* 描述 创建第一张图片
*
* @param imageResult 新建图片对象
* @param maxWidth 最大宽度
* @param mergeBean 图片信息
* @return void
* @author gx
* @date 2022/1/6 14:35:14
* @version 1.0
*/
private static void createOneVerticalImg(BufferedImage imageResult, Integer maxWidth, MergeBean mergeBean) {
int k = 0;
for (int i = 0; i < mergeBean.getHeight(); i++) {
for (int j = 0; j < maxWidth; j++) {
if (mergeBean.getWidth() > j) {
imageResult.setRGB(j, i, mergeBean.getImageArray()[k]);
k++;
} else {
imageResult.setRGB(j, i, -328966);
}
}
}
}
/*
* 描述
*
* @param widthList 存放所有图片宽度
* @param heightList存放所有图片高度
* @param imgInfoList 存放所有图片信息
* @return java.awt.image.BufferedImage 定义的新图片
* @author gx
* @date 2022/1/6 14:22:30
* @version 1.0
*/
private static BufferedImage buildHorizontalImage(List<Integer> widthList, List<Integer> heightList, List<MergeBean> imgInfoList) {
//查找最大的高度
Integer maxHeight = Collections.max(heightList);
//计算所有图片宽度之和
Integer sumWidth = widthList.stream().reduce(Integer::sum).orElse(0);
// 生成新图片 (新图片的宽度之和,新图片的高度,BufferedImage.TYPE_INT_RGB)
BufferedImage imageResult = new BufferedImage(sumWidth, maxHeight, BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < imgInfoList.size(); i++) {
if (i == 0) { //第一张图片
//创建第一张图片
createOneHorizontalImg(imageResult, maxHeight, imgInfoList.get(i));
} else {//大于一张图片
int nowWidthNum = getNowWidthNum(imgInfoList, i);//计算上一张图片结束的宽度,当前拼接的图片的其实位置
//创建图片
createOtherHorizontalImg(imageResult, maxHeight, imgInfoList.get(i), nowWidthNum);
}
}
return imageResult;
}
/*
* 描述 计算上一张图片结束的高度,当前拼接的图片的开始位置
*
* @param imgInfoList 存放所有图片信息
* @param i 遍历到图片的位置
* @return int 返回上一张照片结束的位置,当前图片的起始位置
* @author gx
* @date 2022/1/6 14:25:13
* @version 1.0
*/
private static int getNowHeightNum(List<MergeBean> imgInfoList, int i) {
int nowHeightNum = 0;
for (int k = 0; k < i; k++) {
nowHeightNum += imgInfoList.get(k).getHeight();
}
return nowHeightNum;
}
/*
* 描述 计算上一张图片结束的宽度,当前拼接的图片的开始位置
*
* @param imgInfoList 存放所有图片信息
* @param i 遍历到图片的位置
* @return int 返回上一张照片结束的位置,当前图片的起始位置
* @author gx
* @date 2022/1/6 14:25:13
* @version 1.0
*/
private static int getNowWidthNum(List<MergeBean> imgInfoList, int i) {
int nowWidthNum = 0;
for (int k = 0; k < i; k++) {
nowWidthNum += imgInfoList.get(k).getWidth();
}
return nowWidthNum;
}
/*
* 描述 第二张图片开始创建
*
* @param imageResult 新图的对象
* @param maxHeight 最大高度
* @param mergeBean 图片信息
* @param nowWidthNum 上一张图片结束时的宽度,该图片开始创建的位置
* @return void
* @author gx
* @date 2022/1/6 14:27:20
* @version 1.0
*/
private static void createOtherHorizontalImg(BufferedImage imageResult, Integer maxHeight, MergeBean mergeBean, int nowWidthNum) {
int k1 = 0;
for (int j1 = 0; j1 < maxHeight; j1++) {
for (int i1 = 0; i1 < mergeBean.getWidth(); i1++) {
if (mergeBean.getHeight() > j1) {
imageResult.setRGB(i1 + nowWidthNum, j1, mergeBean.getImageArray()[k1]);
k1++;
} else {
imageResult.setRGB(i1 + nowWidthNum, j1, -328966);
}
}
}
}
/*
* 描述 创建第一张图片
*
* @param imageResult 新图的对象
* @param maxHeight 最大高度
* @param mergeBean 图片信息
* @return void
* @author gx
* @date 2022/1/6 14:27:20
* @version 1.0
*/
private static void createOneHorizontalImg(BufferedImage imageResult, Integer maxHeight, MergeBean mergeBean) {
int k = 0;
for (int j = 0; j < maxHeight; j++) {
for (int i = 0; i < mergeBean.getWidth(); i++) {
if (mergeBean.getHeight() > j) {
imageResult.setRGB(i, j, mergeBean.getImageArray()[k]);
k++;
} else {
imageResult.setRGB(i, j, -328966);
}
}
}
}
/**
* 删除指定文件夹下所有文件
* @param path 文件夹完整绝对路径 ,"Z:/xuyun/save"
*/
public static boolean delAllFile(String path) {
boolean flag = false;
File file = new File(path);
if (!file.exists()) {
return flag;
}
if (!file.isDirectory()) {
return flag;
}
String[] tempList = file.list();
File temp = null;
for (int i = 0; i < tempList.length; i++) {
if (path.endsWith(File.separator)) {
temp = new File(path + tempList[i]);
} else {
temp = new File(path + File.separator + tempList[i]);
}
if (temp.isFile()) {
temp.delete();
}
if (temp.isDirectory()) {
delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
delFolder(path + "/" + tempList[i]);//再删除空文件夹
flag = true;
}
}
return flag;
}
/*************************删除文件夹delFolder / 删除文件夹中的所有文件delAllFile *start***********/
/**
* 删除文件夹
* @param folderPath 文件夹完整绝对路径 ,"Z:/xuyun/save"
*/
public static void delFolder(String folderPath) {
try {
delAllFile(folderPath); //删除完里面所有内容
String filePath = folderPath;
filePath = filePath.toString();
File myFilePath = new File(filePath);
myFilePath.delete(); //删除空文件夹
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 描述 新建文件夹
*
* @param folderPath 新建文件夹路径
* @return void
* @author gx
* @date 2022/1/6 16:00:10
* @version 1.0
*/
public static void newFolder(String folderPath) {
String filePath = folderPath;
File myFilePath = new File(filePath);
try {
if (myFilePath.isDirectory()) {
// System.out.println("文件夹已存在");
} else {
myFilePath.mkdir();
// System.out.println("新建目录成功");
}
} catch (Exception var4) {
System.out.println("新建目录操作出错");
var4.printStackTrace();
}
}
}
2.实体类
代码如下(示例):
package com.example.utils.img.bean;
import lombok.Data;
/**
* 描述 存放图片信息
*
* @author
* @version 1.0
* @date 2022/01/06 10:15:11
*/
@Data
public class MergeBean {
//图片宽
private int width;
//图片高
private int height;
//图片的像素集合
private int[] imageArray;
}
该处使用的url网络请求的数据。