Browse Source

Add threads support,except extension/folder support

HonorLee 5 years ago
parent
commit
5d3536a295
2 changed files with 94 additions and 23 deletions
  1. 84 17
      ImageMinify.js
  2. 10 6
      README.md

+ 84 - 17
ImageMinify.js

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

+ 10 - 6
README.md

@@ -23,13 +23,17 @@ $ npm link
 
 ```
 Usage: ImageMinify -q [Quality] -e [Extension] -o [Output Path] Path...
+
 Options:
-  -r, --removeorigin       Auto remove origin image when jobs done
-  -s, --silence            Run in background
-  -q, --quality <quality>  Output image quality.Default is 85
-  -e, --ext <ext>          Output file extension.Support jpg,png,auto.Default is auto
-  -o, --output <output>    Output folder path.Default is current image path with a subfolder named minified
-  -h, --help               output usage information
+  -r, --removeOrigin                 Auto remove origin image when jobs done
+  -s, --silence                      Run in background
+  -q, --quality <quality>            Output image quality.Default is 85
+  -e, --ext <ext>                    Output file extension.Support jpg,png,auto.Default is auto
+  -E, --exceptExt <exceptExt>        Special extension will not be minified but move(copy) into output.Different ext delimit by ","
+  -F, --exceptFolder <exceptFolder>  Images in excepted folder(name) will not be minified
+  -o, --output <output>              Output folder path.Default is current image path with a subfolder named minified
+  -w, --worker <worker>              Max minify worker at the same time.Default is max CPU Core Number
+  -h, --help                         output usage information
 ```
 ## TODO
 ```