node-canvas实现对图片的批量压缩

node-canvas实现对图片的批量压缩

1.前置知识

1. node 的文件操作系统

  • node 的fs 文件操作系统可以对本地的文件进行增删改查等一些列操作
  • fs.readdir:读取指定文件夹下文件列表
  • fs.writeFileSync:写入指定文件,不存在则创建,存在则更新

2.node-canvas 库

  • node 版的canvas,使用方法略有差异同html
  • 包的引入:const {createCanvas, loadImage} = require('canvas');
  • let cvs =createCanvas(width,height):创建一个canvas的画布
  • let ctx =cvs.getContext(‘2d’): 获取这个画布
  • ctx.translate(0, height):设置这个画布起点,也就是旋转中心/起始点
  • ctx.rotate():根据起点去旋转指定角度,单位是角度
  • cvs.toBuffer(‘image/jpeg’):获得画布的buffer流,原理是获得base64,将用文件格式和base64进行转换成buffer
  • loadImage(path).then(image=>{}):读取指定路径下的文件,并创建一个new Image(),把路径绑定在src上,再把这个元素resolve出去
  • ctx.drawImage():将图片根据指定位置去绘制指定的长度与宽度

3.exif库与照片Orientation属性

  • 照片信息读取:var {ExifImage} = require('exif')
  • new ExifImage({image:path}):异步获取图片信息,里面包含图片的真实宽高,Orientation属性
  • Orientation属性:是一些相机及其手机等设备中,来标识相机拍摄时位置的参数
  • orientation的几种类型:
  • Orientation = 1(不翻转)
  • Orientation = 3 (180度翻转)
  • Orientation = 6 (顺时针翻转90度)
  • Orientation = 8 (逆时针翻转90度)

4.image-size库

  • 为了获取图片真实高度的库
  • 为了计算压缩比和图片比例

2.实现功能

1.读取指定文件夹,并循环读取文件

fs.readdir('./mt/', (err, files) => {
    if (err) {
        console.log(err);
    } else {
        // files 当前文件夹下文件名数组
        for (let i = 0; i < files?.length; i++) {  
	        if(files[i] ==='.DS_Store'){
                console.log('过滤无关文件名,后续可用正则');
            }else{
                readParame()
            }
        }
    }
})

2.获取图片尺寸和图片Orientation,并按照位置调整宽高

function readParame(filesPath){
    var dimensions = sizeOf('./mt/' + filesPath);
    let ratio = dimensions.width / dimensions.height; // 获取宽高比
    let width = 400,height; // 默认宽度,后续可做成配置项
    new ExifImage({ image : `./mt/${filesPath}` }, function (error, exifData) {
        if (error)
            console.log('Error: '+error.message);
        else{
            const Orientation = exifData ?.image ?.Orientation;
            console.log(Orientation,'Orientation');
            // 非正常拍摄位置则宽高互换
            if (!Orientation || Orientation === 1) {
                height = width / ratio;
            }else{
                height = width*ratio;
            }
            CreateCanvas(width, height,filesPath,Orientation)
        }
    });
}

3.利用canvas调整旋转处理图片压缩图片并写入到指定位置

const OrientationType ={
    1: 0, //(不翻转)
    3: 180, // 180度翻转
    6: 90, // 顺时针翻转90度
    8: -90 //  逆时针翻转90度
}
function CreateCanvas(width,height,path,Orientation,){
    let cvs = createCanvas(width,height)
    let ctx = cvs.getContext('2d');
    if([3,6,8 ].includes(Orientation)){
	    // 非正常位置则进行对应旋转
        console.log(OrientationType[Orientation]);
        ctx.translate(0, height);
        ctx.rotate((Number(OrientationType[Orientation]))*Math.PI/180)
    }
    loadImage('./mt/' + path).then(image => {
	    // 非正常位置则进行对应旋转
       if([3,6,8 ].includes(Orientation)){
        ctx.drawImage(image, 0,0 ,height,width)
       }else{
        ctx.drawImage(image, 0,0 ,width,height)
       }
       // 获得文件buffer,并将buffer写入指定路径
        const buffer = cvs.toBuffer('image/jpeg');
        fs.writeFileSync(`./cop/${path}`,buffer);
    })
}

3.完整代码

const fs = require('fs');
var sizeOf = require('image-size');
var {ExifImage} = require('exif')
const {createCanvas, loadImage} = require('canvas');
// Orientation = 1(不翻转)
// Orientation = 2 (左右翻转)
// Orientation = 3 (180度翻转)
// Orientation = 4 (上下翻转)
// Orientation = 5 (顺时针翻转90度后,左右翻转)
// Orientation = 6 (顺时针翻转90度)
// Orientation = 7 (逆时针翻转90度后,左右翻转)
// Orientation = 8 (逆时针翻转90度)

fs.readdir('./mt/', (err, files) => {
    if (err) {
        console.log(err);
    } else {
        let str=[]
        for (let i = 0; i < files?.length; i++) {
            if(files[i] ==='.DS_Store'){
                console.log(1);
            }else{
                readParame(files[i])
            }
            
        }
    }
})
function readParame(filesPath){
    var dimensions = sizeOf('./mt/' + filesPath);
    let ratio = dimensions.width / dimensions.height; // 获取宽高比
    let width = 400,height;
    new ExifImage({ image : `./mt/${filesPath}` }, function (error, exifData) {
        if (error)
            console.log('Error: '+error.message);
        else{
            const Orientation = exifData ?.image ?.Orientation;
            console.log(Orientation,'Orientation');
            if (!Orientation || Orientation === 1) {
                height = width / ratio;
            }else{
                height = width*ratio;
            }
            CreateCanvas(width, height,filesPath,Orientation)
        }
    });
}
const OrientationType ={
    1: 0, //(不翻转)
    3: 180, // 180度翻转
    6: 90, // 顺时针翻转90度
    8: -90 //  逆时针翻转90度
}
function CreateCanvas(width,height,path,Orientation,){
    let cvs = createCanvas(width,height)
    let ctx = cvs.getContext('2d');
    if([3,6,8 ].includes(Orientation)){
        console.log(OrientationType[Orientation]);
        ctx.translate(0, height);
        ctx.rotate((Number(OrientationType[Orientation]))*Math.PI/180)
    }
    loadImage('./mt/' + path).then(image => {
       if([3,6,8 ].includes(Orientation)){
        ctx.drawImage(image, 0,0 ,height,width)
       }else{
        ctx.drawImage(image, 0,0 ,width,height)
       }
        const buffer = cvs.toBuffer('image/jpeg');
        fs.writeFileSync(`./cop/${path}`,buffer);
    })
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

家雀安知鸿鹄志

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值