• 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}`);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 效果

    在这里插入图片描述

    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}`);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 效果

    在这里插入图片描述

    3、批量拼接

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

    在这里插入图片描述

    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}`);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 效果

    在这里插入图片描述

    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}`);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 效果

    在这里插入图片描述

    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}`);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 效果

    在这里插入图片描述

    插件实现

    单张图片拼接

    使用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();
          })
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    批量拼接

    • 使用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;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    自定义矩阵拼接

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    插件使用

    依赖引入

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

    横向拼接两张图片

    参数说明

    • left

    左边图片路径

    • right

    右边图片路径

    • target

    合成图片保存目录

    示例代码

    const p1 = {
        left:'.\\img\\n1.jpg',
        right:'.\\img\\n2.jpg',
        target:'.\\longImg'
    }
    // 横向拼接两张图片
    ImgConcatClass.collapseHorizontal(p1).then(res=>{
        console.log(`拼接完成,图片路径为${res}`);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    纵向拼接两张图片

    参数说明

    • left

    左边图片路径

    • right

    右边图片路径

    • target

    合成图片保存目录

    示例代码

    const p1 = {
        left:'.\\img\\n1.jpg',
        right:'.\\img\\n2.jpg',
        target:'.\\longImg'
    }
    // 纵向拼接两张图片
    ImgConcatClass.collapseVertical(p1).then(res=>{
        console.log(`拼接完成,图片路径为${res}`);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    批量拼接

    参数说明

    • 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}`);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    自定义拼接矩阵

    参数说明

    • 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}`);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    源码地址

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

    觉得有帮助的同学可以帮忙给我点个star,感激不尽~~~
    有什么想法或者改良可以给我提个pr,十分欢迎~~~
    有什么问题都可以在评论告诉我~~~

    往期精彩

    基于inquirer封装一个控制台文件选择器

    node封装一个控制台进度条插件

    vue实现一个鼠标滑动预览视频封面组件

    密码太多不知道怎么记录?不如自己写个密码箱小程序

    微信小程序实现一个手势图案锁组件

    vue封装一个图案手势锁组件

    vue封装一个弹幕组件

    为了学(mo)习(yu),我竟开发了这样一个插件

    程序员的浪漫之——情侣日常小程序

    vue简单实现词云图组件

    vue + echarts实现中国地图省份下钻联动

    使用学过的算法做个游戏很酷的好吗

    说在后面

    🎉这里是JYeontu,喜欢算法,GDCPC打过卡;热爱羽毛球,大运会打过酱油。毕业一年,两年前端开发经验,目前担任H5前端开发,算法业余爱好者,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。

  • 相关阅读:
    C++:深拷贝和浅拷贝——拷贝构造、赋值构造必须自定义
    海外游戏代投需要注意的
    快速安装NGINX
    软考软件设计师-软件工程基础知识
    【pytorch问题解决】OSError: [WinError 1455] 页面文件太小,无法完成操作。
    添加Typora主题皮肤
    Abstract Factory 抽象工厂模式简介与 C# 示例【创建型】
    Net 高级调试之十五:经典的锁故障
    SpringBoot整合阿里云OSS对象存储
    Intel汇编-内联汇编使用浮点数
  • 原文地址:https://blog.csdn.net/Twinkle_sone/article/details/126076072