node封装一个图片拼接插件

说在前面

平时我们拼接图片的时候一般都要通过ps或者其他图片处理工具来进行处理合成,这次有个需求就需要进行图片拼接,而且我希望是可以直接使用代码进行拼接,于是就有了这么一个工具包。

插件效果

通过该插件,我们可以将图片进行以下操作:

1、横向拼接两张图片

如下,我们有这么两张图片,现在我们可以通过该工具将它们拼接成一张

n1.jpg

n1.jpg

n2.jpg

n2.jpg

  • 代码
const consoleInput = require('@jyeontu/img-concat');
const ImgConcatClass = new ImgConcat();
const p1 = {left:'.\\img\\n1.jpg',right:'.\\img\\n2.jpg',target:'.\\longImg'
}
// 横向拼接两张图片
ImgConcatClass.collapseHorizontal(p1).then(res=>{console.log(`拼接完成,图片路径为${res}`);
});
  • 效果

1659164216409.jpg

2、纵向拼接两张图片

仍是上面的两张图片,我们将其进行纵向拼接

  • 代码
const consoleInput = require('@jyeontu/img-concat');
const ImgConcatClass = new ImgConcat();
const p1 = {left:'.\\img\\n1.jpg',right:'.\\img\\n2.jpg',target:'.\\longImg'
}
//纵向拼接两张图片
ImgConcatClass.collapseVertical(p1).then(res=>{console.log(`拼接完成,图片路径为${res}`);
});
  • 效果

1659165823466.jpg

3、批量拼接

我们也可以直接将某一目录中的所有图片进行批量拼接成长图,如下图,我们现在要对该目录下的所有图片进行拼接:

image.png

3.1 横向拼接长图
  • 代码
const consoleInput = require('@jyeontu/img-concat');
const ImgConcatClass = new ImgConcat();
const p = {folderPath:'.\\img',        //资源目录targetFolder:'.\\longImg',  //转换后图片存放目录direction:'y'               //拼接方向,y为横向,n为纵向
}
// 拼接目录下的所有图片
ImgConcatClass.concatAll(p).then(res=>{console.log(`拼接完成,图片路径为${res}`);
})
  • 效果

1659166670102.jpg

3.2 纵向拼接长图
  • 代码
const consoleInput = require('@jyeontu/img-concat');
const ImgConcatClass = new ImgConcat();
const p = {folderPath:'.\\img',        //资源目录targetFolder:'.\\longImg',  //转换后图片存放目录direction:'n'               //拼接方向,y为横向,n为纵向
}
// 拼接目录下的所有图片
ImgConcatClass.concatAll(p).then(res=>{console.log(`拼接完成,图片路径为${res}`);
})
  • 效果

1659167086596.jpg

4、自定义拼接矩阵

我们也可以自己定义图片拼接矩阵,shape为二维数组,定义各个位置的图片,具体如下:

  • 代码
const consoleInput = require('@jyeontu/img-concat');
const ImgConcatClass = new ImgConcat();
const p = {shape:[['.\\img\\n1.jpg','.\\img\\white.jpg','.\\img\\n2.jpg'],['.\\img\\white.jpg','.\\img\\n3.jpg','.\\img\\white.jpg'],['.\\img\\n4.jpg','.\\img\\white.jpg','.\\img\\n5.jpg']],target:'.\\longImg'
};
//自定义矩阵拼接图片
ImgConcatClass.conCatByMaxit(p).then(res=>{console.log(`拼接完成,图片路径为${res}`);
});
  • 效果

1659167368815.jpg

插件实现

单张图片拼接

使用GraphicsMagick进行图片拼接

const gm = require('gm');
collapse (left,right,target,flag = true) { return new Promise((r) => {gm(left).append(right,flag).write(target, err => {if(err) console.log(err);r();})})
}

批量拼接

  • 使用sharp.js获取图片信息,调整图片分辨率大小
  • 使用fs获取文件列表
  • 使用path拼接文件路径
  • 使用 @jyeontu/progress-bar打印进度条
const gm = require('gm');
const fs = require('fs');
const path = require('path');
const progressBar = require('@jyeontu/progress-bar');
const {getFileSuffix,getMetadata,resizeImage} = require('./util');doConcatAll = async(folderPath,targetFolder,direction) => { let fileList = fs.readdirSync(folderPath);fileList.sort((a, b) => {return path.basename(a) - path.basename(b);});const extensionName = getFileSuffix(fileList[0], ".");let targetFilePath = path.join(targetFolder, new Date().getTime() + '.' + extensionName);const barConfig = {duration: fileList.length - 1,current: 0,block:'█',showNumber:true,tip:{0: '拼接中……',100:'拼接完成'},color:'green'};let progressBarC = new progressBar(barConfig);const imgInfo = await this.getImgInfo(path.join(folderPath, fileList[0]));for (let index = 1; index < fileList.length; index++) {let leftFile = path.join(folderPath, fileList[index - 1]);let rightFile = path.join(folderPath, fileList[index]);const leftPath = await this.resizeImage({path:leftFile,width:imgInfo.width,height:imgInfo.height});const rightPath = await this.resizeImage({path:rightFile,width:imgInfo.width,height:imgInfo.height});progressBarC.run(index);await this.collapse(index == 1 ? leftPath : targetFilePath,rightPath,targetFilePath,direction);fs.unlinkSync(leftPath);fs.unlinkSync(rightPath);}console.log('');return targetFilePath;}

自定义矩阵拼接

const gm = require('gm');
const fs = require('fs');
const path = require('path');
const progressBar = require('@jyeontu/progress-bar');
const {getFileSuffix,getMetadata,resizeImage} = require('./util');
async conCatByMaxit(res){const {shape} = res;const tmpList = [];const barConfig = {duration: shape[0].length * shape.length,current: 0,block:'█',showNumber:true,tip:{0: '拼接中……',100:'拼接完成'},color:'green'};const progressBarC = new progressBar(barConfig);let target = '';let extensionName = getFileSuffix(shape[0][0], ".");const imgInfo = await this.getImgInfo(shape[0][0]);for(let i = 0; i < shape.length; i++){target = res.target + '\\' + `targetImg${i}.${extensionName}`;for(let j = 1; j < shape[i].length; j++){const leftPath = await this.resizeImage({path:shape[i][j - 1],width:imgInfo.width,height:imgInfo.height});const rightPath = await resizeImage({path:shape[i][j],width:imgInfo.width,height:imgInfo.height});tmpList.push(leftPath,rightPath,target);progressBarC.run(shape[i].length * i + j);await this.collapse(j == 1 ? leftPath : target,rightPath,target);}if( i > 0){await this.collapse(res.target + '\\' + `targetImg${i - 1}.${extensionName}`,target,target,false);}}progressBarC.run(shape[0].length * shape.length);const newTarget = res.target + '\\' + new Date().getTime() + `.${extensionName}`;fs.renameSync(target,newTarget)for(let i = 0; i < tmpList.length; i++){try{fs.unlinkSync(tmpList[i]);}catch(err){// console.error(err);}}console.log('');return newTarget;
}

插件使用

依赖引入

const consoleInput = require('@jyeontu/img-concat');
const ImgConcatClass = new ImgConcat();

横向拼接两张图片

参数说明
  • left

左边图片路径

  • right

右边图片路径

  • target

合成图片保存目录

示例代码
const p1 = {left:'.\\img\\n1.jpg',right:'.\\img\\n2.jpg',target:'.\\longImg'
}
// 横向拼接两张图片
ImgConcatClass.collapseHorizontal(p1).then(res=>{console.log(`拼接完成,图片路径为${res}`);
});

纵向拼接两张图片

参数说明
  • left

左边图片路径

  • right

右边图片路径

  • target

合成图片保存目录

示例代码
const p1 = {left:'.\\img\\n1.jpg',right:'.\\img\\n2.jpg',target:'.\\longImg'
}
// 纵向拼接两张图片
ImgConcatClass.collapseVertical(p1).then(res=>{console.log(`拼接完成,图片路径为${res}`);
});

批量拼接

参数说明
  • folderPath

资源文件目

  • targetFolder

合并图片保存目录

  • direction

图片合并方向,y为横向,n为纵向

示例代码
const consoleInput = require('@jyeontu/img-concat');
const ImgConcatClass = new ImgConcat();
const p = {folderPath:'.\\img',        //资源目录targetFolder:'.\\longImg',  //合并后图片存放目录direction:'y'               //拼接方向,y为横向,n为纵向
}
// 拼接目录下的所有图片
ImgConcatClass.concatAll(p).then(res=>{console.log(`拼接完成,图片路径为${res}`);
})

自定义拼接矩阵

参数说明
  • shape

图片合并矩阵,传入各个位置的图片路径。

  • target

合并后图片的保存路径

示例代码
const p = {shape:[['.\\img\\n1.jpg','.\\img\\white.jpg','.\\img\\n2.jpg'],['.\\img\\white.jpg','.\\img\\n3.jpg','.\\img\\white.jpg'],['.\\img\\n4.jpg','.\\img\\white.jpg','.\\img\\n5.jpg']],target:'.\\longImg'
};
//自定义矩阵拼接图片
ImgConcatClass.conCatByMaxit(p).then(res=>{console.log(`拼接完成,图片路径为${res}`);
});

源码地址

https://gitee.com/zheng_yongtao/node-scripting-tool/tree/master/src/imgConcat

觉得有帮助的同学可以帮忙给我点个star
有什么想法或者改良可以给我提个pr
有什么问题都可以在评论告诉我~

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java开发框架和中间件面试题(5)

44.Tomcat一个请求的处理流程&#xff1f; 假设来自客户的请求为&#xff1a; http&#xff1a;//localhost&#xff1a;8080/test/index.jsp请求被发送到本机端口8080&#xff0c;被在那里侦听Copote HTTP/1.1 Connector,然后 1.Connector把该请求交给它所在的Service的Engi…

STM32MP157D-DK1开发板Qt镜像构建

上篇介绍了STM32MP57-DK1开发板官方系统的烧录。那个系统包含Linux系统的基础功能&#xff0c;如果要进行Qt开发&#xff0c;还需要重新构建带有Qt功能的镜像 本篇就来介绍如何构建带有Qt功能的系统镜像&#xff0c;并在开发板中烧录构建的镜像。 1 Distribution包的构建 ST…

[C/C++]数据结构 希尔排序

&#x1f966;前言: 希尔排序也称 “缩小增量排序”&#xff0c;它也是一种插入类排序的方法,在学习希尔排序之前我们首先了解一下直接插入排序. 一: &#x1f6a9;直接插入排序 1.1 &#x1f31f;排序思路 直接插入排序的基本原理是将一条记录插入到已排好的有序表中&#x…

【经典LeetCode算法题目专栏分类】【第11期】递归问题:字母大小写全排列、括号生成

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐--…

【C++】STL 容器 - list 双向链表容器 ① ( 容器特点 | 容器操作时间复杂度 | 构造函数 )

文章目录 一、 list 双向链表容器简介1、容器特点2、容器操作时间复杂度3、遍历访问5、头文件 二、 list 双向链表容器 构造函数1、默认无参构造函数2、创建包含 n 个相同元素的 list 双向链表3、使用初始化列表构造 list 双向链表4、使用另外一个 list 容器 构造 list 双向链表…

新概念第二册(1)

【New words and expressions】生词和短语&#xff08;12&#xff09; private adj. 私人的 conversation n. 谈话 theatre n. 剧场&#xff0c;戏院 seat n. 座位 play …

关于MULTI#STORM活动利用远程访问木马瞄准印度和美国的动态情报

一、基本内容 于2023年6月22日&#xff0c;一款代号为MULTI#STORM的新网络钓鱼活动将目标瞄准了印度和美国&#xff0c;利用JavaScript文件在受感染的系统上传播远程访问木马。 二、相关发声情况 Securonix的研究人员Den luzvyk、Tim Peck和Oleg Kolesnikov发表声明称&#x…

session 的原理

目录 1&#xff0c;session 的原理如何删除 session1&#xff0c;设置过期时间2&#xff0c;客户端主动通知 2&#xff0c;和 cookie 的区别安全性举例&#xff1a;验证码 3&#xff0c;举例 1&#xff0c;session 的原理 建议先看这篇文章&#xff1a;浏览器 cookie 的原理&a…

虚继承解决菱形继承的原理

菱形继承的问题&#xff0c;是由多重继承的父类祖先是同一个父类导致的。如下面的情况&#xff1a; 菱形继承&#xff0c;会导致同名成员的二义性问题和数据冗余问题&#xff0c;用下面的代码来测试&#xff1a; class A { public:int _a; }; // class B : public A class B :…

ES8生产实践——Kibana对接Azure AD实现单点登录

基本概念介绍 什么是单点登录 单点登录&#xff08;Single Sign-On&#xff0c;SSO&#xff09;是一种身份验证和访问控制机制&#xff0c;允许用户使用一组凭据&#xff08;通常是用户名和密码&#xff09;仅需登录一次&#xff0c;即可访问多个应用程序或系统&#xff0c;而…

SpringIOC之AbstractResourceBasedMessageSource

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

C++11特性:线程同步之条件变量

条件变量是C11提供的另外一种用于等待的同步机制&#xff0c;它能阻塞一个或多个线程&#xff0c;直到收到另外一个线程发出的通知或者超时时&#xff0c;才会唤醒当前阻塞的线程。条件变量需要和互斥量配合起来使用&#xff0c;C11提供了两种条件变量&#xff1a; 1. conditi…

算法学习系列(十一):KMP算法

目录 引言一、算法概念二、题目描述三、思路讲解三、代码实现四、测试 引言 这个KMP算法就是怎么说呢&#xff0c;就是不管算法竞赛还是找工作笔试面试&#xff0c;都是非常爱问爱考的&#xff0c;其实也是因为这个算法比较难懂&#xff0c;其实就是很难&#xff0c;所以非常个…

智能优化算法应用:基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于指数分布算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.指数分布算法4.实验参数设定5.算法结果6.…

React 路由跳转

1. push 与 replace 模式 默认情况下&#xff0c;开启的是 push 模式&#xff0c;也就是说&#xff0c;每次点击跳转&#xff0c;都会向栈中压入一个新的地址&#xff0c;在点击返回时&#xff0c;可以返回到上一个打开的地址&#xff0c; 就像上图一样&#xff0c;我们每次返…

Windows下安装Oracle19C

官网下载oracle19c 以及客户端 官网地址&#xff1a;Software Download | Oracle 这个是要登录账号的,没有的可以注册,登录上 这个时候在点开这个官网:Database Software Downloads | Oracle 往下面滑 点了之后有个界面注意事项勾上,点下载,你就会下载: 安装oracle19c 解压安…

入门级:用devEco Studio创建一个鸿蒙APP

文章概叙 本文主要讲的是如何在鸿蒙的开发工具devEco Studio新建一个项目&#xff0c;全文很水&#xff0c;只适合新手!! 开始贴图 假设当前你已经下载好了devEco Studio,但是还没正式开始安装&#xff0c;此时你点击安装包&#xff0c;你会发下如下页面&#xff0c;只需要点…

【Linux系统编程】【Google面试题改编】线程之间的同步与协调 Linux文件操作

编写程序&#xff0c;有四个线程1、2、3、4 线程1的功能就是输1,线程2的功能就是输出2,以此类推……现在有四个文件ABCD初始都为空 现要让四个文件呈如下格式&#xff1a; A: 1 22 333 4444 1 22 333 4444… B: 22 333 4444 1 22 333 4444 1… C: 333 4444 1 22 333 4444 1 2…

搭建react+ant design pro+umi 项目框架

一、 写本文的原因 我搭建reactantdumi这个框架的原始资料主要是来源于&#xff08;ReactUmi4从零快速搭建中后台系统保姆级记录教程&#xff08;一、项目创建及初始化&#xff09;&#xff09; 而我写这篇文章的本意就是用来记录我用搭建时候的步骤汇总。 二、 npm和node版…

Nginx快速入门:实现企业安全防护|nginx部署https,ssl证书(七)

0. 引言 之前我们讲到nginx的一大核心作用就是实现企业安全防护&#xff0c;而实现安全防护的原理就是通过部署https证书&#xff0c;以此实现参数加密访问&#xff0c;从而加强企业网站的安全能力。 nginx作为各类服务的统一入口&#xff0c;只需要在入口处部署一个证书&…