Nodejs Sharp 簡明教程

Nodejs Sharp 簡明教程

簡介

Node.js 有一個可用于處理圖像的庫生態(tài)系統(tǒng)符衔,例如sharp奈辰、jimp 和gm 模塊。本文將重點介紹sharp模塊罗售。 Sharp 是一個流行的 Node.js 圖像處理庫辜窑,支持各種圖像文件格式,例如 JPEG寨躁、PNG穆碎、GIF、WebP职恳、AVIF所禀、SVG 和 TIFF。

在本教程中放钦,您將使用Sharp 讀取圖像并提取其元數(shù)據(jù)色徘、調(diào)整大小、更改圖像格式和壓縮圖像操禀。然后褂策,您將裁剪、灰度化颓屑、旋轉(zhuǎn)和模糊圖像辙培。最后,您將合成圖像邢锯,并在圖像上添加文本。在本教程結(jié)束時搀别,您將很好地了解如何在 Node.js 中處理圖像丹擎。

準(zhǔn)備

開始教程之前您需要:

  • 在您的系統(tǒng)上安裝 Node.js 和 npm。
  • 編寫和運行 Node.js 程序的基本知識。
  • 對 JavaScript 異步編程的基本理解蒂培。 按照了解 JavaScript 中的事件循環(huán)再愈、回調(diào)、承諾和 Async/Await 來查看異步編程护戳。

第1步 - 設(shè)置項目目錄并下載圖像

在開始編寫代碼之前翎冲,您需要創(chuàng)建包含本文中將使用的代碼和圖像的目錄。

打開終端并使用 mkdir 命令為項目創(chuàng)建目錄:

mkdir process_images

使用 cd 命令進入新創(chuàng)建的目錄:

cd process_images

使用 npm init 命令創(chuàng)建 package.json 文件以跟蹤項目依賴項:

npm init -y

-y 選項告訴 npm 創(chuàng)建默認(rèn)的 package.json 文件媳荒。

接下來抗悍,安裝sharp作為依賴:

npm install sharp

您將在本教程中使用以下三個圖像:


image.png

image.png

image.png

在本頁面右鍵保存圖片即可。

設(shè)置項目目錄和依賴項后钳枕,您現(xiàn)在可以開始處理圖像了缴渊。

第2步 - 讀取圖像并輸出元數(shù)據(jù)

在本節(jié)中,您將編寫代碼來讀取圖像并提取其元數(shù)據(jù)鱼炒。圖像元數(shù)據(jù)是嵌入到圖像中的文本衔沼,其中包括有關(guān)圖像的信息,例如其類型昔瞧、寬度和高度指蚁。

要提取元數(shù)據(jù),您將首先導(dǎo)入sharp 模塊自晰,創(chuàng)建一個sharp實例凝化,并將圖像路徑作為參數(shù)傳遞。之后缀磕,您將metadata()方法鏈接到實例以提取元數(shù)據(jù)并將其登錄到控制臺缘圈。

為此請在文本編輯器中創(chuàng)建并打開readImage.js文件。接下來袜蚕,需要在文件頂部引用sharp:

const sharp = require("sharp");

sharp 是一個基于promise的圖像處理模塊糟把。
當(dāng)您創(chuàng)建一個 sharp 的實例時,它會返回一個promise牲剃。
您可以使用 then 方法或使用具有更清晰語法的 async/await 來解析承諾遣疯。

要使用 async/await 語法,您需要通過將 async 關(guān)鍵字放在函數(shù)的開頭來創(chuàng)建一個異步函數(shù)凿傅。這將允許您在函數(shù)內(nèi)使用 await 關(guān)鍵字來解析讀取圖像時返回的承諾缠犀。

在您的 readImage.js 文件中,定義一個異步函數(shù) getMetadata() 來讀取圖像聪舒、提取其元數(shù)據(jù)并將其登錄到控制臺:

const sharp = require("sharp");

async function getMetadata() {
  const metadata = await sharp("sammy.png").metadata();
  console.log(metadata);
}

在function之前加上 async 關(guān)鍵字辨液,getMetadata()就變成一個異步函數(shù)。這使您可以在函數(shù)中使用 await 語法箱残。getMetadata() 函數(shù)將讀取圖像并返回一個帶有元數(shù)據(jù)的對象滔迈。

在函數(shù)體中止吁,您通過調(diào)用sharp() 來讀取圖像,該函數(shù)將圖像路徑作為參數(shù)燎悍,這里是sammy.png敬惦。

除了獲取圖像路徑外,sharp() 還可以讀取存儲在 Buffer谈山、Uint8Array 或 Uint8ClampedArray 中的圖像數(shù)據(jù)俄删,前提是圖像是 JPEG、PNG奏路、GIF畴椰、WebP、AVIF思劳、SVG 或 TIFF迅矛。

現(xiàn)在,當(dāng)您使用sharp() 讀取圖像時潜叛,它會創(chuàng)建一個sharp實例秽褒。然后將sharp模塊的metadata()方法鏈接到實例。該方法返回一個包含圖像元數(shù)據(jù)的對象威兜,您將其存儲在元數(shù)據(jù)變量中并使用console.log()記錄其內(nèi)容销斟。

您的程序現(xiàn)在可以讀取圖像并返回其元數(shù)據(jù)。但是椒舵,如果程序在執(zhí)行過程中拋出錯誤暖呕,就會崩潰女轿。為了解決這個問題,您需要在錯誤發(fā)生時捕獲它們。

為此诱告,需要將getMetadata()函數(shù)中的代碼包裝在try...catch塊中:

const sharp = require("sharp");

async function getMetadata() {
  try {
    const metadata = await sharp("sammy.png").metadata();
    console.log(metadata);
  } catch (error) {
    console.log(`An error occurred during processing: ${error}`);
  }
}

try塊中臼疫,您讀取圖像秘噪、提取并打印其元數(shù)據(jù)厦酬。在此過程中發(fā)生錯誤時,執(zhí)行會跳到catch部分并記錄錯誤以防止程序崩潰炬灭。

保存文件醋粟,并執(zhí)行下面的node命令:

node readImage.js

您應(yīng)該會看到與此類似的輸出:

{
  format: 'png',
  width: 750,
  height: 483,
  space: 'srgb',
  channels: 3,
  depth: 'uchar',
  density: 72,
  isProgressive: false,
  hasProfile: false,
  hasAlpha: false
}

現(xiàn)在您已經(jīng)讀取了圖像并提取了其元數(shù)據(jù),接下來將學(xué)習(xí)調(diào)整圖像大小重归、更改其格式并對其進行壓縮米愿。

第3步 — 調(diào)整大小、更改圖像格式和壓縮圖像

調(diào)整大小是更改圖像尺寸鼻吮,而不從中剪切任何內(nèi)容的過程育苟,這會影響圖像文件大小。在本節(jié)中椎木,您將調(diào)整圖像大小宙搬、更改其圖像類型并壓縮圖像笨腥。圖像壓縮是在不降低質(zhì)量的情況下減小圖像文件大小的過程。

首先勇垛,您將從sharp實例中resize()方法來調(diào)整圖像大小,并將其保存在項目目錄中士鸥。其次闲孤,您將使用format()方法調(diào)整大小的圖像以將其格式從png更改為jpeg。 此外烤礁,還需要向format()方法傳遞一個參數(shù)以壓縮圖像并將其保存到目錄中讼积。

在文本編輯器中創(chuàng)建并打開resizeImage.js文件,添加以下代碼以將圖像大小調(diào)整為寬150px脚仔,高97px:

const sharp = require("sharp");

async function resizeImage() {
  try {
    await sharp("sammy.png")
      .resize({
        width: 150,
        height: 97
      })
      .toFile("sammy-resized.png");
  } catch (error) {
    console.log(error);
  }
}

resizeImage();

resizeImage()函數(shù)調(diào)用sharp實例的resize()方法勤众。該方法將一個對象作為參數(shù)。在這對象中可以使用 width 和 height 屬性設(shè)置所需的圖像尺寸鲤脏。將寬度設(shè)置為150们颜,將高度設(shè)置為97 ,將使圖像寬150像素猎醇,高97像素窥突。

調(diào)整圖像大小后,調(diào)用sharp實例的toFile()方法硫嘶,該方法將圖像路徑作為參數(shù)阻问。將sammy-resized.png作為參數(shù)傳遞將使用該名稱將圖像文件保存在程序的工作目錄中。

現(xiàn)在沦疾,保存并退出文件称近。 在終端中運行你的程序:

node resizeImage.js

您不會得到任何輸出,但您應(yīng)該會在項目目錄中看到一個名為 sammy-resized.png 的新圖像文件哮塞。

image.png

現(xiàn)在您已學(xué)會調(diào)整圖像大小刨秆,接下來您將圖像格式從png轉(zhuǎn)換為jpeg,壓縮圖像彻桃,并將其保存在工作目錄中坛善。 為此,您將使用toFormat()方法邻眷,該方法將在resize()方法之后調(diào)用眠屎。

const sharp = require("sharp");

async function resizeImage() {
  try {
    await sharp("sammy.png")
      .resize({
        width: 150,
        height: 97
      })
      .toFormat("jpeg", { mozjpeg: true })
      .toFile("sammy-resized-compressed.jpeg");
  } catch (error) {
    console.log(error);
  }
}

resizeImage();

resizeImage()函數(shù)中,您使用sharp模塊的toFormat()方法來更改圖像格式并對其進行壓縮肆饶。 toFormat()方法的第一個參數(shù)是一個字符串改衩,其中包含要將圖像轉(zhuǎn)換為的圖像格式。第二個參數(shù)是一個可選對象驯镊,包含增強和壓縮圖像的輸出選項葫督。

要壓縮圖像竭鞍,您需要傳遞一個包含布爾值的mozjpeg屬性。當(dāng)您將其設(shè)置為 true 時橄镜,sharp 使用 mozjpeg 默認(rèn)值來壓縮圖像而不犧牲質(zhì)量偎快。對象還可以有更多的選擇;有關(guān)更多詳細信息洽胶,請參閱官方文檔晒夹。

注意:關(guān)于 toFormat() 方法的第二個參數(shù),每種圖像格式都采用具有不同屬性的對象姊氓。 例如丐怯,僅在 JPEG 圖像上接受 mozjpeg 屬性。但是翔横,其他圖像格式具有等效選項读跷,例如qualitycompressionlossless禾唁。 請務(wù)必參閱官方文檔以了解您正在壓縮的圖像格式可接受的選項類型效览。

接下來,您向toFile()方法傳遞一個不同的文件名蟀俊,以將壓縮圖像保存為sammy-resized-compressed.jpeg钦铺。

現(xiàn)在,保存并退出文件肢预,然后使用以下命令運行您的代碼:

node resizeImage.js

您不會收到任何輸出矛洞,但圖像文件 sammy-resized-compressed.jpeg 會保存在您的項目目錄中。

在本地機器上打開圖像烫映,您將看到以下圖像:

image.png

在您的終端中沼本,運行 du 命令可檢查 sammy.png 的文件大小是否壓縮成功:

du -h sammy.png

-h 選項生成人類可讀的輸出,顯示文件大卸Ч怠(以千字節(jié)抽兆、兆字節(jié)等為單位)。

運行該命令后族淮,您應(yīng)該會看到類似于以下內(nèi)容的輸出:

120K    sammy.png

輸出顯示原始圖像為 120KB辫红。

接下來,檢查 sammy-resized.png 的文件大凶@薄:

du -h sammy-resized.png

運行該命令后贴妻,您將看到以下輸出:

8.0K sammy-resized.png

sammy-resized.png 從 120KB 減少到 8KB。 這表明調(diào)整大小操作會影響文件大小蝙斜。

現(xiàn)在名惩,檢查 sammy-resized-compressed.jpeg 的文件大小:

du -h sammy-resized-compressed.jpeg

運行該命令后孕荠,您將看到以下輸出:

4.0K sammy-resized-compressed.jpeg

sammy-resized-compressed.jpeg 現(xiàn)在從 8KB 減少到 4KB娩鹉,節(jié)省了 4KB攻谁,表明壓縮有效。

現(xiàn)在您已學(xué)會調(diào)整圖像大小弯予、更改其格式并對其進行壓縮戚宦,您將對圖像進行裁剪和灰度處理。

第4步 - 裁剪圖像并將其轉(zhuǎn)換為灰度

在這一步中熙涤,您將裁剪圖像阁苞,并將其轉(zhuǎn)換為灰度。裁剪是從圖像中去除不需要的區(qū)域的過程祠挫。您將使用extend()方法裁剪 sammy.png 圖像。之后悼沿,您會將grayscale()方法鏈接到裁剪后的圖像實例并將其轉(zhuǎn)換為灰度等舔。

在文本編輯器中創(chuàng)建并打開cropImage.js,添加以下代碼以裁剪圖像:

const sharp = require("sharp");

async function cropImage() {
  try {
    await sharp("sammy.png")
      .extract({ width: 500, height: 330, left: 120, top: 70  })
      .toFile("sammy-cropped.png");
  } catch (error) {
    console.log(error);
  }
}

cropImage();

cropImage() 函數(shù)是一個異步函數(shù)糟趾,它讀取圖像并返回裁剪后的圖像慌植。在 try 塊中,sharp將讀取圖像义郑,然后調(diào)用sharp實例的extract() 方法采用具有以下屬性的對象:

  • width:要裁剪的區(qū)域的寬度蝶柿。
  • height:要裁剪的區(qū)域的高度。
  • top:要裁剪的區(qū)域的垂直位置非驮。
  • left:要裁剪的區(qū)域的水平位置交汤。

當(dāng)您將寬度設(shè)置為500,并將高度設(shè)置為330時劫笙,想象一下Sharp在您要裁剪的圖像頂部創(chuàng)建一個透明框芙扎。適合框的圖像的任何部分將保留,其余部分將被剪切:

image.png

top 和 left 屬性控制框的位置填大。當(dāng)您將 left 設(shè)置為 120 時戒洼,框位于距圖像左邊緣 120px 的位置,將 top 設(shè)置為 70 將框定位在距圖像頂部邊緣 70px 的位置允华。

適合框的圖像區(qū)域?qū)⒈惶崛〕鰜聿⒆鳛閱为毜膱D像保存到 sammy-cropped.png 中圈浇。

保存并退出文件。在終端中運行程序:

node cropImage.js

圖像 sammy-cropped.png 將保存在您的項目目錄中靴寂。在本地機器上打開圖像磷蜀。您應(yīng)該看到圖像被裁剪:

image.png

現(xiàn)在您裁剪了圖像,您將把圖像轉(zhuǎn)換為灰度榨汤。為此蠕搜,您將調(diào)用grayscale方法。

const sharp = require("sharp");

async function cropImage() {
  try {
    await sharp("sammy.png")
      .extract({ width: 500, height: 330, left: 120, top: 70 })
      .grayscale()
      .toFile("sammy-cropped-grayscale.png");
  } catch (error) {
    console.log(error);
  }
}

cropImage();

cropImage() 函數(shù)通過調(diào)用sharp實例的grayscale()方法收壕,將裁剪后的圖像轉(zhuǎn)換為灰度妓灌。然后將圖像保存在項目目錄中作為sammy-cropped-grayscale.png轨蛤。

在終端中運行您的代碼:

node cropImage.js

在本地機器上打開 sammy-cropped-grayscale.png。 您現(xiàn)在應(yīng)該可以看到灰度圖像:

image.png

現(xiàn)在您已學(xué)會裁剪和提取了圖像虫埂,您將使用旋轉(zhuǎn)和模糊處理它祥山。

第5步 - 旋轉(zhuǎn)和模糊圖像

在這一步中,您將以 33度角旋轉(zhuǎn)sammy.png圖片掉伏。您還將在旋轉(zhuǎn)后的圖像上應(yīng)用高斯模糊缝呕。高斯模糊是一種使用高斯函數(shù)模糊圖像的技術(shù),它降低了圖像的噪聲水平和細節(jié)斧散。

在文本編輯器中創(chuàng)建一個 rotateImage.js 文件供常,編寫以下代碼塊以創(chuàng)建一個將 sammy.png 旋轉(zhuǎn)到 33 度角的函數(shù):

const sharp = require("sharp");

async function rotateImage() {
  try {
    await sharp("sammy.png")
      .rotate(33, { background: { r: 0, g: 0, b: 0, alpha: 0 } })
      .toFile("sammy-rotated.png");
  } catch (error) {
    console.log(error);
  }
}

rotateImage();

rotateImage() 函數(shù)是一個異步函數(shù),它讀取圖像并返回旋轉(zhuǎn)到33度角的圖像鸡捐。在該函數(shù)中栈暇,sharp實例的 rotate() 方法接受兩個參數(shù)。第一個參數(shù)是旋轉(zhuǎn)角度33度箍镜。默認(rèn)情況下源祈,sharp 將旋轉(zhuǎn)圖像的背景設(shè)為黑色。要移除黑色背景色迂,您需要傳遞一個對象作為第二個參數(shù)以使背景透明香缺。

該對象具有一個背景屬性,該屬性包含一個定義 RGBA 顏色模型的對象歇僧。 RGBA 代表紅色图张、綠色、藍色和 alpha馏慨。

r:控制紅色的強度埂淮。它接受 0-255 之間的整數(shù)值。0 表示不使用紅色写隶,255 表示紅色最高倔撞。
g:控制綠色的強度。它接受 0-255 之間的整數(shù)值慕趴。0 表示不使用綠色痪蝇,255 表示綠色最高。
b:控制藍色的強度冕房。它接受 0-255 之間的整數(shù)值躏啰。0 表示不使用藍色, 255 表示藍色最高。
alpha:控制由 r耙册、g 和 b 屬性定義的顏色的不透明度给僵。 0 或 0.0 使顏色透明,1 或 1.1 使顏色不透明。
要使 alpha 屬性起作用帝际,您必須確保設(shè)置 r蔓同、g、 b 的值蹲诀。將 r斑粱、g 、b 值設(shè)置為 0 會創(chuàng)建黑色脯爪。要創(chuàng)建透明背景则北,必須先定義顏色,然后可以將 alpha 設(shè)置為 0 使其透明痕慢。

現(xiàn)在尚揣,保存文件,在終端中運行你的腳本:

node rotateImage.js

檢查項目目錄中是否存在 sammy-rotated.png掖举。 在本地機器上打開它惑艇。

您應(yīng)該看到旋轉(zhuǎn)到 33 度角的圖像:

image.png

接下來,您將對旋轉(zhuǎn)后的圖像進行模糊處理拇泛。 您將通過調(diào)用blur()方法來實現(xiàn)這一點。

const sharp = require("sharp");

async function rotateImage() {
  try {
    await sharp("sammy.png")
      .rotate(33, { background: { r: 0, g: 0, b: 0, alpha: 0 } })
      .blur(4)
      .toFile("sammy-rotated-blurred.png");
  } catch (error) {
    console.log(error);
  }
}

rotateImage();

rotateImage() 函數(shù)讀取圖像思灌,旋轉(zhuǎn)俺叭,并對圖像應(yīng)用高斯模糊。它使用sharp模塊的blur()方法對圖像應(yīng)用高斯模糊泰偿。該方法接受一個 0.3-1000之間的參數(shù)熄守。把4傳遞給它,將應(yīng)用sigma值為4的高斯模糊耗跛。圖像模糊后保存模糊圖像裕照。

保存文件,然后在終端中運行腳本:

node rotateImage.js

運行腳本后调塌,在本地機器上打開 sammy-rotated-blurred.png 文件晋南。您應(yīng)該看到旋轉(zhuǎn)后的圖像變得模糊:

image.png

現(xiàn)在您已經(jīng)學(xué)會旋轉(zhuǎn)并模糊了圖像,您將在另一個圖像上合成一個圖像羔砾。

第6步 - 使用composite()合成圖像

圖像合成是將兩張或多張單獨的圖片組合在一起以創(chuàng)建單個圖像的過程负间。這樣做是為了創(chuàng)建從不同照片中借用最佳元素的效果。另一個常見的用例是為給圖像添加水印姜凄。

在本節(jié)中政溃,您將在 underwater.png 上合成 sammy-transparent.png。 這會產(chǎn)生一種鯊魚在海洋深處游泳的錯覺态秧。要合成圖像董虱,您需要將調(diào)用composite()方法。

在文本編輯器中創(chuàng)建并打開文件 compositeImage.js申鱼,編寫以下代碼:

const sharp = require("sharp");

async function compositeImages() {
  try {
    await sharp("underwater.png")
      .composite([
        {
          input: "sammy-transparent.png",
          top: 50,
          left: 50,
        },
      ])
      .toFile("sammy-underwater.png");
  } catch (error) {
    console.log(error);
  }
}

compositeImages()

compositeImages() 函數(shù)首先讀取underwater.png愤诱。接下來云头,調(diào)用composite()方法,該方法接受一個數(shù)組作為參數(shù)转锈。該數(shù)組包含一個讀取sammy-transparent.png圖像的對象盘寡。該對象具有以下屬性:

  • input:采用要在處理過的圖像上合成的圖像的路徑。它還接受 Buffer撮慨、Uint8Array 或 Uint8ClampedArray 作為輸入竿痰。
  • top:控制要合成的圖像的垂直位置。將 top 設(shè)置為 50 會使 sammy-transparent.png 圖像從underwater.png圖像的頂部邊緣偏移50px砌溺。
  • left:控制要在另一個圖像上合成的圖像的水平位置影涉。將 left 設(shè)置為 50 會使 sammy-transparent.pngunderwater.png 圖像的左邊緣偏移50px。

composite() 方法需要與處理后的圖像大小相似或更小的圖像规伐。

為了看到composite()方法正在做什么蟹倾,可以把它想象成創(chuàng)建一堆圖像。 sammy-transparent.png 圖像放置在 underwater.png 圖像之上:

image.png

top和left的值相對于underwater.png圖像定位sammy-transparent.png圖像猖闪。

保存文件鲜棠,運行以下代碼:

node compositeImages.js

在本地機器上打開sammy-underwater.png。您現(xiàn)在應(yīng)該看到sammy-transparent.png合成在underwater.png圖像上:

image.png

您現(xiàn)在已經(jīng)使用 composite() 方法合成了圖像培慌。 在下一步中豁陆,您將使用 composite() 方法向圖像添加文本。

第7步 - 在圖像上添加文本

在這一步中吵护,您將在圖像上書寫文本盒音。在撰寫本文時,sharp沒有向圖像添加文本的原生方式馅而。要添加文本祥诽,首先,您將編寫代碼以使用可縮放矢量圖形 (SVG) 繪制文本瓮恭。創(chuàng)建 SVG 圖像后雄坪,您將編寫代碼以使用復(fù)合方法將圖像與 sammy.png 圖像合成。

SVG 是一種基于 XML 的標(biāo)記語言偎血,用于為 Web 創(chuàng)建矢量圖形诸衔。您可以繪制文本或圓形、三角形等形狀颇玷,也可以繪制復(fù)雜的形狀笨农,例如插圖、徽標(biāo)等帖渠。使用生成 SVG 代碼的 inkscape 等圖形工具創(chuàng)建復(fù)雜的形狀谒亦。 SVG形狀可以渲染和縮放到任何大小而不會降低質(zhì)量。

在文本編輯器中創(chuàng)建并打開 addTextOnImage.js 文件,編寫以下代碼:

const sharp = require("sharp");

async function addTextOnImage() {
  try {
    const width = 750;
    const height = 483;
    const text = "Sammy the Shark";

    const svgImage = `
    <svg width="${width}" height="${height}">
    </svg>
    `;
  } catch (error) {
    console.log(error);
  }
}

addTextOnImage();

addTextOnImage() 函數(shù)定義了四個變量:width份招、height切揭、text 和 svgImage。 width 保存整數(shù)750锁摔,height 保存整數(shù)483廓旬。 text 保存字符串Sammy the Shark。 這是您將使用 SVG 繪制的文本谐腰。

svgImage 變量保存 svg 元素孕豹。 svg 元素有兩個屬性:width 和 height,它們插入您之前定義的寬度和高度變量十气。 svg 元素根據(jù)給定的寬度和高度創(chuàng)建一個透明的容器励背。

您為 svg 元素提供了 750 的寬度和 483 的高度,以便 SVG 圖像具有與 sammy.png 相同的大小砸西。 這將有助于使文本看起來以 sammy.png 圖像為中心叶眉。

接下來,您將繪制文本圖形芹枷。 添加突出顯示的代碼以在 SVG 容器上繪制 Sammy the Shark:

async function addTextOnImage() {
    ...
    const svg = `
    <svg width="${width}" height="${height}">
    <text x="50%" y="50%" text-anchor="middle" class="title">${text}</text>
    </svg>
    `;
  ....
}

SVG 文本元素有四個屬性:x衅疙、y、text-anchor 和 class鸳慈。 x 和 y 定義您在 SVG 容器上繪制的文本的位置炼蛤。 x 屬性水平放置文本,y 屬性垂直放置文本蝶涩。

將 x 設(shè)置為 50% 將在 x 軸上的容器中間繪制文本,將 y 設(shè)置為 50% 將文本定位在 SVG 圖像的 y 軸上的中間絮识。

文本錨將文本水平對齊绿聘。 將 text-anchor 設(shè)置為 middle 將使文本在您指定的 x 坐標(biāo)的中心對齊。

class 在文本元素上定義了一個類名次舌。 您將使用類名將 CSS 樣式應(yīng)用于文本元素熄攘。

${text} 插入存儲在 text 變量中的字符串 Sammy the Shark。 這是將在 SVG 圖像上繪制的文本彼念。

接下來挪圾,添加突出顯示的代碼以使用 CSS 設(shè)置文本樣式:

const svg = `
<svg width="${width}" height="${height}">
  <style>
  .title { fill: #001; font-size: 70px; font-weight: bold;}
  </style>
  <text x="50%" y="50%" text-anchor="middle" class="title">${text}</text>
</svg>
`;

在這段代碼中,fill 將文本顏色更改為黑色逐沙, font-size 更改字體大小哲思, font-weight 更改字體粗細。

至此吩案,您已經(jīng)編寫了使用 SVG 繪制文本 Sammy the Shark 所需的代碼棚赔。 接下來,您將 SVG 圖像保存為具有清晰的 png,以便您可以看到 SVG 如何繪制文本靠益。 完成后丧肴,您將使用 sammy.png 合成 SVG 圖像。

添加突出顯示的代碼以將 SVG 圖像保存為具有清晰的 png:

....
    const svgImage = `
    <svg width="${width}" height="${height}">
    ...
    </svg>
    `;
    const svgBuffer = Buffer.from(svgImage);
    const image = await sharp(svgBuffer).toFile("svg-image.png");
  } catch (error) {
    console.log(error);
  }
}

addTextOnImage();

Buffer.from() 從 SVG 圖像創(chuàng)建一個 Buffer 對象胧后。 緩沖區(qū)是內(nèi)存中存儲二進制數(shù)據(jù)的臨時空間芋浮。

創(chuàng)建緩沖區(qū)對象后,您可以使用緩沖區(qū)對象作為輸入創(chuàng)建一個清晰的實例壳快。 除了圖像路徑纸巷,sharp 還接受緩沖區(qū)、Uint9Array 或 Uint8ClampedArray濒憋。

最后何暇,在項目目錄中將 SVG 圖像保存為 svg-image.png。

這是完整的代碼:

const sharp = require("sharp");

async function addTextOnImage() {
  try {
    const width = 750;
    const height = 483;
    const text = "Sammy the Shark";

    const svgImage = `
    <svg width="${width}" height="${height}">
      <style>
      .title { fill: #001; font-size: 70px; font-weight: bold;}
      </style>
      <text x="50%" y="50%" text-anchor="middle" class="title">${text}</text>
    </svg>
    `;
    const svgBuffer = Buffer.from(svgImage);
    const image = await sharp(svgBuffer).toFile("svg-image.png");
  } catch (error) {
    console.log(error);
  }
}

addTextOnImage()

保存文件凛驮,并執(zhí)行以下命令:

node addTextOnImage.js

在本地機器上打開 svg-image.png裆站。 您現(xiàn)在應(yīng)該看到文本 Sammy the Shark 呈現(xiàn)的透明背景:

image.png

現(xiàn)在您已經(jīng)確認(rèn) SVG 代碼繪制了文本,您將把文本圖形合成到 sammy.png 上黔夭。

添加以下突出顯示的代碼以將 SVG 文本圖形圖像合成到 sammy.png 圖像上宏胯。

const sharp = require("sharp");

async function addTextOnImage() {
  try {
    const width = 750;
    const height = 483;
    const text = "Sammy the Shark";

    const svgImage = `
    <svg width="${width}" height="${height}">
      <style>
      .title { fill: #001; font-size: 70px; font-weight: bold;}
      </style>
      <text x="50%" y="50%" text-anchor="middle" class="title">${text}</text>
    </svg>
    `;
    const svgBuffer = Buffer.from(svgImage);
    const image = await sharp("sammy.png")
      .composite([
        {
          input: svgBuffer,
          top: 0,
          left: 0,
        },
      ])
      .toFile("sammy-text-overlay.png");
  } catch (error) {
    console.log(error);
  }
}

addTextOnImage();

Composite() 方法從 svgBuffer 變量中讀取 SVG 圖像,并將其放置在距 sammy.png 頂部 0 像素和左邊緣 0 像素的位置本姥。 接下來肩袍,將合成圖像保存為 sammy-text-overlay.png。

保存的文件婚惫,并執(zhí)行以下命令:

node addTextOnImage.js

在本地機器上打開 sammy-text-overlay.png氛赐。 您應(yīng)該會看到在圖像上添加的文本:

image.png

您現(xiàn)在已經(jīng)使用composite() 方法在另一個圖像上添加使用 SVG 創(chuàng)建的文本。

結(jié)論

在本文中先舷,您學(xué)習(xí)了如何在 Node.js 中使用sharp的方法處理圖像艰管。 首先,您創(chuàng)建了一個實例來讀取圖像并使用 metadata() 方法提取圖像元數(shù)據(jù)蒋川。 然后使用 resize() 方法調(diào)整圖像大小牲芋。 之后,您使用 format() 方法更改圖像類型捺球,并壓縮圖像缸浦。 接下來,您繼續(xù)使用各種sharp的方法來裁剪氮兵、灰度裂逐、旋轉(zhuǎn)和模糊圖像。 最后泣栈,您使用了 composite() 方法來合成圖像絮姆,并在圖像上添加文本醉冤。

要更深入地了解其他sharp的方法,請訪問 sharp 文檔篙悯。

本文翻譯的原文鏈接: https://www.digitalocean.com/community/tutorial_series/how-to-code-in-node-js

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚁阳,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鸽照,更是在濱河造成了極大的恐慌螺捐,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矮燎,死亡現(xiàn)場離奇詭異定血,居然都是意外死亡,警方通過查閱死者的電腦和手機诞外,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門澜沟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人峡谊,你說我怎么就攤上這事茫虽。” “怎么了既们?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵濒析,是天一觀的道長。 經(jīng)常有香客問我啥纸,道長号杏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任斯棒,我火速辦了婚禮盾致,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘荣暮。我一直安慰自己绰上,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布渠驼。 她就那樣靜靜地躺著,像睡著了一般鉴腻。 火紅的嫁衣襯著肌膚如雪迷扇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天爽哎,我揣著相機與錄音蜓席,去河邊找鬼。 笑死课锌,一個胖子當(dāng)著我的面吹牛厨内,可吹牛的內(nèi)容都是我干的祈秕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼雏胃,長吁一口氣:“原來是場噩夢啊……” “哼请毛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瞭亮,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤方仿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后统翩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仙蚜,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年厂汗,在試婚紗的時候發(fā)現(xiàn)自己被綠了委粉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖昼激,靈堂內(nèi)的尸體忽然破棺而出政供,到底是詐尸還是另有隱情,我是刑警寧澤氮双,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站霎匈,受9級特大地震影響戴差,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜铛嘱,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一暖释、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧墨吓,春花似錦球匕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至秘症,卻和暖如春照卦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背乡摹。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工役耕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人聪廉。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓瞬痘,卻偏偏與公主長得像故慈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子框全,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容