食用源碼:image-size

image-size 是什麼

一個Node模塊,用於獲取任何圖像文件的尺寸。css

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

源碼解析

首先整理出一份流程圖來分析 一圖勝萬語: git

吸收到的養分

  1. nodejs 的包加載機制github

    bin/image-size.jsweb

    var imageSize = require('..');
    複製代碼

    package.jsonchrome

    "main": "lib/index.js"
    複製代碼

    require('..') 具體加載了哪一個文件?json

    nodejs 的包加載機制會把 '..' 解析成 '../',而後會嘗試去 package.json 內取 main 字段的值,做爲文件加載的入口,因此這裏加載了 lib/index.js。api

  2. 檢測用戶的輸入bash

    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. 大小端
相關文章
相關標籤/搜索