Введение: Что такое Sharp и зачем она нужна?
Sharp — это высокопроизводительная библиотека для обработки изображений, написанная на C++ и предоставляющая удобный API для Node.js. Она позволяет преобразовывать изображения форматов JPEG, PNG, WebP, AVIF, TIFF и GIF в другие форматы, изменять их размер, обрезать, поворачивать, добавлять эффекты и многое другое.
Основное преимущество Sharp — это скорость. Библиотека использует нативные библиотеки libvips, что делает её в несколько раз быстрее аналогов (например, Jimp или gm). Она идеально подходит для:
- Веб-серверов и API — динамическая обработка аватарок, превью, оптимизация изображений перед загрузкой.
- Пакетной обработки — конвертация тысяч изображений в нужный формат и размер.
- Создания миниатюр и галерей — быстрая генерация thumbnail.
- Оптимизации веса изображений — сжатие без потери качества (или с контролируемой потерей).
Sharp работает с буферами, потоками (streams) и файлами, что делает её гибкой для интеграции в любые Node.js приложения.
Установка
Установка Sharp выполняется через npm. Для работы библиотеки требуется Node.js версии 12.13.0 или выше (рекомендуется 14+).
npm install sharp
Если вы используете yarn:
yarn add sharp
Важно: Sharp компилирует нативные модули при установке. Если у вас возникают ошибки, убедитесь, что установлены build-essential (на Linux) или Xcode Command Line Tools (на macOS). Для Windows обычно достаточно Visual Studio Build Tools.
После установки импортируйте библиотеку в ваш проект:
const sharp = require('sharp');
Быстрый старт
Давайте напишем простой скрипт, который загружает изображение, уменьшает его до ширины 300 пикселей (сохраняя пропорции) и сохраняет в формате WebP.
const sharp = require('sharp');
const path = require('path');
async function quickStart() {
try {
await sharp('input.jpg')
.resize(300) // Ширина 300px, высота подстроится автоматически
.webp({ quality: 80 }) // Конвертируем в WebP с качеством 80%
.toFile('output.webp');
console.log('Изображение успешно обработано!');
} catch (error) {
console.error('Ошибка:', error);
}
}
quickStart();
Этот пример демонстрирует цепочку методов (chaining), которая является основой работы с Sharp. Каждый метод возвращает новый экземпляр Sharp, что позволяет последовательно применять трансформации.
Основные методы и функции
Ниже представлены 10 ключевых методов Sharp с подробным описанием, параметрами и примерами кода.
1. resize() — Изменение размера изображения
Что делает: Изменяет ширину и/или высоту изображения. Может обрезать или вписывать изображение в заданные рамки.
Параметры:
width(number, опционально) — новая ширина в пикселях.height(number, опционально) — новая высота в пикселях.options(object, опционально):fit(string) — режим вписывания: 'cover' (заполнить, обрезая лишнее), 'contain' (вписать целиком), 'fill' (растянуть), 'inside' (уменьшить до вписывания), 'outside' (увеличить до выхода за границы). По умолчанию 'cover'.position(string) — позиция при обрезке: 'center', 'top', 'left', 'right', 'bottom' и т.д.withoutEnlargement(boolean) — запретить увеличение изображения.
Пример:
// Уменьшить до 200x200, обрезая по центру
await sharp('input.jpg')
.resize(200, 200, { fit: 'cover', position: 'center' })
.toFile('output_200x200.jpg');
// Вписать в прямоугольник 400x300 без растяжения
await sharp('input.jpg')
.resize(400, 300, { fit: 'inside' })
.toFile('output_contain.jpg');
2. toFile() — Сохранение результата в файл
Что делает: Записывает обработанное изображение в файл на диске. Это конечный метод в цепочке.
Параметры:
fileOut(string) — путь к выходному файлу. Формат определяется по расширению (.jpg, .png, .webp и т.д.).
Пример:
await sharp('input.png')
.resize(100)
.toFile('output_thumb.png');
3. toBuffer() — Получение результата в виде буфера
Что делает: Возвращает обработанное изображение как Buffer (бинарные данные). Полезно для отправки через HTTP или сохранения в базу данных.
Параметры: Нет.
Пример:
const buffer = await sharp('input.jpg')
.resize(150)
.jpeg({ quality: 70 })
.toBuffer();
// Теперь buffer можно отправить как ответ сервера
res.type('image/jpeg').send(buffer);
4. jpeg() / png() / webp() / avif() — Настройка выходного формата
Что делает: Задает параметры кодирования для соответствующего формата. Если не вызвать ни один из этих методов, Sharp сохранит в исходном формате (или определит по расширению файла).
Параметры (общие для всех):
quality(number, 0-100) — качество сжатия. Для JPEG по умолчанию 80, для WebP — 80.progressive(boolean) — прогрессивный JPEG (только для jpeg).compressionLevel(number, 0-9) — уровень сжатия PNG (по умолчанию 6).lossless(boolean) — сжатие без потерь (для WebP и AVIF).
Пример:
// Сохранить как JPEG с качеством 50%
await sharp('input.png')
.jpeg({ quality: 50, progressive: true })
.toFile('output_compressed.jpg');
// Сохранить как WebP без потерь
await sharp('input.jpg')
.webp({ lossless: true })
.toFile('output_lossless.webp');
5. rotate() — Поворот изображения
Что делает: Поворачивает изображение на заданный угол. Также автоматически корректирует ориентацию на основе EXIF-данных, если передать true.
Параметры:
angle(number, опционально) — угол поворота в градусах (кратный 90). Если не указан, используется EXIF-ориентация.options(object, опционально) — содержит свойствоbackground(string) для цвета фона (по умолчанию черный).
Пример:
// Поворот на 90 градусов по часовой стрелке
await sharp('input.jpg')
.rotate(90)
.toFile('rotated_90.jpg');
// Автоматическая коррекция по EXIF
await sharp('input.jpg')
.rotate()
.toFile('corrected.jpg');
6. flip() и flop() — Отражение изображения
Что делает: flip() отражает изображение по вертикали (верх-низ). flop() отражает по горизонтали (лево-право).
Параметры: Нет.
Пример:
// Отражение по вертикали
await sharp('input.jpg')
.flip()
.toFile('flipped_vertical.jpg');
// Отражение по горизонтали
await sharp('input.jpg')
.flop()
.toFile('flopped_horizontal.jpg');
7. grayscale() — Преобразование в оттенки серого
Что делает: Делает изображение черно-белым (оттенки серого).
Параметры: Нет (но можно передать true для явного включения).
Пример:
await sharp('colorful.jpg')
.grayscale()
.toFile('black_and_white.jpg');
8. tint() — Тонирование изображения
Что делает: Накладывает цветной оттенок на изображение. Полезно для создания эффектов или цветокоррекции.
Параметры:
tint(object) — объект с цветом в формате RGB:{ r: number, g: number, b: number }.
Пример:
// Наложить красный оттенок
await sharp('input.jpg')
.tint({ r: 255, g: 0, b: 0 })
.toFile('red_tinted.jpg');
9. blur() — Размытие изображения
Что делает: Применяет гауссово размытие к изображению. Полезно для создания эффекта "боке" или размытия фона.
Параметры:
sigma(number, опционально) — радиус размытия (стандартное отклонение). По умолчанию 3. Больше значение — сильнее размытие.
Пример:
// Легкое размытие
await sharp('input.jpg')
.blur(2)
.toFile('blurred_light.jpg');
// Сильное размытие
await sharp('input.jpg')
.blur(10)
.toFile('blurred_heavy.jpg');
10. composite() — Наложение одного изображения на другое
Что делает: Позволяет наложить одно или несколько изображений (watermark, логотип) поверх основного. Поддерживает позиционирование и смешивание.
Параметры:
images(array) — массив объектов, каждый из которых содержит:input(string|Buffer) — путь к накладываемому изображению или буфер.top(number) — отступ сверху в пикселях.left(number) — отступ слева в пикселях.blend(string) — режим смешивания: 'over' (поверх), 'in', 'out', 'atop', 'xor' и др.gravity(string) — позиция: 'center', 'north', 'south' и т.д. (альтернатива top/left).
Пример:
// Наложение водяного знака в правый нижний угол
await sharp('background.jpg')
.composite([
{
input: 'logo.png',
gravity: 'southeast', // Юго-восток (правый нижний угол)
blend: 'over'
}
])
.toFile('watermarked.jpg');
Реальный практический пример: Создание миниатюр для галереи
Представьте, что у вас есть веб-приложение, где пользователи загружают фотографии. Вам нужно создать три версии каждого изображения: оригинал (