食用源码:image-size

image-size 是什么

一个Node模块,用于获取任何图像文件的尺寸。

git:https://github.com/image-size/image-size

源码解析

首先整理出一份流程图来分析 一图胜万语:

吸取到的营养

  1. nodejs 的包加载机制

    bin/image-size.js

    var imageSize = require('..');
    复制代码

    package.json

        "main": "lib/index.js"
    复制代码

    require('..') 具体加载了哪个文件?

    nodejs 的包加载机制会把 '..' 解析成 '../',然后会尝试去 package.json 内取 main 字段的值,作为文件加载的入口,所以这里加载了 lib/index.js。

  2. 检测用户的输入

        var files = process.argv.slice(2);
        if (!files.length) {
          console.error('Usage: image-size image1 [image2] [image3] ...');
          process.exit(-1);
        }
    复制代码

    通过 process.argv.slice(2) 获取用户的输入,并且在用户没有输入的情况下给予提示帮助

  3. 检测当前文件是否存在

        fs.existsSync(path.resolve(image)
    复制代码

    先把图片的路径转换为绝对路径 然后调用 fs.existsSync 方法。

    虽然 fs.exists() 是废弃的,但 fs.existsSync() 不是。--nodejs 文档

  4. 读取文件转换为 buffer

    • 异步转换
        function asyncFileToBuffer (filepath, callback) {
          // open the file in read only mode
          fs.open(filepath, 'r', function (err, descriptor) {
            if (err) { return callback(err); }
            fs.fstat(descriptor, function (err, stats) {
              if (err) { return callback(err); }
              var size = stats.size;
              if (size <= 0) {
                return callback(new Error('File size is not greater than 0 —— ' + filepath));
              }
              var bufferSize = Math.min(size, MaxBufferSize);
              var buffer = new Buffer(bufferSize);
              // read first buffer block from the file, asynchronously
              fs.read(descriptor, buffer, 0, bufferSize, 0, function (err) {
                if (err) { return callback(err); }
                // close the file, we are done
                fs.close(descriptor, function (err) {
                  callback(err, buffer);
                });
              });
            });
          });
        }
    复制代码
    • 同步转换
        function syncFileToBuffer (filepath) {
          // read from the file, synchronously
          var descriptor = fs.openSync(filepath, 'r');
          var size = fs.fstatSync(descriptor).size;
          var bufferSize = Math.min(size, MaxBufferSize);
          var buffer = new Buffer(bufferSize);
          fs.readSync(descriptor, buffer, 0, bufferSize, 0);
          fs.closeSync(descriptor);
          return buffer;
        }
    复制代码
    1. 先打开文件 fs.open
    2. 获取文件信息 fs.fstat
    3. 满足条件的话,读取文件 fs.read
    4. 成功后,关闭文件流 fs.close

    这里作者限制了 buffer 的大小,不然的话使用 fs.createReadStream 更为方便些。

  5. 检测图片的类型

    • 在 lib/types 文件夹内有着所有格式的扩展类,并且在 lib/types.js 文件内统一加载导入

      var typeHandlers = {
        bmp: require('./types/bmp'),
        cur: require('./types/cur'),
        dds: require('./types/dds'),
        gif: require('./types/gif'),
        icns: require('./types/icns'),
        ico: require('./types/ico'),
        jpg: require('./types/jpg'),
        png: require('./types/png'),
        psd: require('./types/psd'),
        svg: require('./types/svg'),
        tiff: require('./types/tiff'),
        webp: require('./types/webp'),
      };
      复制代码

      可以用一个类专门做多文件导入之类的处理。

    • 所有的格式扩展类导出的方法名都是 'detect' 和 'calculate'

      lib/detector.js

          module.exports = function (buffer, filepath) {
            var type, result;
            for (type in typeHandlers) {
              result = typeHandlers[type].detect(buffer, filepath);
              if (result) {
                return type;
              }
            }
          };
      复制代码

      统一了格式扩展类导出的方法名,方便扩展。以后再扩展不同格式的图片时,只需要增加对应的格式扩展类,而无需改变当前的代码。(对修改关闭 对扩展开放 --ocp原则)

  6. 获取图片的信息

    不同的图片格式获取信息的方式不一致,这里涉及的知识有点深,这里只是记录下思路,具体需要时在详细的查询。

    • 基于 buffer 读取字节,基于格式说明,读取出相对应的二进制数据信息。

    记录大端读取和小端读取的区别:

    const buf = Buffer.from([0x12, 0x34, 0x56]);
    console.log(buf.readUInt16BE(0).toString(16));
    // Prints: 1234         大端在右
    console.log(buf.readUInt16LE(0).toString(16));
    // Prints: 3412         小端在右
    复制代码
  7. console.log 输出带颜色的字体

    在最后返回结果的时候,宽和高数据都是绿色的。发现 console.log 原来是可以设置 css 样式的。

    例如(可以在 chrome 开发者模式下输入看下样式)

         console.log( '%c你好', 'color:red' )
    复制代码

    %c 后面的所有字体可以作用写好的 css样式。

        console.log( '%c你好%c今天学习了吗', 'color:red' , 'color:yellow')
    复制代码

    多个字体样式的使用

总结

阅读源码可以开阔自己的视野,也能更好的学习 nodejs。先从简单的模块入手,慢慢在增加难度,学习作者的思路和套路。

参考

  1. nodejs文档
  2. 大小端

转载于:https://juejin.im/post/5b57fb15e51d4535a65ad4df

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值