C# 如何使用ImageSharp调整中心大小和裁剪图像

C# 如何使用ImageSharp调整中心大小和裁剪图像,c#,imagesharp,C#,Imagesharp,我需要转换一些基于System.Drawing的代码以使用此.NET Core兼容库: 下面的基于System.Drawing的代码调整图像大小并裁剪边缘,返回要保存的内存流。使用ImageSharp库可以实现这一点吗 private static Stream Resize(Stream inStream, int newWidth, int newHeight) { var img = Image.Load(inStream); if (newWidth != img.Wi

我需要转换一些基于System.Drawing的代码以使用此.NET Core兼容库:

下面的基于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;
        }
    }
}
private静态流大小调整(流内流、int-newWidth、int-newHeight)
{
var img=图像负载(流内);
if(newWidth!=img.Width | | newHeight!=img.Height)
{
var ratioX=(双)新宽度/img.Width;
变量比率=(双)新高度/模型高度;
var比率=数学最大值(ratioX,ratioY);
变量宽度=(int)(img.宽度*比率);
变量高度=(整数)(img.高度*比率);
var newImage=新位图(宽度、高度);
Graphics.FromImage(newImage).DrawImage(img,0,0,宽度,高度);
img=新图像;
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=作物(img、新宽度、新高度、起始点、起始点);
}
}
var ms=新内存流();
img.Save(ms,ImageFormat.Jpeg);
ms.Position=0;
返回ms;
}
私有静态图像裁剪(图像图像,int-newWidth,int-newHeight,int-startX=0,int-startY=0)
{
如果(image.Height
使用(var inStream=…)
使用(var outStream=new MemoryStream())
使用(var image=image.Load(流内、流外IImageFormat格式))
{
图像,变异(
i=>i.Resize(宽度、高度)
.Crop(新矩形(x,y,cropWidth,cropHeight));
保存(扩展、格式化);
}
编辑 如果要保持原始图像不变,可以使用
Clone
方法

使用(var inStream=…)
使用(var outStream=new MemoryStream())
使用(var image=image.Load(流内、流外IImageFormat格式))
{
var clone=image.clone(
i=>i.Resize(宽度、高度)
.Crop(新矩形(x,y,cropWidth,cropHeight));
clone.Save(扩展、格式化);
}

您甚至可以通过重载将其优化为单个方法调用,该重载接受带有`ResizeMode.Crop的
ResizeOptions
实例。这将允许您将大小调整为某个比率,然后裁剪掉该比率以外的任何多余部分。

因此,在转换为不使用原始方法后,下面是相关代码:

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
}

事实上,我已经找到了一个可能有用的示例,也许我可以去掉圆角部分,它将是类似的:太棒了,看起来我可以完全去掉原来的调整大小和裁剪方法。我用它们来保存三种不同的尺寸。每次保存后,我是否需要从“流内”重新加载,或者如果每次裁剪都较小,则不重新加载是否会提高性能?我还想知道ResizeMode.Crop是否会输出与Resize和Crop相同的图像?如果你有一个“给我买杯咖啡”的页面需要支持?我刚刚使用了github页面底部的backers链接(数量很少,但我的网站目前正在赔钱):谢谢!我添加了一个额外的代码示例,说明如何克隆图像并调整大小,使原始图像保持不变。这样,您可以加载一次图像并多次调整大小,而不会降低质量
ResizeMode.Crop
默认情况下应该创建相同的输出,只要作物居中,尽管您可以设置坐标。您好@JamesSouth,为死灵术道歉。除了克隆部分,我使用了或多或少相同的方法从传入图像生成缩略图。但当我将某些jpeg图像调整为缩略图时,它们的一侧会出现扭曲的边框。我逐渐了解到,这与ICC颜色配置文件和jpeg编码器有关,但无法找到(也无法理解)到底是什么导致了这种情况。你见过这个吗?你能提出一个解决方案吗?TIA。编辑以使用克隆。