微日志_免费提供日志记录|作品展示|学习教程|免费日记

Nodejs如何结合TinyPng实现基本无损的图片压缩?

图片压缩 TinyPng 阅读:155

体验地址:暂无地址

Nodejs对于开发人员来说都很熟悉,TinyPng可能很多伙伴还不知道是什么,其实它就是一个网站,百度搜索就有结果,它采用了通过有选择地减少图像中的颜色数量,需要较少的字节来存储数据,来实现图片压缩技术,肉眼很难看出端倪,但是大小却是惊人的改变,一般的图片压缩率可以高达70%左右,这对于资源大小有要的无非是一件天大的喜事。下面我们来看下如何实现:

一、获取网站

tinypng地址:https://tinypng.com/

二、.注册获取key

打开网站后,是这个样子,可以拖动图片到压缩区域进行压缩,压缩完成后进行下载,当然这不是本文的目的,少数图片是没有问题的,如果说图片太多了怎么办?

看到右上角的login按钮,点击进行登录,这里输入邮箱号即可,先说,接入api是需要付费的,但是每个月一个账号有500张免费的次数,超过了就要收费,如何做到免费,在文章最后告诉你。

类似这样,输入邮箱地址,直接发送激活链接,send link即可,然后登录邮箱,点击链接进行激活

登录成功后,点击进入个人中心,选中WordPress & API,这里我红色的圈圈出来的就是key,这个后面我们开发的时候需要使用。网站就先到这里,下面我们来写代码:

三、编写Nodejs代码,实现自动压缩

1.安装Node

如果没有nodejs,你需要去下载nodejs,这个很好操作的,下载地址在这里:https://nodejs.org/en/ ,下载后进行安装即可,安装完成后,打开cmd控制台或者终端,输入 node -v出现版本号,就证明安装成功了。

2.初始化项目

在你喜欢的目录,新建一个文件夹,名称自定义,建立好之后,进入到文件夹或者目录中,打开终端 输入

npm init

进行项目初始化,一直回车就可以了,初始化完成后,目录里面会多一个package.json文件。

3.安装依赖包

这里我们需要tinypng的依赖包,否则无法使用它的api。运行下面的命令:

npm install --save-dev tinify

等待安装完成。

4.编写代码

安装完成后,我们就开始编写代码了,新建config.js用于存放配置信息,新建index.js用作启动根文件。

config.js代码如下:

const Config = {
maxComNum:500, //个人账号的最大压缩数量
outDir:'CompressImage' //本地图片来源,默认为当前目录下的CompressImage,如果是这个名称,需要手动建立改文件夹或者目录
}
module.exports = {
Config
}

index.js代码如下:

/******
 * 
 * 系统版本:1.0.1
 * 系统作者:keen
 * 系统说明:本系统接入tp压缩,key需要自己去官方申请,进入根目录直接node index,然后输入key值即可自动压缩,config为一些配置,
 * 默认输出目录会在CompressImage,安装放入的原样输出,讲需要压缩的图片放到CompressImage目录下,压缩完成后,会自动放回对应目录。
 * 完成时间:2020-05-19
 * 
 * *****/
const tinify = require("tinify"), //导入tinypng的api包
fs = require("fs"), //导入node 的文件系统
readline = require("readline"); //引入读取一行
Config = require("./config").Config; //引入配置文件
class Compress {  //创建类
constructor(key, path) { //初始化数据
console.log('压缩服务已启动~');
this.source = [];
this.allnum = 0;
this.init(key, path);
    }
//检查数量
checkNum() {
return Config.maxComNum - Number(this.compressionCount());
    }
//获取已用数量
compressionCount() {
return tinify.compressionCount;
    }
//设置秘钥
init(key, path) {
console.log('key初始化成功,等待签名认证...');
tinify.key = key;
this.validateKey(path);
    }
//校验
validateKey(path) {
tinify.validate(err => {
if (err) {
console.log('签名错误,请检查key值或稍后再试~');
process.exit(0);
            }
console.log('认证成功,开始校验剩余次数~');
let checkNumber = this.checkNum();
if (checkNumber <= 0 || isNaN(checkNumber)) {  //使用次数
console.log('当前key的剩余可用数已用尽或key值错误,请更换key重试!');
process.exit(0);
            }
console.log('剩余压缩次数为:' + this.checkNum());
console.log('计算文件总数,请等待...');
this.computedFiles(path);
//计算完毕
this.compress();
        });
    }
//计算文件总数
computedFiles(path) {
//读取目录
//同步执行
try {
let fileList = fs.readdirSync(path);
fileList.forEach(item => {
let stat = fs.statSync(path + '/' + item);
if (stat.isDirectory()) {  //判断是否是目录                
this.computedFiles(path + '/' + item);
                } else {
this.source.push({
path: path + '/' + item,
name: item
                    });
                }
            });
        } catch (err) {
console.log('读取发生错误:' + err);
        }
    }
//获取文件总数
getFileNum() {
this.allnum = this.source.length;
return this.allnum;
    }
//开始读取文件并上传
compress() {
console.log('文件总数为:' + this.getFileNum());
console.log('开始压缩文件,请等待...');
this.source.map(async item => {
if (!this.checkFileType(item.name, ['png', 'jpg', 'jpeg'])) {
console.log('压缩失败,文件类型错误,名称为:' + item.name);
this.allnum--;
            } else {
const source = await tinify.fromFile(item.path);  //来自于哪里
await source.toFile(item.path);  //输出到哪里
console.log('压缩成功,名称为:' + item.name);
this.allnum--;
            }
if (this.allnum == 0) {
console.log('全部压缩完成!');
process.exit(0);
            }
        });
    }
//检查文件类型
checkFileType(filePath, type) {
let arr = filePath.split('.');
if (Array.isArray(type) && type.indexOf(arr[arr.length - 1]) !== -1) return true;
else if (typeof type == 'string' && type.toLocaleLowerCase() == arr[arr.length - 1].toLocaleLowerCase()) return true;
return false;
    }
}
//默认CompressImage目录下面的所有资源,如果需要更改目录,可以在此处进行修改,默认输出CompressImage/
console.log('请输入TinyPng Key:')
const readLine = readline.createInterface({
input: process.stdin,
output: process.stdout
});
readLine.on('line', function (line) {
new Compress(`${line.replace(/\s+/g, '')}`, Config.outDir);
});

5.运行测试

我们将要压缩的图片拷贝到我们指定的文件目录中,可以是文件夹,并且里面可以包含任何文件,结果我们只需要运行程序,会自动压缩,压缩后会自动替换掉原来的文件,非图片文件不会进行处理,这个您可以完全放心。

准备图片到指定的目录:

打开终端,运行

node index

这里就会让你输入之前我们申请的key,你复制进去回车即可。结果如下:

可以清楚的看到,自动进行压缩,如果有非图片的内容存在的话,会跳过那个文件,这个我就不测试了,大家可以去自行进行测试,由于开始做游戏开发,cocos creator项目打包后,用过的都知道,文件很复杂,所以直接把res包丢到这个目录即可,方便的完成压缩,细心的朋友就可以看到,上面总和是700多KB,我压缩过后是多少呢?

此出应有掌声,tinypng太牛逼了。

最后谢谢大家的支持,奉上GitHub地址:https://github.com/vlinr/CompressImage ,有什么不懂得可以联系我哟。喜欢得话,记得支持一下哟: