java拼接多张图片,可直接使用


前言

功能说明: 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网络请求的数据。


效果展示

1、原图

1.1、原图1

在这里插入图片描述

1.2、原图2

在这里插入图片描述

1.3、原图3

在这里插入图片描述

2、水平方向拼接

在这里插入图片描述

3、竖直方向拼接

在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值