Работа с изображениями в TypeScript: resize и crop с Sharp и Jimp

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

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

Начать курс

Работа с изображениями в TypeScript: resize и crop

В современной веб-разработке обработка изображений — одна из самых востребованных задач. TypeScript, благодаря строгой типизации и интеграции с Node.js, позволяет создавать надежные и производительные инструменты для изменения размеров (resize) и обрезки (crop) изображений. В этой статье мы рассмотрим две популярные библиотеки: Sharp (серверная обработка) и Jimp (чистый JavaScript), а также нативный подход с использованием Canvas API для браузера.

1. Установка и настройка TypeScript проекта

Для начала создайте проект и установите необходимые зависимости:

npm init -y
npm install typescript @types/node sharp jimp
npx tsc --init

В файле tsconfig.json убедитесь, что "module": "commonjs" и "target": "ES2020".

2. Библиотека Sharp — быстрая серверная обработка

Sharp использует нативный модуль libvips и обеспечивает высокую производительность. Подходит для серверных приложений (NestJS, Express).

2.1. Изменение размера (resize) с Sharp

Метод resize() принимает ширину и высоту. Можно указать только один параметр — второй будет вычислен пропорционально.

import sharp from 'sharp';

async function resizeImage(inputPath: string, outputPath: string, width: number, height?: number): Promise<void> {
  try {
    await sharp(inputPath)
      .resize(width, height, {
        fit: 'cover',       // 'cover', 'contain', 'fill', 'inside', 'outside'
        position: 'center'  // позиция для обрезки при cover
      })
      .toFile(outputPath);
    console.log(`Изображение изменено: ${outputPath}`);
  } catch (error) {
    console.error('Ошибка resize:', error);
  }
}

// Пример использования
resizeImage('input.jpg', 'output_800x600.jpg', 800, 600);

2.2. Обрезка (crop) с Sharp

Метод extract() позволяет вырезать прямоугольную область. Параметры: left, top, width, height.

async function cropImage(
  inputPath: string,
  outputPath: string,
  left: number,
  top: number,
  cropWidth: number,
  cropHeight: number
): Promise<void> {
  try {
    await sharp(inputPath)
      .extract({ left, top, width: cropWidth, height: cropHeight })
      .toFile(outputPath);
    console.log(`Обрезка выполнена: ${outputPath}`);
  } catch (error) {
    console.error('Ошибка crop:', error);
  }
}

// Пример: вырезать центр 400x400 из изображения 800x600
cropImage('input.jpg', 'cropped_center.jpg', 200, 100, 400, 400);

2.3. Комбинирование resize и crop

Sharp позволяет объединять операции в цепочку. Например, сначала уменьшить, потом обрезать:

async function resizeAndCrop(inputPath: string, outputPath: string): Promise<void> {
  await sharp(inputPath)
    .resize(500, 500, { fit: 'inside' })  // уменьшаем до 500x500 без обрезки
    .extract({ left: 50, top: 50, width: 400, height: 400 }) // обрезаем центр
    .toFile(outputPath);
}

resizeAndCrop('input.jpg', 'processed.jpg');

3. Библиотека Jimp — чистый JavaScript без нативных зависимостей

Jimp работает на чистом JavaScript, не требует установки дополнительных системных библиотек. Идеален для изолированных сред (например, AWS Lambda).

3.1. Установка Jimp

npm install jimp
npm install @types/jimp  // для TypeScript

3.2. resize с Jimp

import Jimp from 'jimp';

async function resizeWithJimp(inputPath: string, outputPath: string, width: number, height: number): Promise<void> {
  try {
    const image = await Jimp.read(inputPath);
    image.resize(width, height, Jimp.RESIZE_BILINEAR); // алгоритмы: BILINEAR, BICUBIC, NEAREST_NEIGHBOR
    await image.writeAsync(outputPath);
    console.log('Resize Jimp завершен');
  } catch (error) {
    console.error('Ошибка Jimp resize:', error);
  }
}

resizeWithJimp('input.jpg', 'jimp_resized.jpg', 300, 200);

3.3. crop с Jimp

async function cropWithJimp(
  inputPath: string,
  outputPath: string,
  x: number,
  y: number,
  w: number,
  h: number
): Promise<void> {
  try {
    const image = await Jimp.read(inputPath);
    image.crop(x, y, w, h);
    await image.writeAsync(output                    

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