Обработка изображений в Node.js: resize и crop с Sharp

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с изображениями в Node.js: resize и crop с помощью Sharp

В современной веб-разработке обработка изображений на серверной стороне — частая задача. Node.js предлагает несколько мощных библиотек для работы с графикой. В этой статье мы подробно рассмотрим библиотеку Sharp — быстрый и эффективный инструмент для изменения размера (resize) и обрезки (crop) изображений.

Почему Sharp?

Sharp использует нативные библиотеки libvips, что делает его одним из самых производительных решений для Node.js. Основные преимущества:

  • Высокая скорость обработки (в разы быстрее аналогов на чистом JavaScript)
  • Низкое потребление памяти
  • Поддержка всех популярных форматов: JPEG, PNG, WebP, AVIF, TIFF
  • Простой и понятный API
  • Возможность работы с потоками (streams)

Установка

Установка Sharp в проект Node.js выполняется одной командой:

npm install sharp

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

Базовое изменение размера (resize)

Метод resize() позволяет изменить размеры изображения. Рассмотрим основные варианты использования.

Пример 1: Простое изменение размера

const sharp = require('sharp');
const path = require('path');

async function resizeImage() {
    try {
        await sharp('input.jpg')
            .resize(300, 200) // ширина 300px, высота 200px
            .toFile('output.jpg');
        console.log('Изображение изменено успешно');
    } catch (error) {
        console.error('Ошибка:', error);
    }
}

resizeImage();

В этом примере изображение будет сжато до точных размеров 300x200 пикселей, что может исказить пропорции.

Пример 2: Сохранение пропорций

async function resizeWithProportions() {
    await sharp('input.jpg')
        .resize({
            width: 400, // только ширина
            height: undefined, // высота будет вычислена автоматически
            fit: 'inside' // сохраняем пропорции
        })
        .toFile('output_inside.jpg');
    
    console.log('Пропорции сохранены');
}

Параметр fit принимает несколько значений:

  • cover — обрезает изображение, чтобы полностью заполнить заданные размеры (по умолчанию)
  • contain — вписывает изображение в заданные размеры, сохраняя пропорции
  • fill — растягивает изображение до заданных размеров
  • inside — уменьшает изображение, чтобы оно поместилось в заданные размеры
  • outside — увеличивает изображение, чтобы оно выходило за пределы заданных размеров

Обрезка изображений (crop)

Sharp предоставляет два основных способа обрезки: с помощью метода extract() и через параметры resize().

Метод extract()

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

async function cropImage() {
    await sharp('input.jpg')
        .extract({
            left: 100,   // отступ слева
            top: 50,     // отступ сверху
            width: 300,  // ширина области
            height: 200  // высота области
        })
        .toFile('cropped.jpg');
    
    console.log('Обрезка выполнена');
}

Автоматическая обрезка при resize

Часто требуется изменить размер и одновременно обрезать изображение. Это делается с помощью параметра gravity или position:

async function cropAndResize() {
    await sharp('input.jpg')
        .resize(200, 200, {
            fit: 'cover', // обрезаем до точного размера
            position: 'center' // фокус на центре
        })
        .toFile('avatar.jpg');
    
    console.log('Аватар создан');
}

Параметр position может принимать значения: center, top, bottom, left, right, top-left, top-right, bottom-left, bottom-right или координаты в процентах (left: 50%, top: 30%).

Продвинутые техники

Работа с потоками (streams)

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

const fs = require('fs');

async function streamProcess() {
    const readStream =                    

Рекомендаций