Работа с изображениями на C#: изменение размера и обрезка (resize, crop)
В современной веб-разработке и desktop-приложениях часто требуется программно обрабатывать изображения: уменьшать их для ускорения загрузки, создавать миниатюры или обрезать лишние края. В экосистеме .NET существует несколько подходов для решения этих задач. В этой статье мы рассмотрим два основных способа изменения размера (resize) и обрезки (crop) изображений на C#: классический System.Drawing и современный кроссплатформенный SixLabors.ImageSharp.
1. Использование System.Drawing (Windows Forms / .NET Framework)
Классический способ, доступный в .NET Framework и .NET Core/5+ (с ограничениями на Linux/macOS). Работает через пространство имен System.Drawing и класс Bitmap. Подходит для старых проектов или Windows-only приложений.
Пример: изменение размера с сохранением пропорций
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
public static Bitmap ResizeImage(Image image, int newWidth, int newHeight)
{
var destRect = new Rectangle(0, 0, newWidth, newHeight);
var destImage = new Bitmap(newWidth, newHeight);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
// Использование:
using (var original = Image.FromFile("input.jpg"))
{
using (var resized = ResizeImage(original, 800, 600))
{
resized.Save("output.jpg", ImageFormat.Jpeg);
}
}
Пример: обрезка (crop) изображения
public static Bitmap CropImage(Image source, Rectangle cropArea)
{
var bmp = new Bitmap(cropArea.Width, cropArea.Height);
using (var g = Graphics.FromImage(bmp))
{
g.DrawImage(source, new Rectangle(0, 0, bmp.Width, bmp.Height),
cropArea, GraphicsUnit.Pixel);
}
return bmp;
}
// Использование:
var cropRect = new Rectangle(100, 50, 300, 200); // X, Y, Width, Height
using (var cropped = CropImage(Image.FromFile("input.jpg"), cropRect))
{
cropped.Save("cropped.jpg", ImageFormat.Jpeg);
}
2. Шестилабораторный ImageSharp (кроссплатформенный .NET)
SixLabors.ImageSharp — это современная, полностью управляемая библиотека для обработки изображений, работающая на .NET Core, .NET 5/6/7+ и .NET Framework. Она не зависит от Windows API, поэтому идеально подходит для веб-приложений (ASP.NET Core), консольных утилит и Docker-контейнеров.
Установка через NuGet:
dotnet add package SixLabors.ImageSharp
Пример: изменение размера с сохранением пропорций
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
public static void ResizeImageSharp(string inputPath, string outputPath, int width, int height)
{
using (var image = Image.Load(inputPath))
{
// Режим ResizeMode.Pad — вписывает изображение, добавляя прозрачные/белые поля
// ResizeMode.Crop — обрезает до заданных размеров
// ResizeMode.Max — сохраняет пропорции, вписывая в прямоугольник
image.Mutate(x => x.Resize(width, height, KnownResamplers.Lanczos3));
image.Save(outputPath);
}
}
// Пример с сохранением пропорций (автоматический расчет высоты):
public static void ResizeWithAspectRatio(string inputPath, string outputPath, int newWidth)
{
using (var image = Image.Load(inputPath))
{
float ratio = (float)newWidth / image.Width;
int newHeight = (int)(image.Height * ratio);
image.Mutate(x => x.Resize(newWidth, newHeight));
image.Save(outputPath);
}
}
Пример: обрезка (crop) изображения
public static void CropImageSharp(string inputPath, string outputPath, Rectangle cropRect)
{
using (var image = Image.Load(inputPath))
{
image.Mutate(x => x.Crop(cropRect));
image.Save(outputPath);
}
}
// Альтернатива: обрезка с использованием координат
public static void CropByCoordinates(string inputPath, string outputPath, int x, int y, int width, int height)
{
using (var image = Image.Load(inputPath))
{
image.Mutate(ctx => ctx.Crop(new Rectangle(x, y, width, height)));