亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

使用 Node.js 實現圖片的動態裁切及算法實例代碼詳解

2024-05-06 16:46:15
字體:
來源:轉載
供稿:網友

背景&概覽

目前常見的圖床服務都會有圖片動態裁切的功能,主要的應用場景用以為各種終端和業務形態輸出合適尺寸的圖片。

一張動輒以 MB 為計量單位的原始大圖,通常不會只設置一下顯示尺寸就直接輸出到終端中,因為體積太大加載體驗會很差,除了影響加載速度還會增加終端設備的內存占用。所以要想在各種終端下都能保證圖片質量的同時又確保輸出合適的尺寸,那么此時就需要根據圖片 URL 來對原始圖片進行裁切,然后動態生成并輸出一張新的圖片。

URL 的設計

圖片 URL 需要包含圖片 id、尺寸、質量等信息。有兩種類型的圖片 URL,分別是原圖 URL 和帶動態裁切信息的 URL。

// 原圖 URLhttp://example.com/$imgId// 帶裁切信息的圖片 URLhttp://example.com/$cropType/$width_$height_$quality/$imgId

來分析一下上面 URL 中的變量:

  • $imgId
  • $cropType
  • $width
  • $height
  • $quality

那么一張圖片 id 為 4b2d4edcc1f82452 的原圖 URL 應該是:

http://example.com/4b2d4edcc1f82452.jpg

如果想要一張該圖 800×600 的版本,裁切的 URL 大致是下面這樣的:

http://example.com/es/800_600_/4b2d4edcc1f82452.jpg

裁切算法

該來說說以上 URL 背后的算法了。在 Node.js 中可以使用著名的圖片裁切庫 GM ,該庫是基于 imagemagick 和 graphicsmagick 底層庫的封裝。

最常見的裁切算法是等比例裁切,等比裁切的算法需要至少給出裁切目標圖片的寬度和高度的其中一個,如果圖片限寬就給出寬度,限高就給出高度,如果兩個參數都有,就需要確保裁切的目標寬高相對于原始的寬高是按比例計算的,否則裁切的結果就會出現拉伸。

var gm = require('gm');// 裁切的最小尺寸var minSize = 48;var defaultQuality = 90;/** * 等比例縮放 equal scaling * @param { String } 原文件路徑 * @param { String } 新文件路徑 * @param { String } 縮放規則 * @return { promise } */var es = function(src, dest, rules) {  return new Promise(function(resolve, reject) {    // 900_600_90 => 寬度900/高度600/品質90    rules = rules.split('_');    if (rules.length !== 3) {      return reject(new Error('Resize rules invalid'));    }    // 解析裁切的目標寬高    let resizeWidth = parseInt(rules[0]);    let resizeHeight = parseInt(rules[1]);    let quality = parseInt(rules[2]) || defaultQuality;    const readStream = fs.createReadStream(src);    const writeStream = fs.createWriteStream(dest);    gm(readStream)      .size({        bufferStream: true      }, function(err, size) {        if (err) {          return reject(err);        }        const origWidth = size.width;        const origHeight = size.height;        let resizeResult;        // 縮放的寬度和高度做最大最小值限制        if (resizeWidth) {          if (resizeWidth > origWidth * 1.5) {            resizeWidth = Math.floor(origWidth * 1.5);          }          else if (resizeWidth < minSize) {            resizeWidth = minSize;          }        }        if (resizeHeight) {          if (resizeHeight > origHeight * 1.5) {            resizeHeight = Math.floor(origHeight * 1.5);          }          else if (resizeHeight < minSize) {            resizeHeight = minSize;          }        }        resizeResult = this.resize(resizeWidth, resizeHeight);        resizeResult          .quality(quality)          .interlace('line') // 使用逐行掃描方式          .unsharp(2, 0.5, 0.5, 0)          .stream()          .on('end', resolve)          .pipe(writeStream);      });  });};

說說幾個重要的 API:

quality 設置圖片的質量,GM 圖片質量范圍是 0-100,默認的質量是 75。
interlace 用于設置圖片在顯示器上加載時的顯示方式,當然顯示方式本身還要受圖片本身的影響。
unsharp 用來設置圖片的銳度,將一張大圖縮放成一張小圖時,會損失很多像素,需要適當的增加圖片銳度來保證圖片的質量。關于 unsharp 的使用,詳見 Using ImageMagick to make sharp web-sized photographs 。
等比例裁切嚴格來說實際上還只是對圖片進行縮放,并未動用圖片裁切的 API。

還有一種比較常見的裁切方式,會先將圖片等比例縮放后再從中心裁切,裁切出來的圖片是一個正方形,這樣能盡可能保證圖片的內容。

/* * 等比例縮放后從中心裁切 equal scaling crop center(正方形裁切) * @param { String } 原文件路徑 * @param { String } 新文件路徑 * @param { String } 縮放規則 * @return { promise } */var escc = function(src, dest, rules) {  return new Promise(function(resolve, reject) {  // 600_90 => 寬度600/高度600/品質90    rules = rules.split('_');    if (rules.length !== 2) {      return reject(new Error('Resize rules invalid'));    }    let cropSize = parseInt(rules[0]);    let quality = parseInt(rules[1]) || defaultQuality;    const readStream = fs.createReadStream(src);    const writeStream = fs.createWriteStream(dest);    if (!cropSize) {      reject(new Error('Crop params invalid'));      return;    }    gm(readStream)      .size({        bufferStream: true      }, function(err, size) {        if (err) {          reject(err);          return;        }        const origWidth = size.width;        const origHeight = size.height;        let cropX = 0;        let cropY = 0;        let resizeWidth;        let resizeHeight;        let resizeResult;        // 裁切的寬度和高度做最大最小值限制        if (cropSize > origWidth) {          cropSize = origWidth;        }        else if (cropSize > origHeight) {          cropSize = origHeight;        }        else if (cropSize < minSize) {          cropSize = minSize;        }        // 先計算出等比縮放的尺寸,然后再根據此尺寸計算出裁切位置        if (origWidth > origHeight) {          resizeWidth = cropSize / origHeight * origWidth;          resizeHeight = cropSize;          cropX = Math.floor((resizeWidth - cropSize) / 2);          cropY = 0;        }        else {          resizeHeight = cropSize / origWidth * origHeight;          resizeWidth = cropSize;          cropX = 0;          cropY = Math.floor((resizeHeight - cropSize) / 2);        }        resizeResult = this.resize(resizeWidth, resizeHeight);        resizeResult          .quality(quality)          .interlace('line') // 使用逐行掃描方式          .crop(cropSize, cropSize, cropX, cropY)          .unsharp(2, 0.5, 0.5, 0)          .stream()          .on('end', resolve)          .pipe(writeStream);      });  });};

上面的 crop 就是對圖片進行裁切。當然除了中心裁切,還能延伸出頂部裁切,底部裁切等,相對來說使用場景要少很多。

結語

在服務的實際應用中,還會做一些優化,比如對服務的接口做一些安全限制,確保該接口不會被刷,裁切本身是比較消耗資源的操作。由于裁切操作比較耗資源,那么相同的尺寸應該保證只有一次裁切操作,這樣只有第一次請求裁切圖片才會真正有裁切操作,后續的訪問就直接讀取原來就裁切好的實體文件即可。

以上所述是小編給大家介紹的使用 Node.js 實現圖片的動態裁切及算法實例代碼詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VeVb武林網網站的支持!


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成人一区二区三区电影| 北条麻妃在线一区二区| 国产精品18久久久久久麻辣| 欧美激情第6页| 国产精品久久久久一区二区| 91在线观看免费| 欧美成人午夜免费视在线看片| 岛国av一区二区三区| 亚洲精品国产精品乱码不99按摩| 欧美综合一区第一页| 91精品视频免费看| 亚洲第一免费网站| 91精品国产成人www| 欧美日韩国产丝袜另类| 97在线视频国产| 国产精品伦子伦免费视频| 久久精品视频va| 国产精品专区h在线观看| 亚洲综合视频1区| 国产精品久久久久久久久久小说| 亚洲18私人小影院| 69av在线播放| 欧美极品第一页| 国产精品视频免费观看www| 中文字幕欧美在线| 欧美成年人视频网站| 日韩中文字幕国产精品| 欧美孕妇孕交黑巨大网站| 欧美大学生性色视频| 国产精国产精品| 久久九九免费视频| 97人洗澡人人免费公开视频碰碰碰| 欧美极品少妇全裸体| 国内精品视频久久| 久久视频在线看| 亚洲精品第一国产综合精品| 亚洲国产日韩一区| 91免费电影网站| 精品中文字幕乱| 俺也去精品视频在线观看| 精品成人国产在线观看男人呻吟| 亚洲第一视频网| 国产精品自拍视频| 亚洲黄色成人网| 日韩成人xxxx| 欧美性视频网站| 国产又爽又黄的激情精品视频| 91在线视频九色| 亚洲精品国产福利| 国产视频久久久久| 国产精品美女www爽爽爽视频| 国产精品福利小视频| 国产亚洲一区二区在线| 日韩综合中文字幕| 亚洲第一精品久久忘忧草社区| 中文日韩在线视频| 日韩在线观看免费av| 日韩欧美国产黄色| 中文字幕日韩欧美在线| 日韩精品在线观看视频| 国产午夜精品美女视频明星a级| 国产成人在线精品| 国产精品igao视频| 国产精品久久不能| 色综合五月天导航| 国产亚洲精品久久久久动| 精品中文字幕久久久久久| 日韩中文字幕免费视频| 亚洲欧美日韩第一区| 欧美日本国产在线| 亚洲国产天堂久久国产91| 精品亚洲永久免费精品| 91久久久久久久久久久| 九九视频直播综合网| 亚洲精品欧美日韩| 精品露脸国产偷人在视频| 中文字幕亚洲欧美日韩2019| 欧美高清理论片| 8090理伦午夜在线电影| 亚洲精品一区av在线播放| 亚洲福利视频免费观看| 一区二区三区视频观看| 精品国产一区二区三区久久久| 欧美高清视频免费观看| 久久久在线免费观看| 国产偷国产偷亚洲清高网站| 日韩av在线免费播放| 久久久久久成人精品| 浅井舞香一区二区| 日日狠狠久久偷偷四色综合免费| 色婷婷av一区二区三区久久| 91视频-88av| 中文字幕在线成人| 欧美视频中文在线看| 一本一本久久a久久精品牛牛影视| 久久精品中文字幕一区| 日韩欧美亚洲一二三区| 国产精品一区二区性色av| 欧美精品久久一区二区| 亚洲人成五月天| 久久久久久12| 久久99久久亚洲国产| 少妇激情综合网| 欧美插天视频在线播放| www国产亚洲精品久久网站| 精品高清美女精品国产区| 久久久精品视频成人| www欧美日韩| 91麻豆国产语对白在线观看| 国产一区二区三区精品久久久| 亚洲色图日韩av| 亚洲无限乱码一二三四麻| 午夜欧美大片免费观看| 一区二区在线视频播放| 亚洲a中文字幕| 亚洲欧美日韩视频一区| 成人高h视频在线| 久久久久久久久国产精品| 91精品国产乱码久久久久久久久| 欧美激情va永久在线播放| 国内精品视频久久| 亚洲va欧美va国产综合剧情| 久久久精品网站| 亚洲free性xxxx护士hd| 久久久亚洲影院| 国产精品久久久久av免费| 欧美日韩国产在线播放| 久久久久久久999精品视频| 欧美日韩高清在线观看| 久久精彩免费视频| 欧美日本国产在线| 国产91精品久久久| 亚洲一区二区自拍| 日韩精品在线免费观看| 成人在线激情视频| 成人黄色在线播放| 欧美成人激情在线| 亚洲激情视频网站| 欧美精品18videos性欧| 久久偷看各类女兵18女厕嘘嘘| 夜夜嗨av一区二区三区四区| 久久97久久97精品免视看| 国产日韩一区在线| 2023亚洲男人天堂| 欧美三级欧美成人高清www| 亚洲人成亚洲人成在线观看| 国产拍精品一二三| 大伊人狠狠躁夜夜躁av一区| 亚洲福利在线看| 亚洲精品99久久久久| 在线播放日韩欧美| 亚洲欧美国产精品| 亚洲国产三级网| 九九热最新视频//这里只有精品| 丝袜美腿亚洲一区二区| 国产精品一区久久| 亚洲最新av在线网站| 日韩在线视频观看正片免费网站| 亚洲精品视频免费| 成人免费看黄网站| 欧美黑人一区二区三区| 久久亚洲国产成人| 国产亚洲精品久久久久久| 高清欧美性猛交xxxx|