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);
})
}