ImageMinify.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #! /usr/bin/env node
  2. `use strict`
  3. var fs = require('fs-extra');
  4. var path = require('path');
  5. var exec = require('child_process').exec;
  6. var program = require('commander');
  7. var readlineSync = require('readline-sync');
  8. var ProgressBar = require('progress');
  9. program
  10. .option('-r, --removeorigin', 'Auto remove origin image when jobs done')
  11. .option('-s, --silence', 'Run in background')
  12. .option('-q, --quality <quality>', 'Output image quality.Default is 85')
  13. .option('-e, --ext <ext>', 'Output file extension.Support jpg,png,auto.Default is auto')
  14. .option('-o, --output <output>', 'Output folder path.Default is current image path with a subfolder named minified')
  15. .usage('-q [Quality] -e [Extension] -o [Output Path] Path...')
  16. .arguments('[path...]')
  17. .parse(process.argv);
  18. var Config = {
  19. path : program.args[0],
  20. quality : program.quality,
  21. output : program.output,
  22. ext : program.ext,
  23. isFolder:false,
  24. currentDir:'',
  25. outputDir:''
  26. }
  27. var ImageList = [],failureList = [];
  28. var processBar;
  29. if(!Config.path) return program.outputHelp();
  30. exec('gm -version | grep -o -E \'^GraphicsMagick ([0-9]|\.)+\'',function(err,stdout,stderr){
  31. if(err || !stdout) return console.error('GraphicsMagick not installed!!!')
  32. checkPath();
  33. })
  34. function checkPath(){
  35. fs.stat(Config.path,function(err,stats){
  36. if(err || !stats) return console.error(`No such file or directory [${Config.path}]`)
  37. if(stats.isFile()){
  38. let ext = path.extname(Config.path);
  39. if(!ext.match(/^.(jpg|jpeg|png|gif|bmp|raw)$/gi)){
  40. return console.log("ImageMinify only support image with extension name in jpg,jpeg,png,gif,bmp or raw");
  41. }
  42. ImageList.push(Config.path);
  43. Config.currentDir = path.parse(Config.path).dir;
  44. prepareTask();
  45. }else{
  46. Config.isFolder = true;
  47. Config.currentDir = path.resolve(Config.path);
  48. analysisFolder(Config.currentDir);
  49. prepareTask();
  50. }
  51. });
  52. }
  53. function analysisFolder(readPath){
  54. let currentPath = readPath;
  55. let fileList = fs.readdirSync(currentPath);
  56. for(let fileName of fileList){
  57. let filePath = path.join(currentPath,fileName);
  58. let fileStat = fs.statSync(filePath);
  59. if(fileStat.isFile()){
  60. let ext = path.extname(fileName);
  61. if(ext.match(/jpg|jpeg|png|gif|bmp|raw/gi)){
  62. ImageList.push(filePath);
  63. }
  64. }else{
  65. analysisFolder(filePath);
  66. }
  67. }
  68. }
  69. function prepareTask(){
  70. if(!Config.output){
  71. if(program.silence){
  72. Config.output = 'minified';
  73. }else{
  74. Config.output = readlineSync.question('Output directory [minified] : ');
  75. if(!Config.output) Config.output = 'minified';
  76. }
  77. }
  78. Config.outputDir = path.resolve(Config.currentDir,Config.output);
  79. if(!Config.quality){
  80. if(program.silence){
  81. Config.quality = 85;
  82. }else{
  83. Config.quality = Number(readlineSync.question('Output quality [85] : '));
  84. if(!Config.quality) Config.quality = 85;
  85. }
  86. }
  87. if(!Config.ext){
  88. if(program.silence){
  89. Config.ext = 'auto';
  90. }else{
  91. Config.ext = readlineSync.question('Output extension,only support jpg,png,gif or auto [auto] : ');
  92. if(!Config.ext || !Config.ext.match(/^(jpg|png|gif)$/i)) Config.ext = 'auto';
  93. }
  94. }
  95. startTask();
  96. }
  97. function startTask(){
  98. console.log('-----------------------------------------------------------------');
  99. console.log(`[ Path ] ${Config.path}`);
  100. console.log(`[Folder] ${Config.isFolder}\t[Quality] ${Config.quality}\t[OutputExtension] ${Config.ext}\t[Amount] ${ImageList.length}`);
  101. console.log('-----------------------------------------------------------------');
  102. console.log(`[OutputDirectory] ${Config.outputDir}`);
  103. console.log('-----------------------------------------------------------------');
  104. processBar = new ProgressBar('Minifying: [:bar][:current/:total] [:image]', { total: ImageList.length, width: 20, complete: '*' });
  105. minify();
  106. }
  107. function minify(){
  108. if(ImageList.length==0) return finished();
  109. let image = ImageList.pop();
  110. let pathParse = path.parse(image);
  111. let imageDir = pathParse.dir;
  112. let fileName = pathParse.name;
  113. let subDir = imageDir.replace(Config.currentDir,'');
  114. let outputExt = (Config.ext=='auto')?pathParse.ext.replace('.',''):Config.ext;
  115. let outputDir = Config.outputDir + subDir;
  116. let outputFile = `${outputDir}/${fileName}.${outputExt}`;
  117. fs.mkdirpSync(outputDir);
  118. exec(`gm convert -strip -format '${outputExt}' -quality ${Config.quality} -depth 8 '${image}' '${outputFile}'`,function(err,stdout,stderr){
  119. if(err || stdout || stderr){
  120. failureList.push(image);
  121. }else{
  122. if(program.removeorigin) fs.removeSync(image);
  123. }
  124. processBar.tick(1,{'image':`${subDir}/${fileName}`});
  125. minify();
  126. });
  127. }
  128. function finished(){
  129. if(!program.silence) console.log('\All images minified');
  130. }