如何使用 ImageSharp 调整中心大小和裁剪图像
How to Resize Center and Crop an image with ImageSharp
我需要转换一些基于 System.Drawing 的代码才能使用这个 .NET Core 兼容库:
https://github.com/SixLabors/ImageSharp
下面基于 System.Drawing 的代码调整图像大小和裁剪边缘,返回内存流以进行保存。 ImageSharp 库可以做到这一点吗?
private static Stream Resize(Stream inStream, int newWidth, int newHeight)
{
var img = Image.Load(inStream);
if (newWidth != img.Width || newHeight != img.Height)
{
var ratioX = (double)newWidth / img.Width;
var ratioY = (double)newHeight / img.Height;
var ratio = Math.Max(ratioX, ratioY);
var width = (int)(img.Width * ratio);
var height = (int)(img.Height * ratio);
var newImage = new Bitmap(width, height);
Graphics.FromImage(newImage).DrawImage(img, 0, 0, width, height);
img = newImage;
if (img.Width != newWidth || img.Height != newHeight)
{
var startX = (Math.Max(img.Width, newWidth) - Math.Min(img.Width, newWidth)) / 2;
var startY = (Math.Max(img.Height, newHeight) - Math.Min(img.Height, newHeight)) / 2;
img = Crop(img, newWidth, newHeight, startX, startY);
}
}
var ms = new MemoryStream();
img.Save(ms, ImageFormat.Jpeg);
ms.Position = 0;
return ms;
}
private static Image Crop(Image image, int newWidth, int newHeight, int startX = 0, int startY = 0)
{
if (image.Height < newHeight)
newHeight = image.Height;
if (image.Width < newWidth)
newWidth = image.Width;
using (var bmp = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb))
{
bmp.SetResolution(72, 72);
using (var g = Graphics.FromImage(bmp))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(image, new Rectangle(0, 0, newWidth, newHeight), startX, startY, newWidth, newHeight, GraphicsUnit.Pixel);
var ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Jpeg);
image.Dispose();
var outimage = Image.FromStream(ms);
return outimage;
}
}
}
是的,超级简单。
using (var inStream = ...)
using (var outStream = new MemoryStream())
using (var image = Image.Load(inStream, out IImageFormat format))
{
image.Mutate(
i => i.Resize(width, height)
.Crop(new Rectangle(x, y, cropWidth, cropHeight)));
image.Save(outStream, format);
}
编辑
如果你想保持原始图像不变,你可以使用 Clone
方法。
using (var inStream = ...)
using (var outStream = new MemoryStream())
using (var image = Image.Load(inStream, out IImageFormat format))
{
var clone = image.Clone(
i => i.Resize(width, height)
.Crop(new Rectangle(x, y, cropWidth, cropHeight)));
clone.Save(outStream, format);
}
您甚至可以通过接受带有 `ResizeMode.Crop 的 ResizeOptions
实例的重载将其优化为对 Resize
的单个方法调用。这将允许您调整到一个比例,然后剪掉超出该比例的任何多余部分。
所以这里是转换为不使用原始方法之后的相关代码:
using (var fullSizeStream = new MemoryStream())
using (var smallStream = new MemoryStream())
using (var thumbStream = new MemoryStream())
using (var reviewThumbStream = new MemoryStream())
using (var image = Image.Load(inStream))
{
// Save original constrained
var clone = image.Clone(context => context
.Resize(new ResizeOptions
{
Mode = ResizeMode.Max,
Size = new Size(1280, 1280)
}));
clone.Save(fullSizeStream, new JpegEncoder { Quality = 80 });
//Save three sizes Cropped:
var jpegEncoder = new JpegEncoder { Quality = 75 };
clone = image.Clone(context => context
.Resize(new ResizeOptions
{
Mode = ResizeMode.Crop,
Size = new Size(277, 277)
}));
clone.Save(smallStream, jpegEncoder);
clone = image.Clone(context => context
.Resize(new ResizeOptions
{
Mode = ResizeMode.Crop,
Size = new Size(100, 100)
}));
clone.Save(thumbStream, jpegEncoder);
clone = image.Clone(context => context
.Resize(new ResizeOptions
{
Mode = ResizeMode.Crop,
Size = new Size(50, 50)
}));
clone.Save(reviewThumbStream, jpegEncoder);
//...then I just save the streams to blob storage
}
我需要转换一些基于 System.Drawing 的代码才能使用这个 .NET Core 兼容库:
https://github.com/SixLabors/ImageSharp
下面基于 System.Drawing 的代码调整图像大小和裁剪边缘,返回内存流以进行保存。 ImageSharp 库可以做到这一点吗?
private static Stream Resize(Stream inStream, int newWidth, int newHeight)
{
var img = Image.Load(inStream);
if (newWidth != img.Width || newHeight != img.Height)
{
var ratioX = (double)newWidth / img.Width;
var ratioY = (double)newHeight / img.Height;
var ratio = Math.Max(ratioX, ratioY);
var width = (int)(img.Width * ratio);
var height = (int)(img.Height * ratio);
var newImage = new Bitmap(width, height);
Graphics.FromImage(newImage).DrawImage(img, 0, 0, width, height);
img = newImage;
if (img.Width != newWidth || img.Height != newHeight)
{
var startX = (Math.Max(img.Width, newWidth) - Math.Min(img.Width, newWidth)) / 2;
var startY = (Math.Max(img.Height, newHeight) - Math.Min(img.Height, newHeight)) / 2;
img = Crop(img, newWidth, newHeight, startX, startY);
}
}
var ms = new MemoryStream();
img.Save(ms, ImageFormat.Jpeg);
ms.Position = 0;
return ms;
}
private static Image Crop(Image image, int newWidth, int newHeight, int startX = 0, int startY = 0)
{
if (image.Height < newHeight)
newHeight = image.Height;
if (image.Width < newWidth)
newWidth = image.Width;
using (var bmp = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb))
{
bmp.SetResolution(72, 72);
using (var g = Graphics.FromImage(bmp))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(image, new Rectangle(0, 0, newWidth, newHeight), startX, startY, newWidth, newHeight, GraphicsUnit.Pixel);
var ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Jpeg);
image.Dispose();
var outimage = Image.FromStream(ms);
return outimage;
}
}
}
是的,超级简单。
using (var inStream = ...)
using (var outStream = new MemoryStream())
using (var image = Image.Load(inStream, out IImageFormat format))
{
image.Mutate(
i => i.Resize(width, height)
.Crop(new Rectangle(x, y, cropWidth, cropHeight)));
image.Save(outStream, format);
}
编辑
如果你想保持原始图像不变,你可以使用 Clone
方法。
using (var inStream = ...)
using (var outStream = new MemoryStream())
using (var image = Image.Load(inStream, out IImageFormat format))
{
var clone = image.Clone(
i => i.Resize(width, height)
.Crop(new Rectangle(x, y, cropWidth, cropHeight)));
clone.Save(outStream, format);
}
您甚至可以通过接受带有 `ResizeMode.Crop 的 ResizeOptions
实例的重载将其优化为对 Resize
的单个方法调用。这将允许您调整到一个比例,然后剪掉超出该比例的任何多余部分。
所以这里是转换为不使用原始方法之后的相关代码:
using (var fullSizeStream = new MemoryStream())
using (var smallStream = new MemoryStream())
using (var thumbStream = new MemoryStream())
using (var reviewThumbStream = new MemoryStream())
using (var image = Image.Load(inStream))
{
// Save original constrained
var clone = image.Clone(context => context
.Resize(new ResizeOptions
{
Mode = ResizeMode.Max,
Size = new Size(1280, 1280)
}));
clone.Save(fullSizeStream, new JpegEncoder { Quality = 80 });
//Save three sizes Cropped:
var jpegEncoder = new JpegEncoder { Quality = 75 };
clone = image.Clone(context => context
.Resize(new ResizeOptions
{
Mode = ResizeMode.Crop,
Size = new Size(277, 277)
}));
clone.Save(smallStream, jpegEncoder);
clone = image.Clone(context => context
.Resize(new ResizeOptions
{
Mode = ResizeMode.Crop,
Size = new Size(100, 100)
}));
clone.Save(thumbStream, jpegEncoder);
clone = image.Clone(context => context
.Resize(new ResizeOptions
{
Mode = ResizeMode.Crop,
Size = new Size(50, 50)
}));
clone.Save(reviewThumbStream, jpegEncoder);
//...then I just save the streams to blob storage
}