|
@@ -2,6 +2,7 @@
|
|
|
`use strict`
|
|
|
|
|
|
var fs = require('fs-extra');
|
|
|
+var os = require('os');
|
|
|
var path = require('path');
|
|
|
var exec = require('child_process').exec;
|
|
|
var program = require('commander');
|
|
@@ -10,25 +11,31 @@ var ProgressBar = require('progress');
|
|
|
|
|
|
|
|
|
program
|
|
|
-.option('-r, --removeorigin', 'Auto remove origin image when jobs done')
|
|
|
+.option('-r, --removeOrigin', 'Auto remove origin image when jobs done')
|
|
|
.option('-s, --silence', 'Run in background')
|
|
|
.option('-q, --quality <quality>', 'Output image quality.Default is 85')
|
|
|
.option('-e, --ext <ext>', 'Output file extension.Support jpg,png,auto.Default is auto')
|
|
|
+.option('-E, --exceptExt <exceptExt>', 'Special extension will not be minified but move(copy) into output.Different ext delimit by ","')
|
|
|
+.option('-F, --exceptFolder <exceptFolder>', 'Images in excepted folder(name) will not be minified')
|
|
|
.option('-o, --output <output>', 'Output folder path.Default is current image path with a subfolder named minified')
|
|
|
+.option('-w, --worker <worker>', 'Max minify worker at the same time.Default is max CPU Core Number')
|
|
|
.usage('-q [Quality] -e [Extension] -o [Output Path] Path...')
|
|
|
.arguments('[path...]')
|
|
|
.parse(process.argv);
|
|
|
|
|
|
var Config = {
|
|
|
- path : program.args[0],
|
|
|
- quality : program.quality,
|
|
|
- output : program.output,
|
|
|
- ext : program.ext,
|
|
|
- isFolder:false,
|
|
|
- currentDir:'',
|
|
|
- outputDir:''
|
|
|
+ path : program.args[0],
|
|
|
+ quality : program.quality,
|
|
|
+ output : program.output,
|
|
|
+ ext : program.ext,
|
|
|
+ exceptExt : program.exceptExt,
|
|
|
+ exceptFolder : program.exceptPath,
|
|
|
+ worker : program.worker,
|
|
|
+ isFolder :false,
|
|
|
+ currentDir : '',
|
|
|
+ outputDir : ''
|
|
|
}
|
|
|
-var ImageList = [],failureList = [];
|
|
|
+var ImageList = [],failureList = [],exceptExt = {},exceptFolder = {},workerCount = 0;
|
|
|
var processBar;
|
|
|
|
|
|
if(!Config.path) return program.outputHelp();
|
|
@@ -38,6 +45,19 @@ exec('gm -version | grep -o -E \'^GraphicsMagick ([0-9]|\.)+\'',function(err,std
|
|
|
})
|
|
|
|
|
|
function checkPath(){
|
|
|
+ if(Config.exceptExt){
|
|
|
+ let arr = Config.exceptExt.split(',');
|
|
|
+ for(let ext of arr){
|
|
|
+ exceptExt[ext] = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Config.exceptFolder){
|
|
|
+ let arr = Config.exceptFolder.split(',');
|
|
|
+ for(let folder of arr){
|
|
|
+ exceptFolder[folder] = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ exceptFolder['minified'] = 1;
|
|
|
fs.stat(Config.path,function(err,stats){
|
|
|
if(err || !stats) return console.error(`No such file or directory [${Config.path}]`)
|
|
|
|
|
@@ -69,12 +89,14 @@ function analysisFolder(readPath){
|
|
|
ImageList.push(filePath);
|
|
|
}
|
|
|
}else{
|
|
|
+ if(exceptFolder[path.parse(filePath).name]) continue;
|
|
|
analysisFolder(filePath);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function prepareTask(){
|
|
|
+ fs.removeSync(`${Config.outputDir}/error.log`);
|
|
|
if(!Config.output){
|
|
|
if(program.silence){
|
|
|
Config.output = 'minified';
|
|
@@ -103,43 +125,88 @@ function prepareTask(){
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if(!Config.worker){
|
|
|
+ Config.worker = os.cpus().length;
|
|
|
+ // if(program.silence){
|
|
|
+
|
|
|
+ // }else{
|
|
|
+ // Config.worker = Number(readlineSync.question('Output quality [85] : '));
|
|
|
+ // if(!Config.worker) Config.worker = os.cpus().length;
|
|
|
+ // }
|
|
|
+ }
|
|
|
startTask();
|
|
|
}
|
|
|
|
|
|
function startTask(){
|
|
|
console.log('-----------------------------------------------------------------');
|
|
|
console.log(`[ Path ] ${Config.path}`);
|
|
|
- console.log(`[Folder] ${Config.isFolder}\t[Quality] ${Config.quality}\t[OutputExtension] ${Config.ext}\t[Amount] ${ImageList.length}`);
|
|
|
+ console.log(`[Folder] ${Config.isFolder}\t[Quality] ${Config.quality}\t[OutputExtension] ${Config.ext}\t[Amount] ${ImageList.length}\t[Worker] ${Config.worker}`);
|
|
|
console.log('-----------------------------------------------------------------');
|
|
|
console.log(`[OutputDirectory] ${Config.outputDir}`);
|
|
|
console.log('-----------------------------------------------------------------');
|
|
|
processBar = new ProgressBar('Minifying: [:bar][:current/:total] [:image]', { total: ImageList.length, width: 20, complete: '*' });
|
|
|
- minify();
|
|
|
+ for(let i = 0;i<Config.worker;i++){
|
|
|
+ minify();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
function minify(){
|
|
|
- if(ImageList.length==0) return finished();
|
|
|
+ // if(ImageList.length==0) return finished();
|
|
|
+ if(ImageList.length==0) return;
|
|
|
+ workerCount++;
|
|
|
let image = ImageList.pop();
|
|
|
let pathParse = path.parse(image);
|
|
|
let imageDir = pathParse.dir;
|
|
|
let fileName = pathParse.name;
|
|
|
let subDir = imageDir.replace(Config.currentDir,'');
|
|
|
- let outputExt = (Config.ext=='auto')?pathParse.ext.replace('.',''):Config.ext;
|
|
|
+ let imgExt = pathParse.ext.replace('.','');
|
|
|
+ let outputExt = (Config.ext=='auto')?imgExt:Config.ext;
|
|
|
let outputDir = Config.outputDir + subDir;
|
|
|
let outputFile = `${outputDir}/${fileName}.${outputExt}`;
|
|
|
+
|
|
|
fs.mkdirpSync(outputDir);
|
|
|
- exec(`gm convert -strip -format '${outputExt}' -quality ${Config.quality} -depth 8 '${image}' '${outputFile}'`,function(err,stdout,stderr){
|
|
|
+
|
|
|
+ if(exceptExt[imgExt]){
|
|
|
+ if(Config.removeOrigin){
|
|
|
+ fs.moveSync(image,`${outputDir}/${fileName}.${imgExt}`);
|
|
|
+ }else{
|
|
|
+ fs.copySync(image,`${outputDir}/${fileName}.${imgExt}`);
|
|
|
+ }
|
|
|
+ processBar.total--;
|
|
|
+ workerCount--;
|
|
|
+ if(ImageList.length==1) return finished();
|
|
|
+ return minify();
|
|
|
+ }
|
|
|
+
|
|
|
+ exec(`export OMP_NUM_THREADS=4 && gm convert -strip -format '${outputExt}' -quality ${Config.quality} -depth 8 "${image}" "${outputFile}"`,function(err,stdout,stderr){
|
|
|
if(err || stdout || stderr){
|
|
|
+ console.log(err,stdout,stderr)
|
|
|
failureList.push(image);
|
|
|
}else{
|
|
|
- if(program.removeorigin) fs.removeSync(image);
|
|
|
+ if(program.removeOrigin) fs.removeSync(image);
|
|
|
}
|
|
|
- processBar.tick(1,{'image':`${subDir}/${fileName}`});
|
|
|
+ processBar.tick(1,{'image':`${subDir}/${fileName}.${imgExt}`});
|
|
|
+
|
|
|
+ workerCount--;
|
|
|
+ if(workerCount==0 && ImageList.length==0) return finished();
|
|
|
minify();
|
|
|
});
|
|
|
}
|
|
|
function finished(){
|
|
|
- if(!program.silence) console.log('\All images minified');
|
|
|
+ if(!program.silence) console.log('\nAll images minified');
|
|
|
+ if(!failureList.length) return;
|
|
|
+ let log = '';
|
|
|
+ log += ('\n-----------------------------------------------------------------');
|
|
|
+ log += ('These image(s) minified failed!');
|
|
|
+ log += ('-----------------------------------------------------------------');
|
|
|
+
|
|
|
+ for(let image of failureList){
|
|
|
+ log += image + '\n';
|
|
|
+ }
|
|
|
+ log += ('-----------------------------------------------------------------\n');
|
|
|
+
|
|
|
+ fs.writeFileSync(`${Config.outputDir}/error.log`,log,'UTF-8');
|
|
|
+ console.log(log);
|
|
|
}
|
|
|
|
|
|
|