Java实现图片的垂直方向拼接

利用Java实现了任意两张图片的垂直方向拼接,不限制大小类型,可直接用于生产。

实现任意两张图片的垂直方向拼接,对于过小图片实现了放大,保证了图片拼接后的清晰度。

对于高度大于宽度的图片,进行了-90度旋转。


import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

//垂直方向合并图片
public class ImageMerge {

    /**
     * 1比较2张图片的大小,以2张图片的最大边长为宽,以第二边长为高,构造2张空图片
     * 2选择第一张图片,若宽小于于高,旋转-90度,粘贴到第一张空图片上
     * 3选择第二张图片,若宽小于于高,旋转-90度,粘贴到第二张空图片上
     *
     * @param img1 待合并的第一张图
     * @param img2 带合并的第二张图
     * @return 返回合并后的BufferedImage对象
     * @throws IOException
     */
    public static BufferedImage mergeImage(BufferedImage img1, BufferedImage img2) throws IOException {
        //判断是否需要放大图片
        if (Math.max(img1.getWidth(), img1.getHeight()) > Math.max(img2.getWidth(), img2.getHeight())) {
            img2 = judgeIfNeedChangeImageSize(img1, img2);
        } else {
            img1 = judgeIfNeedChangeImageSize(img1, img2);
        }
        //获取背景图片宽高
        int w1 = img1.getWidth();
        int h1 = img1.getHeight();
        int w2 = img2.getWidth();
        int h2 = img2.getHeight();
        List<Integer> list = Arrays.asList(w1, w2, h1, h2);
        list.sort((v1, v2) -> v2 - v1);
        int maxWidth = list.get(0);
        int maxHeight = list.get(1);
        int[] backgroundImage = new int[maxWidth * maxHeight];
        //设置背景图片数据
        for (int i = 0; i < backgroundImage.length; i++) {
            backgroundImage[i] = -1;
        }
        //绘制背景图片
        BufferedImage createImage = new BufferedImage(maxWidth, maxHeight << 1, BufferedImage.TYPE_INT_RGB);
        createImage.setRGB(0, 0, maxWidth, maxHeight, backgroundImage, 0, maxWidth);
        createImage.setRGB(0, maxHeight, maxWidth, maxHeight, backgroundImage, 0, maxWidth);
        //准备图片一绘制数据
        int[] imageArrayOne = new int[w1 * h1];
        imageArrayOne = img1.getRGB(0, 0, w1, h1, imageArrayOne, 0, w1);
        if (w1 < h1) {
            rotateImage(w1, h1, imageArrayOne);
            int temp = w1;
            w1 = h1;
            h1 = temp;
        }
        //计算绘图位置,尽量居中
        int startX;
        int startY;
        startX = (maxWidth - w1) >> 1;
        startY = (maxHeight - h1) >> 1;
        //在背景图片上绘制图片
        createImage.setRGB(startX, startY, w1, h1, imageArrayOne, 0, w1);
        //准备图片一绘制数据
        int[] imageArrayTwo = new int[w2 * h2];
        imageArrayTwo = img2.getRGB(0, 0, w2, h2, imageArrayTwo, 0, w2);
        if (w2 < h2) {
            rotateImage(w2, h2, imageArrayTwo);
            int temp = w2;
            w2 = h2;
            h2 = temp;
        }
        //计算绘图位置,尽量居中
        startX = (maxWidth - w2) >> 1;
        startY = (maxHeight - h2) >> 1;
        //准备图片二绘制数据
        createImage.setRGB(startX, maxHeight + startY, w2, h2, imageArrayTwo, 0, w2);
        return createImage;
    }


    private static BufferedImage judgeIfNeedChangeImageSize(BufferedImage img1, BufferedImage img2) {
        int w1 = img1.getWidth();
        int h1 = img1.getHeight();
        int w2 = img2.getWidth();
        int h2 = img2.getHeight();
        int max1 = Math.max(w1, h1);
        int max2 = Math.max(w2, h2);
        if (max1 < max2) {
            return enlargementImage(img1, w1, h1, max1, max2);
        } else {
            return enlargementImage(img2, w2, h2, max2, max1);
        }
    }

    private static BufferedImage enlargementImage(BufferedImage srcImg, int w1, int h1, int max1, int max2) {
        while (max2 / max1 >= 2) {
            max1 *= 2;
            w1 *= 2;
            h1 *= 2;
        }
        // 放大边长
        BufferedImage resultImg = new BufferedImage(w1, h1, BufferedImage.TYPE_INT_RGB);
        //绘制放大后的图片
        resultImg.getGraphics().drawImage(srcImg, 0, 0, w1, h1, null);
        return resultImg;
    }


    /**
     * 旋转图片-90度
     *
     * @param width  目标图像宽度
     * @param height 目标图像高度
     * @return
     */
    public static void rotateImage(int width, int height, int[] imageArray) {
        int[][] arr = new int[height][width];
        int x = 0;
        int y = 0;
        for (int i = 0; i < imageArray.length; i++) {
            arr[y][x++] = imageArray[i];
            if (x % width == 0) {
                x = 0;
                y++;
            }
        }
        //旋转-90度
        int index = 0;
        for (int j = width - 1; j >= 0; j--) {
            for (int i = 0; i < arr.length; i++) {
                imageArray[index++] = arr[i][j];
            }
        }
    }


    private static final String SOURCE_FILE_PATH = "C:\\Users\\Administrator\\Pictures\\fee.jpg";
    private static final String WATER_FILE_PATH = "C:\\Users\\Administrator\\Pictures\\invoiceH.png";
    private static final String SAVE_FILE_PATH = "C:\\Users\\Administrator\\Pictures\\overlyingImageNew.jpg";


    /**
     * @param fileUrl 文件绝对路径或相对路径
     * @return 读取到的缓存图像
     * @throws IOException 路径错误或者不存在该文件时抛出IO异常
     */
    public static BufferedImage getBufferedImage(String fileUrl)
            throws IOException {
        File f = new File(fileUrl);
        return ImageIO.read(f);
    }


    /**
     * 输出图片
     *
     * @param buffImg  图像拼接叠加之后的BufferedImage对象
     * @param savePath 图像拼接叠加之后的保存路径
     */
    public static void generateSaveFile(BufferedImage buffImg, String savePath) {
        int temp = savePath.lastIndexOf(".") + 1;
        try {
            File outFile = new File(savePath);
            if (!outFile.exists()) {
                outFile.createNewFile();
            }
            ImageIO.write(buffImg, savePath.substring(temp), outFile);
            System.out.println("ImageIO write...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * Java 测试图片合并方法
     */
    public static void imageMargeTest() {
        // 读取待合并的文件
        BufferedImage bi1 = null;
        BufferedImage bi2 = null;
        // 调用mergeImage方法获得合并后的图像
        BufferedImage destImg = null;
        System.out.println("下面是垂直合并的情况:");
        String saveFilePath = WATER_FILE_PATH;
        String divingPath = SOURCE_FILE_PATH;
        String margeImagePath = SAVE_FILE_PATH;
        try {
            bi1 = getBufferedImage(saveFilePath);
            bi2 = getBufferedImage(divingPath);
            // 调用mergeImage方法获得合并后的图像
            destImg = mergeImage(bi1, bi2);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 保存图像
        generateSaveFile(destImg, margeImagePath);
        System.out.println("垂直合并完毕!");
    }

    public static void main(String[] args) {
        // 测试图片的垂直合并
        imageMargeTest();
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/779426.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

openssh版本升级实战(修补ssh漏洞)基于RedHat8.4版本测试--已成功升级

升级前具有漏洞的的版本 通过命令查看目前系统的ssh和sshd版本&#xff1a; ssh -V sshd -V 注意&#xff1a;由于ssh是远程连接服务器的功能&#xff0c;在进行下面操作升级openssh前&#xff0c;请打开多个连接会话保持&#xff0c;如升级失败&#xff0c;可通过已连接的会话…

C#——密封类详情

密封类 密封类是密封方法的扩展&#xff0c;用于确保某个类不会被继承。在C#中&#xff0c;你可以使用sealed关键字来声明一个密封类。 public sealed class SealedClass {// 类成员定义 } 如果使用密封类继承的话&#xff0c;程序会报错&#xff01;&#xff01;&#xff0…

windows server2016搭建AD域服务器

文章目录 一、背景二、搭建AD域服务器步骤三、生成可供java程序使用的keystore文件四、导出某用户的keytab文件五、主机配置hosts文件六、主机确认是否能ping通本人其他相关文章链接 一、背景 亲测可用,之前搜索了很多博客&#xff0c;啥样的都有&#xff0c;就是不介绍报错以…

02浅谈大模型文本生成的背后逻辑

02浅谈大语言模型文本生成的背后逻辑 两个概念&#xff1a; 通俗理解大模型文本生成逻辑 假设有一个prompt&#xff1a;How are you &#xff1f;&#xff0c;输入给大模型&#xff0c;那么大模型使怎么输出&#xff1f;

nginx 主备server自动切换配置

nginx.conf 配置详情&#xff1a; #user nobody; worker_processes 1;error_log logs/error.log;events {worker_connections 1024; }http {include mime.types;default_type application/octet-stream;client_max_body_size 2048m; # 设置最大上传限制为5Gproxy_b…

锂电池寿命预测 | Matlab基于改进的遗传算法优化BP神经网络的锂离子电池健康状态SOH估计

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 主要流程如下: 1、首先提取“放电截止电压时间”作为锂电池间接健康因子&#xff1b; 2、然后引入改进的遗传算法对BP神经网络的模型参数进行优化。 3、最后 NASA 卓越预测中心的锂电池数据集 B0005、B0006、B0007对…

【实战项目】:电商网站数据抓取分析||电商API数据采集

导语&#xff1a;在电商行业&#xff0c;了解市场动态和竞争对手的信息非常重要。通过抓取电商网站上的商品数据&#xff0c;我们可以进行市场分析、价格监控和产品趋势研究。本文将介绍如何构建一个系统&#xff0c;自动化抓取电商网站上的商品数据&#xff0c;并进行分析。 …

windows下编译ffmpeg 最详细教程

1 Ffmpeg下载地址&#xff1a;FFmpeg 使用命令下载 git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg 下载完成后会发现如下目录&#xff1a; 2 msys2下载地址&#xff1a;MSYS2 解压好后&#xff0c;选择一个非空路径安装&#xff0c;安装好后路径如下&#xff1a; 为…

短视频商城系统源码揭秘:架构设计与实现

在短视频平台和电商平台蓬勃发展的背景下&#xff0c;短视频商城系统应运而生&#xff0c;融合了短视频内容和电商功能&#xff0c;给用户带来了全新的购物体验。本文将揭示短视频商城系统的源码架构设计与实现&#xff0c;帮助开发者了解该系统的内部工作原理及其关键技术。 …

【密码学】密码学体系

密码学体系是信息安全领域的基石&#xff0c;它主要分为两大类&#xff1a;对称密码体制和非对称密码体制。 一、对称密码体制&#xff08;Symmetric Cryptography&#xff09; 在对称密码体制中&#xff0c;加密和解密使用相同的密钥。这意味着发送方和接收方都必须事先拥有这…

QT使用QGraphicsView绘图 重写QGraphicsObject类实现点在QPainterPath路径上移动动画效果

闲谈&#xff1a;眨眼间&#xff0c;2024年就过去了一半了&#xff0c;年前定下的计划一个都没完成&#xff0c;也是废了。天天刷龙王CP&#xff0c;倒是看得很开心。乘着有空&#xff0c;把之前学习的内容和示例先总结了。 目录 导读SVG 转QPainterPath 路径获取QPainterPath指…

FPGA_GTX:简要版

1. GTX介绍 Xilinx FPGA的GT意思是Gigabyte Transceiver。通常称呼为Serdes、高速收发器。GT在xilinx不同系列有着不同的产品&#xff0c;从7系列到UltraScale系列分别有GTP、GTX、GTZ、GTH、GTY和GTM。不同GT整体结构上类似&#xff0c;为了支持越来越高的line rate&#xff…

【HTML】-解决页面内容无法选择、复制问题

目录 1、网页内容无法选中 1.1、问题原因 1.2、解决脚本 1.2.1、开启控制台窗口 1.2.2、执行脚本命令 2、内容复制弹出阻止框 2.2、解决脚本 1、网页内容无法选中 1.1、问题原因 今天在访问某一网站平台&#xff0c;需要将内容进行选择、复制时发现不可使用。 在使用…

单选多选提交问卷,代码示例

&#xff45;&#xff4c;&#xff45;&#xff4d;&#xff45;&#xff4e;&#xff54;中 需要对接口返回的数据进行分析。多选问题使用checkbox&#xff0c;单选题使用radio。 多选时可以绑定&#xff4d;&#xff49;&#xff4e;&#xff0f;&#xff4d;&#xff41;&am…

最新扣子(Coze)实战案例:使用图像流做超分,模糊图片秒变清晰,完全免费教程

&#x1f9d9;‍♂️ 大家好&#xff0c;我是斜杠君&#xff0c;手把手教你搭建扣子AI应用。 &#x1f4dc; 本教程是《AI应用开发系列教程之扣子(Coze)实战教程》&#xff0c;完全免费学习。 &#x1f440; 关注斜杠君&#xff0c;可获取完整版教程。&#x1f44d;&#x1f3f…

[笔记] 卷积 - 02 滤波器在时域的等效形式

1.讨论 这里主要对时域和频域的卷积运算的特征做了讨论&#xff0c;特别是狄拉克函数的物理意义。 关于狄拉克函数&#xff0c;参考这个帖子&#xff1a;https://zhuanlan.zhihu.com/p/345809392 1.狄拉克函数提到的好函数的基本特征是能够快速衰减&#xff0c;对吧&#xf…

Sharding-JDBC

一、概念&#xff1a; Sharding-JDBC是一个在客户端的分库分表工具。它是一个轻量级Java框架&#xff0c;在Java的JDBC层提供的额外服务。 ShardingSphere提供标准化的数据分片、分布式事务和数据治理功能。 二、架构图&#xff1a; ShardingRuleConfiguration 可以包含多个 T…

WEB编程-了解Tomcat服务器

第⼀章⽹络编程 1.1 概述 计算机⽹络&#xff1a;是指将地理位置不同的具有独⽴功能的多台计算机及其外部设备&#xff0c;通过通信线路连接起来&#xff0c;在⽹络 操作系统、⽹络管理软件及⽹络通信协议的管理和协调下&#xff0c;实现资源共享和信息传递的计算机系统。 …

Python 获取tiktok视频评论回复数据 api接口

TIKTOK api接口 用于爬取tiktok视频评论回复数据 详细采集页面如图 https://www.tiktok.com/dailymail/video/7329872821990182190?qneural%20link&t1706783508149 请求API http://api.xxxx.com/tt/video/info/comment/reply?video_id7288909913185701125&comment_…

uni-app使用ucharts地图,自定义Tooltip鼠标悬浮显示内容并且根据@getIndex点击事件获取点击的地区下标和地区名

项目场景&#xff1a; uni-app使用ucharts地图,自定义Tooltip鼠标悬浮显示内容并且根据getIndex点击事件获取点击的地区下标和地区名 例如&#xff1a; 问题描述 官方给的文档有限&#xff0c;需要自己下载地图json数据然后自己渲染和编写鼠标悬浮显示内容以及获取点击地址…