瀏覽代碼

编写图片压缩库

bill 5 年之前
當前提交
45b201cad2
共有 5 個文件被更改,包括 303 次插入0 次删除
  1. 18 0
      .gitignore
  2. 106 0
      main.js
  3. 82 0
      minify.js
  4. 83 0
      package-lock.json
  5. 14 0
      package.json

+ 18 - 0
.gitignore

@@ -0,0 +1,18 @@
+.DS_Store
+node_modules
+input
+output
+
+# local env files
+.env.local
+.env.*.local
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw*
+*.bak

+ 106 - 0
main.js

@@ -0,0 +1,106 @@
+const {init, extnameCheck, runExtnames} = require('./minify')
+const path = require('path')
+const fs = require('fs')
+
+const analysisUrl = url => {
+  if (!url){
+    throw '无效路径'
+  } else if (path.isAbsolute(url)) {
+    return url
+  } else {
+    return path.join(__dirname, url)
+  }
+}
+
+const analysisArgs = args => {
+  const config = {
+    input: analysisUrl(args.shift()),
+    width: 0,
+    height: 0,
+    quality: 75,
+    format: undefined
+  }
+
+  if (args.length >= 5 || (
+        args.length &&
+        isNaN(Number(args[args.length - 1])) && 
+        !extnameCheck(args[args.length - 1]))
+      ) {
+    config.output = analysisUrl(args.pop())
+  } else {
+    config.output = config.input
+  }
+
+  switch(args.length) {
+    case 0:
+      break;
+    case 1:
+      if (extnameCheck(args[0])) {
+        config.format = args[0]
+      } else {
+        config.quality = args[0]
+      }
+      break;
+    case 2:
+      if (extnameCheck(args[1])) {
+        config.format = args[1]
+        config.quality = args[0]
+      } else {
+        config.width = args[0]
+        config.height = args[1]
+      }
+      break;
+    case 4:
+      config.format = extnameCheck(args[3]) && args[3]
+    default:
+      if (extnameCheck(args[2])) {
+        config.format = args[2]
+        config.width = args[0]
+        config.height = args[1]
+      } else {
+        config.quality = args[0]
+        config.width = args[1]
+        config.height = args[2]
+      }
+  }
+
+  if (config.format) {
+    let extIndex = config.output.lastIndexOf('.')
+    let extNameLen = config.output.length - extIndex - 1
+    let maxLen = Math.max(runExtnames.map(s => s.length))
+    if (!~extIndex || extNameLen > maxLen) {
+      config.output += '.' + config.format
+    } else {
+      config.output = config.output.substring(0, extIndex) + '.' + config.format
+    }
+  }
+
+  return config
+}
+
+const main = async () => {
+  const config = analysisArgs(process.argv.slice(2))
+
+  if (!fs.existsSync(config.input)) {
+    throw config.input + ' No such file or directory'
+  }
+
+  const gm = await init({fileUri: config.input})
+
+  if (config.width && config.height) {
+    gm.zoom({width: config.width, height: config.height})
+  }
+  if (config.quality) {
+    gm.quality(config.quality)
+  }
+  
+  gm.write(config.output, err => {
+    if (err) {
+      console.error(err)
+    } else {
+      console.log('成功转换,存储路径为', config.output)
+    }
+  })
+}
+
+main();

+ 82 - 0
minify.js

@@ -0,0 +1,82 @@
+const gm = require('gm').subClass({ imageMagick: true });
+const fs = require('fs');
+const runExtnames = ["png", "jpg", "jpeg", "gif", "bmp"]
+
+// 检查格式是否符合
+const extnameCheck = name => ~runExtnames.indexOf(name.toLocaleLowerCase())
+
+/**
+ * 对图片进行缩放
+ * @param {*} width Number 缩放宽度 
+ *            height Number 缩放高度
+ */
+function zoom({ width, height }) {
+  let seft = this
+
+  width = Number(width) || 0;
+  width = width < 0 ? 0 : width;
+  height = Number(height) || 0;
+  height = height < 0 ? 0 : height;
+
+  if (!width && !height) throw 'Invalid zoom size'
+
+  if (width && height) {
+    let { origin_width: oWdith, origin_height: oHeight } = seft
+    let porp = width / height, oPorp = oWdith / oHeight, left, top, cWidth, cHeight;
+
+    if (oPorp <= porp) {
+      seft.resize(width);
+      cWidth = width;
+      cHeight = cWidth / oPorp;
+    } else if (oPorp > porp) {
+      seft.resize(undefined, height);
+      cHeight = height;
+      cWidth = cHeight * oPorp;
+    }
+
+
+    left = (cWidth - width) / 2;
+    top = (cHeight - height) / 2;
+    seft = seft.crop(width, height, left, top);
+  } else {
+    seft = seft.resize(width || undefined, height || undefined);
+  }
+
+  return seft;
+}
+
+
+/**
+ * 初始化缩略图对象
+ * @param {*} fileUri string 要进行缩放的图片本地路径
+ *            stream readStream 要进行缩放的图片的可读流
+ *            fileFormat string 要缩放的图片的后缀名
+ * @return Promise 
+ */
+const init = ({ fileUri, stream }) => {
+  if (fileUri) {
+    stream = fs.createReadStream(fileUri);
+  } else if (!stream) {
+    throw 'Unknown file';
+  }
+
+  return new Promise((resolve, reject) => {
+    gm(stream).size({ bufferStream: true }, function (err, val) {
+      if (err) {
+        reject(err)
+      } else {
+        let result = Object.create(this);
+        result.origin_width = val.width;
+        result.origin_height = val.height;
+        result.zoom = zoom;
+        resolve(result);
+      }
+    });
+  });
+}
+
+module.exports = exports = {
+  runExtnames,
+  init,
+  extnameCheck
+};

+ 83 - 0
package-lock.json

@@ -0,0 +1,83 @@
+{
+  "name": "imgminify",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "array-parallel": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npm.taobao.org/array-parallel/download/array-parallel-0.1.3.tgz",
+      "integrity": "sha1-j3hTCJJu1apHjEfmTRszS2wMlH0="
+    },
+    "array-series": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npm.taobao.org/array-series/download/array-series-0.1.5.tgz",
+      "integrity": "sha1-3103v8XC7wdV4qpPkv6ufUtaly8="
+    },
+    "cross-spawn": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-4.0.2.tgz",
+      "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=",
+      "requires": {
+        "lru-cache": "^4.0.1",
+        "which": "^1.2.9"
+      }
+    },
+    "debug": {
+      "version": "3.2.6",
+      "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz",
+      "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=",
+      "requires": {
+        "ms": "^2.1.1"
+      }
+    },
+    "gm": {
+      "version": "1.23.1",
+      "resolved": "https://registry.npm.taobao.org/gm/download/gm-1.23.1.tgz",
+      "integrity": "sha1-Lt7rlYCE0PjqeYjl2ZWxx9/BR3c=",
+      "requires": {
+        "array-parallel": "~0.1.3",
+        "array-series": "~0.1.5",
+        "cross-spawn": "^4.0.0",
+        "debug": "^3.1.0"
+      }
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+    },
+    "lru-cache": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.5.tgz",
+      "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=",
+      "requires": {
+        "pseudomap": "^1.0.2",
+        "yallist": "^2.1.2"
+      }
+    },
+    "ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz",
+      "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
+    },
+    "pseudomap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz",
+      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+    },
+    "which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npm.taobao.org/which/download/which-1.3.1.tgz?cache=0&sync_timestamp=1574116720213&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwhich%2Fdownload%2Fwhich-1.3.1.tgz",
+      "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=",
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "yallist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz",
+      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+    }
+  }
+}

+ 14 - 0
package.json

@@ -0,0 +1,14 @@
+{
+  "name": "imgminify",
+  "version": "1.0.0",
+  "description": "",
+  "main": "main.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "gm": "^1.23.1"
+  }
+}