Как обрабатывать изображения в Node.js с помощью Sharp

Автор выбрал Фонд разнообразия в технологиях для получения пожертвования в рамках программы Пиши ради благотворительности.

Введение

Цифровая обработка изображений – это метод использования компьютера для анализа и манипулирования изображениями. Процесс включает чтение изображения, применение методов для изменения или улучшения изображения, а затем сохранение обработанного изображения. Это обычно применяется в приложениях, которые обрабатывают загруженный пользователями контент. Например, если вы пишете веб-приложение, которое позволяет пользователям загружать изображения, пользователи могут загружать избыточно большие изображения. Это может негативно сказаться на скорости загрузки приложения и также занимать место на вашем сервере. С помощью обработки изображений ваше приложение может изменять размер и сжимать все загруженные пользователями изображения, что существенно улучшит производительность вашего приложения и сэкономит дисковое пространство на сервере.

Node.js имеет экосистему библиотек, которые вы можете использовать для обработки изображений, такие как sharp, jimp и модуль gm. Эта статья сосредоточится на модуле sharp. sharp – популярная библиотека обработки изображений для Node.js, которая поддерживает различные форматы файлов изображений, такие как JPEG, PNG, GIF, WebP, AVIF, SVG и TIFF.

В этом учебнике вы будете использовать sharp для чтения изображения и извлечения его метаданных, изменения размера, изменения формата изображения и сжатия изображения. Затем вы обрежете, преобразуете в оттенки серого, повернете и размоете изображение. Наконец, вы составите изображения и добавите текст на изображение. К концу этого учебника вы будете хорошо разбираться в обработке изображений в Node.js.

Предварительные требования

Чтобы выполнить этот учебник, вам понадобится:

Шаг 1 — Настройка каталога проекта и загрузка изображений

Прежде чем начать писать код, вам необходимо создать каталог, который будет содержать код и изображения, которые вы будете использовать в этой статье.

Откройте ваш терминал и создайте каталог для проекта, используя команду mkdir:

  1. mkdir process_images

Перейдите в только что созданный каталог с помощью команды cd:

  1. cd process_images

Создайте файл package.json, используя команду npm init, чтобы отслеживать зависимости проекта:

  1. npm init -y

Опция -y указывает npm создать файл package.json по умолчанию.

Затем установите sharp в качестве зависимости:

  1. npm install sharp

Вы будете использовать следующие три изображения в этом учебнике:



Затем загрузите изображения в каталог вашего проекта, используя команду curl.

Используйте следующую команду для загрузки первого изображения. Это загрузит изображение как sammy.png:

  1. curl -O https://assets.digitalocean.com/how-to-process-images-in-node-js-with-sharp/sammy.png

Затем загрузите второе изображение с помощью следующей команды. Это загрузит изображение как underwater.png:

  1. curl -O https://assets.digitalocean.com/how-to-process-images-in-node-js-with-sharp/underwater.png

Наконец, загрузите третье изображение с помощью следующей команды. Это загрузит изображение как sammy-transparent.png:

  1. curl -O https://assets.digitalocean.com/how-to-process-images-in-node-js-with-sharp/sammy-transparent.png

С настройкой каталога проекта и зависимостями вы теперь готовы начать обработку изображений.

Шаг 2 — Чтение изображений и вывод метаданных

В этом разделе вы напишете код для чтения изображения и извлечения его метаданных. Метаданные изображения — это текст, встроенный в изображение, который содержит информацию о изображении, такую как его тип, ширина и высота.

Для извлечения метаданных сначала импортируйте модуль sharp, создайте экземпляр sharp и передайте путь к изображению в качестве аргумента. Затем свяжите метод metadata() с экземпляром, чтобы извлечь метаданные и записать их в консоль.

Для этого создайте и откройте файл readImage.js в выбранном вами текстовом редакторе. В этом руководстве используется текстовый редактор терминала под названием nano:

  1. nano readImage.js

Затем подключите модуль sharp в начале файла:

process_images/readImage.js
const sharp = require("sharp");

Sharp – это модуль обработки изображений, работающий на основе обещаний. При создании экземпляра sharp возвращается обещание. Вы можете разрешить обещание, используя метод then, или использовать async/await, который имеет более чистый синтаксис.

Для использования синтаксиса async/await вам нужно создать асинхронную функцию, поместив ключевое слово async в начало функции. Это позволит вам использовать ключевое слово await внутри функции для разрешения обещания, возвращаемого при чтении изображения.

В вашем файле readImage.js определите асинхронную функцию getMetadata(), чтобы прочитать изображение, извлечь его метаданные и записать их в консоль:

process_images/readImage.js
const sharp = require("sharp");

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

getMetadata() – это асинхронная функция, так как перед меткой function указано ключевое слово async. Это позволяет использовать синтаксис await внутри функции. Функция getMetadata() считывает изображение и возвращает объект с его метаданными.

Внутри тела функции изображение считывается с помощью вызова sharp(), который принимает путь к изображению в качестве аргумента, здесь с sammy.png.

Помимо пути к изображению, sharp() также может считывать данные изображения, хранящиеся в Buffer, Uint8Array или Uint8ClampedArray, при условии, что изображение представляет собой JPEG, PNG, GIF, WebP, AVIF, SVG или TIFF.

Теперь, когда вы используете sharp() для чтения изображения, создается экземпляр sharp. Затем вы применяете метод metadata() модуля sharp к этому экземпляру. Метод возвращает объект, содержащий метаданные изображения, которые вы сохраняете в переменной metadata, а затем выводите содержимое этой переменной с помощью console.log().

Теперь ваша программа может считывать изображение и возвращать его метаданные. Однако, если во время выполнения программа выдает ошибку, она завершится сбоем. Чтобы избежать этого, вам необходимо обрабатывать ошибки при их возникновении.

Чтобы сделать это, оберните код внутри функции getMetadata() в блок try...catch:

process_images/readImage.js
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 вы читаете изображение, извлекаете и записываете его метаданные. Когда происходит ошибка во время этого процесса, выполнение переходит к секции catch и записывает ошибку, предотвращая программу от вылета.

Наконец, вызовите функцию getMetadata(), добавив выделенную строку:

process_images/readImage.js

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}`);
  }
}

getMetadata();

Теперь сохраните и закройте файл. Введите y, чтобы сохранить внесенные в файл изменения, и подтвердите имя файла, нажав клавишу ENTER или RETURN.

Запустите файл, используя команду node:

  1. node readImage.js

Вы должны увидеть вывод, аналогичный этому:

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

Теперь, когда вы прочитали изображение и извлекли его метаданные, теперь измените размер изображения, измените его формат и сожмите его.

Шаг 3 — Изменение размера, изменение формата изображения и сжатие изображений

Изменение размера – это процесс изменения размера изображения без его обрезки, что влияет на размер файла изображения. В этом разделе вы измените размер изображения, измените его тип и сожмите изображение. Сжатие изображения – это процесс уменьшения размера файла изображения без потери качества.

Сначала вы вызовете метод resize() от экземпляра sharp для изменения размера изображения и сохраните его в директории проекта. Во-вторых, вы вызовете метод format() для изменения формата измененного изображения с png на jpeg. Кроме того, вы передадите параметр в метод format() для сжатия изображения и сохранения его в директории.

Создайте и откройте файл resizeImage.js в вашем текстовом редакторе:

  1. nano resizeImage.js

Добавьте следующий код для изменения размера изображения на ширину 150px и высоту 97px:

process_images/resizeImage.js
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() цепляет метод resize() модуля sharp к экземпляру sharp. Метод принимает объект в качестве аргумента. В этом объекте вы устанавливаете желаемые размеры изображения, используя свойства width и height. Установка width в 150 и height в 97 сделает изображение шириной 150px и высотой 97px.

После изменения размера изображения вы цепляете метод toFile() модуля sharp, который принимает путь к изображению в качестве аргумента. Передача sammy-resized.png в качестве аргумента сохранит файл изображения с этим именем в рабочей директории вашей программы.

Теперь сохраните и закройте файл. Запустите вашу программу в терминале:

  1. node resizeImage.js

Вы не получите вывода, но вы должны увидеть новый файл изображения с именем sammy-resized.png в директории проекта.

Откройте изображение на своем локальном компьютере. Вы должны увидеть изображение Сэмми шириной 150px и высотой 97px:

Теперь, когда вы можете изменить размер изображения, следующим шагом будет преобразование формата измененного изображения из png в jpeg, сжатие изображения и сохранение его в рабочем каталоге. Для этого вы будете использовать метод toFormat(), который вы вызовете после метода resize().

Добавьте выделенный код для изменения формата изображения на jpeg и его сжатия:

process_images/resizeImage.js
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() вы используете метод toFormat() модуля sharp для изменения формата изображения и его сжатия. Первый аргумент метода toFormat() – это строка, содержащая формат изображения, в который вы хотите преобразовать свое изображение. Второй аргумент – необязательный объект, содержащий параметры вывода, которые улучшают и сжимают изображение.

Чтобы сжать изображение, передайте ему свойство mozjpeg, которое содержит булево значение. Когда вы устанавливаете его в true, sharp использует по умолчанию mozjpeg для сжатия изображения без ущерба качества. Объект также может принимать больше параметров; см. документацию sharp для получения более подробной информации.

Примечание: Относительно второго аргумента метода toFormat(), каждый формат изображения принимает объект с разными свойствами. Например, свойство mozjpeg принимается только для изображений JPEG.

Однако другие форматы изображений имеют эквивалентные параметры, такие как качество, сжатие и без потерь. Обязательно обратитесь к документации, чтобы узнать, какие параметры допустимы для формата изображения, который вы сжимаете.

Затем передайте методу toFile() другое имя файла для сохранения сжатого изображения, например sammy-resized-compressed.jpeg.

Теперь сохраните и закройте файл, затем выполните свой код с помощью следующей команды:

  1. node resizeImage.js

Вывода не будет, но файл изображения sammy-resized-compressed.jpeg будет сохранен в директории вашего проекта.

Откройте изображение на вашем локальном компьютере и вы увидите следующее изображение:

Теперь, когда ваше изображение сжато, проверьте размер файла, чтобы подтвердить успешное сжатие. В вашем терминале выполните команду du, чтобы проверить размер файла sammy.png:

  1. du -h sammy.png

Опция -h выводит информацию, понятную человеку, показывая размер файла в килобайтах, мегабайтах и многих других.

После выполнения команды вы увидите вывод примерно такого вида:

Output
120K sammy.png

Вывод показывает, что исходное изображение занимает 120 килобайт.

Затем проверьте размер файла sammy-resized.png:

  1. du -h sammy-resized.png

После выполнения команды вы увидите следующий вывод:

Output
8.0K sammy-resized.png

sammy-resized.png весит 8 килобайт вместо 120 килобайт. Это показывает, что операция изменения размера влияет на размер файла.

Теперь проверьте размер файла для sammy-resized-compressed.jpeg:

  1. du -h sammy-resized-compressed.jpeg

После выполнения команды вы увидите следующий вывод:

Output
4.0K sammy-resized-compressed.jpeg

Файл sammy-resized-compressed.jpeg теперь весит 4 килобайта вместо 8 килобайт, что позволяет сэкономить 4 килобайта, что показывает, что сжатие сработало.

Теперь, когда вы изменили размер изображения, изменили его формат и сжали его, вы обрежете и переведете изображение в оттенки серого.

Шаг 4 — Обрезка и преобразование изображений в оттенки серого

На этом шаге вы обрежете изображение и преобразуете его в оттенки серого. Обрезка – это процесс удаления ненужных областей изображения. Вы будете использовать метод extend() для обрезки изображения sammy.png. После этого вы добавите метод grayscale() к экземпляру обрезанного изображения и преобразуете его в оттенки серого.

Создайте и откройте файл cropImage.js в вашем текстовом редакторе:

  1. nano cropImage.js

В вашем файле cropImage.js добавьте следующий код для обрезки изображения:

process_images/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() является асинхронной функцией, которая считывает изображение и возвращает обрезанное изображение. Внутри блока try экземпляр sharp будет читать изображение. Затем метод extract() модуля sharp, связанный с экземпляром, принимает объект со следующими свойствами:

  • width: ширина области, которую вы хотите обрезать.
  • height: высота области, которую вы хотите обрезать.
  • top: вертикальное положение области, которую вы хотите обрезать.
  • left: горизонтальное положение области, которую вы хотите обрезать.

Когда вы устанавливаете width в 500, а height в 330, представьте себе, что sharp создает прозрачный прямоугольник поверх изображения, которое вы хотите обрезать. Любая часть изображения, которая помещается в прямоугольник, останется, а остальное будет обрезано:

Свойства top и left управляют положением прямоугольника. Когда вы устанавливаете left в 120, прямоугольник размещается на 120 пикселей от левого края изображения, а установка top в 70 размещает прямоугольник на 70 пикселей от верхнего края изображения.

Область изображения, которая помещается в прямоугольник, будет вырезана и сохранена в файле sammy-cropped.png как отдельное изображение.

Сохраните и закройте файл. Запустите программу в терминале:

  1. node cropImage.js

Вывод не будет отображен, но изображение sammy-cropped.png будет сохранено в вашем рабочем каталоге.

Откройте изображение на вашем локальном компьютере. Вы должны увидеть обрезанное изображение:

Теперь, когда вы обрезали изображение, вы преобразуете его в оттенки серого. Для этого вы примените метод grayscale к экземпляру sharp. Добавьте выделенный код для преобразования изображения в оттенки серого:

process_images/cropImage.js
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() преобразует обрезанное изображение в оттенки серого, применяя метод grayscale() модуля sharp к экземпляру sharp. Затем она сохраняет изображение в директории проекта как sammy-cropped-grayscale.png.

Нажмите CTRL+X, чтобы сохранить и выйти из файла.

Запустите свой код в терминале:

  1. node cropImage.js

Откройте sammy-cropped-grayscale.png на вашем локальном компьютере. Теперь вы должны увидеть изображение в оттенках серого:

Теперь, когда вы обрезали и извлекли изображение, вы будете работать с его поворотом и размытием.

Шаг 5 — Поворот и размытие изображений

На этом этапе вы повернете изображение sammy.png на угол 33 градуса. Вы также примените гауссово размытие к повернутому изображению. Гауссово размытие – это метод размытия изображения с использованием функции Гаусса, которая снижает уровень шума и деталей на изображении.

Создайте файл rotateImage.js в вашем текстовом редакторе:

  1. nano rotateImage.js

В вашем файле rotateImage.js напишите следующий блок кода для создания функции, которая поворачивает sammy.png на угол 33 градуса:

process_images/rotateImage.js
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() является асинхронной функцией, которая считывает изображение и возвращает изображение, повернутое на угол 33 градуса. Внутри функции метод rotate() модуля sharp принимает два аргумента. Первый аргумент – угол поворота 33 градуса. По умолчанию sharp делает фон повернутого изображения черным. Чтобы удалить черный фон, вы передаете объект в качестве второго аргумента, чтобы сделать фон прозрачным.

Объект имеет свойство background, которое содержит объект, определяющий модель цвета RGBA. RGBA означает красный, зеленый, синий и альфа.

  • r: управляет интенсивностью красного цвета. Принимает целочисленное значение от 0 до 255. 0 означает, что цвет не используется, а 255 – максимальная интенсивность красного.

  • g: управляет интенсивностью зеленого цвета. Принимает целочисленное значение от 0 до 255. 0 означает, что цвет зеленый не используется, а 255 – максимальная интенсивность зеленого.

  • b: управляет интенсивностью синего цвета. Также принимает целочисленное значение от 0 до 255. 0 означает, что синий цвет не используется, а 255 – максимальная интенсивность синего.

  • alpha: контролирует непрозрачность цвета, определенного свойствами r, g и b. 0 или 0.0 делает цвет прозрачным, а 1 или 1.1 делает цвет непрозрачным.

Чтобы свойство alpha работало, убедитесь, что вы определили и установили значения для r, g и b. Установка значений r, g и b в 0 создает черный цвет. Чтобы создать прозрачный фон, сначала определите цвет, а затем установите alpha в 0, чтобы сделать его прозрачным.

Теперь сохраните и выйдите из файла. Запустите свой скрипт в терминале:

  1. node rotateImage.js

Проверьте наличие файла sammy-rotated.png в вашем проектном каталоге. Откройте его на локальной машине.

Вы должны увидеть изображение, повернутое под углом 33 градуса:

Затем вы размоете повернутое изображение. Вы достигнете этого, добавив метод blur() к экземпляру sharp.

Введите выделенный ниже код, чтобы размыть изображение:

process_images/rotateImage.js
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() теперь читает изображение, поворачивает его и применяет размытие по Гауссу к изображению. Она применяет размытие по Гауссу к изображению с использованием метода blur() модуля sharp. Метод принимает единственный аргумент, содержащий значение сигмы от 0.3 до 1000. Передача значения 4 применит размытие по Гауссу с значением сигмы 4. После того, как изображение размыто, вы определяете путь для сохранения размытого изображения.

Теперь ваш скрипт будет размывать повернутое изображение со значением сигмы 4. Сохраните и закройте файл, затем запустите скрипт в вашем терминале:

  1. node rotateImage.js

После запуска скрипта откройте файл sammy-rotated-blurred.png на вашем локальном компьютере. Теперь вы должны увидеть размытое повернутое изображение:

Теперь, когда вы повернули и размылили изображение, вы будете составлять одно изображение над другим.

Шаг 6 — Компоновка изображений с помощью composite()

Компоновка изображений — это процесс объединения двух или более отдельных изображений для создания одного изображения. Это делается для создания эффектов, взятых из лучших элементов разных фотографий. Еще одним распространенным случаем использования является нанесение водяного знака на изображение с логотипом.

В этом разделе вы скомпонуете sammy-transparent.png поверх underwater.png. Это создаст иллюзию того, что Сэмми плавает глубоко в океане. Чтобы скомпоновать изображения, вы примените метод composite() к экземпляру sharp.

Создайте и откройте файл compositeImage.js в вашем текстовом редакторе:

  1. nano compositeImages.js

Теперь создайте функцию для компоновки двух изображений, добавив следующий код в файл compositeImages.js:

process_images/compositeImages.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() сначала считывает изображение underwater.png. Затем вы применяете метод composite() модуля sharp, который принимает массив в качестве аргумента. Массив содержит единственный объект, который считывает изображение sammy-transparent.png. Объект имеет следующие свойства:

  • input: принимает путь изображения, которое вы хотите скомпоновать поверх обработанного изображения. Он также принимает Buffer, Uint8Array или Uint8ClampedArray в качестве ввода.
  • top: управляет вертикальным положением изображения, которое вы хотите скомпоновать. Установка top в 50 смещает изображение sammy-transparent.png на 50 пикселей от верхнего края изображения underwater.png.
  • left: управляет горизонтальным положением изображения, которое вы хотите объединить с другим. Установка left в 50 смещает sammy-transparent.png на 50px от левого края изображения underwater.png.

Метод composite() требует изображения с аналогичным или меньшим размером по отношению к обрабатываемому изображению.

Чтобы визуализировать, что делает метод composite(), думайте о нем как о создании стопки изображений. Изображение sammy-transparent.png помещается поверх изображения underwater.png:

Значения top и left позиционируют изображение sammy-transparent.png относительно изображения underwater.png.

Сохраните свой скрипт и выйдите из файла. Запустите ваш скрипт для создания композиции изображений:

node compositeImages.js

Откройте sammy-underwater.png на вашем локальном компьютере. Теперь вы должны увидеть, как sammy-transparent.png объединено с изображением underwater.png:

Теперь вы сделали композицию изображений с помощью метода composite(). В следующем шаге вы будете использовать метод composite(), чтобы добавить текст на изображение.

Шаг 7 — Добавление текста на изображение

На этом этапе вы напишете текст на изображении. На момент написания, в Sharp нет нативного способа добавления текста к изображению. Чтобы добавить текст, сначала вам нужно будет написать код для рисования текста с использованием масштабируемой векторной графики (SVG). После создания изображения SVG вы напишете код для компоновки изображения с изображением sammy.png с помощью метода composite.

SVG – это основанный на XML язык разметки для создания векторной графики для веба. Вы можете рисовать текст или формы, такие как круги, треугольники, а также рисовать сложные формы, такие как иллюстрации, логотипы и т. д. Сложные формы создаются с помощью графического инструмента, такого как Inkscape, который генерирует SVG-код. Формы SVG могут быть отображены и масштабированы до любого размера без потери качества.

Создайте и откройте файл addTextOnImage.js в вашем текстовом редакторе.

  1. nano addTextOnImage.js

В вашем файле addTextOnImage.js добавьте следующий код для создания контейнера SVG:

process_images/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() определяет четыре переменные: width, height, text и svgImage. width хранит целое число 750, а height хранит целое число 483. text содержит строку Sammy the Shark. Это текст, который вы нарисуете с помощью SVG.

Переменная svgImage содержит элемент svg. Элемент svg имеет два атрибута: width и height, которые интерполируют переменные width и height, определенные ранее. Элемент svg создает прозрачный контейнер с учетом указанной ширины и высоты.

Вы установили для элемента svg ширину 750 и высоту 483, чтобы SVG-изображение имело такой же размер, как и sammy.png. Это поможет сделать текст выровненным по центру изображения sammy.png.

Затем вы нарисуете текстовую графику. Добавьте выделенный код для отрисовки Sammy the Shark на контейнере SVG:

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

Элемент text SVG имеет четыре атрибута: x, y, text-anchor и class. x и y определяют позицию текста, который вы рисуете на контейнере SVG. Атрибут x позиционирует текст горизонтально, а атрибут y – вертикально.

Установка x в 50% рисует текст посередине контейнера по оси x, а установка y в 50% позиционирует текст посередине по оси y изображения SVG.

Атрибут text-anchor выравнивает текст горизонтально. Установка text-anchor в middle выровняет текст по центру на указанной вами координате x.

class определяет имя класса для элемента text. Вы будете использовать имя класса для применения CSS стилей к элементу text.

${text} интерполирует строку Sammy the Shark, хранящуюся в переменной text. Это текст, который будет нарисован на изображении SVG.

Затем добавьте выделенный код для стилизации текста с помощью CSS:

process_images/addTextOnImage.js
    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 изменяет насыщенность шрифта.

На этом этапе вы написали код, необходимый для рисования текста Sammy the Shark с использованием SVG. Затем вы сохраните изображение SVG в формате png с помощью sharp, чтобы увидеть, как SVG рисует текст. После этого вы сольете изображение SVG с sammy.png.

Добавьте выделенный код для сохранения изображения SVG в формате png с помощью sharp:

process_images/addTextOnImage.js
    ....
    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() создает объект Buffer из изображения SVG. Буфер – это временное пространство в памяти, которое хранит двоичные данные.

После создания объекта буфера вы создаете экземпляр sharp с этим объектом буфера в качестве ввода. Кроме пути к изображению, sharp также принимает буфер, Uint9Array или Uint8ClampedArray.

Наконец, сохраните SVG-изображение в директории проекта как svg-image.png.

Вот полный код:

process_images/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}">
      <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()

Сохраните и закройте файл, затем запустите ваш скрипт следующей командой:

node addTextOnImage.js

Примечание: Если вы установили Node.js, используя Опцию 2 — Установка Node.js с помощью Apt с использованием репозитория NodeSource PPA или Опцию 3 — Установка Node с помощью менеджера версий Node и получаете ошибку fontconfig error: cannot load default config file: no such file: (null), установите fontconfig, чтобы создать файл конфигурации шрифта.

Обновите индекс пакетов сервера, а затем используйте apt install для установки fontconfig.

  1. sudo apt update
  2. sudo apt install fontconfig

Откройте svg-image.png на вашем локальном компьютере. Теперь вы должны видеть текст Сэмми Акула, отображенный на прозрачном фоне:

Теперь, когда вы подтвердили, что SVG-код рисует текст, вы добавите текстовую графику на sammy.png.

Добавьте следующий выделенный код, чтобы наложить изображение текстовой графики SVG на изображение sammy.png.

process_images/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}">
      <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() считывает изображение SVG из переменной svgBuffer и размещает его на расстоянии 0 пикселов от верхнего края и 0 пикселов от левого края sammy.png. Затем вы сохраняете составленное изображение как sammy-text-overlay.png.

Сохраните и закройте файл, затем запустите программу с помощью следующей команды:

  1. node addTextOnImage.js

Откройте sammy-text-overlay.png на вашем локальном компьютере. Вы должны увидеть добавленный текст над изображением:

Теперь вы использовали метод composite(), чтобы добавить текст, созданный с помощью SVG, на другое изображение.

Заключение

В этой статье вы узнали, как использовать острые методы для обработки изображений в Node.js. Сначала вы создали экземпляр для чтения изображения и использовали метод metadata() для извлечения метаданных изображения. Затем вы использовали метод resize() для изменения размера изображения. После этого вы использовали метод format() для изменения типа изображения и его сжатия. Затем вы продолжили использовать различные методы острых для обрезки, перевода в оттенки серого, поворота и размытия изображения. Наконец, вы использовали метод composite() для совмещения изображения и добавления текста на изображение.

Для получения дополнительной информации о дополнительных методах острых посетите документацию по острым. Если вы хотите продолжить изучение Node.js, ознакомьтесь с серией статей Как программировать на Node.js.

Source:
https://www.digitalocean.com/community/tutorials/how-to-process-images-in-node-js-with-sharp