Работа с изображениями в 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