如何在c#中使图像更平滑

问题描述 投票:0回答:1

代码打开图像使其流通,但是我想要的是使他的角落尽可能平滑而没有非常粗糙的边缘

the image i want

the image i has getting

img具有60x60注意:忽略蓝色边框

尝试切换平滑模式但没有成功

我到目前为止在该项目中做了什么

 private void Recorte_Click(object sender, EventArgs e)
    {
        OpenFileDialog open = new OpenFileDialog();
        // Filter for image files
        open.Filter = "Image Files(*.jpg; *.jpeg; *.gif; *.bmp; *.png)|*.jpg; *.jpeg; *.gif; *.bmp; *.png";
        if (open.ShowDialog() == DialogResult.OK)
        {
            // display image in picture box 
            PointF p = new PointF(1, 1);
            Bitmap org = new Bitmap(open.FileName);
            Image srcImage = Bitmap.FromFile(open.FileName);
            // Resize image in 60x60
            Image resized = ResizeImage(srcImage, new Size(60, 60), false);
            MemoryStream memStream = new MemoryStream();
            // Crop in round shape
            Image cropped = CropToCircle(resized,Color.Transparent);
            cropped.Save(@"..\..\Cortada.png", System.Drawing.Imaging.ImageFormat.Png);
            pictureBox1.Image = cropped;
        }
    }
    public static Image CropToCircle(Image srcImage, Color backGround)
    {
        Image dstImage = new Bitmap(srcImage.Width, srcImage.Height, srcImage.PixelFormat);
        Graphics g = Graphics.FromImage(dstImage);
        using (Brush br = new SolidBrush(backGround))
        {
            g.FillRectangle(br, 0, 0, dstImage.Width, dstImage.Height);
        }
        float radius = 25;
        PointF center = new Point(60, 60);
        GraphicsPath path = new GraphicsPath();
        path.AddEllipse(7, 7, radius * 2, radius * 2);
        g.SetClip(path);
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.InterpolationMode = InterpolationMode.HighQualityBilinear;
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.DrawImage(srcImage, 0, 0);

        return dstImage;
    }

    public static Image ResizeImage(Image image, Size size, bool preserveAspectRatio = true)
    {
        int newWidth;
        int newHeight;
        if (preserveAspectRatio)
        {
            int originalWidth = image.Width;
            int originalHeight = image.Height;
            float percentWidth = (float)size.Width / (float)originalWidth;
            float percentHeight = (float)size.Height / (float)originalHeight;
            float percent = percentHeight < percentWidth ? percentHeight : percentWidth;
            newWidth = (int)(originalWidth * percent);
            newHeight = (int)(originalHeight * percent);
        }
        else
        {
            newWidth = size.Width;
            newHeight = size.Height;
        }
        Image newImage = new Bitmap(newWidth, newHeight);
        using (Graphics graphicsHandle = Graphics.FromImage(newImage))
        {
            graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight);
        }
        return newImage;
    }
c# image smoothing
1个回答
0
投票

要使此功能按预期工作,需要进行一些更改:

  • 处置创建的一次性对象非常重要,尤其是在处理图形对象时,但是您需要处置所有创建的具有Dispose()方法的对象(其中包括OpenFileDialog对象)。

  • 请勿以这种形式使用路径:@"..\..\Image.png":将可执行文件移动到其他位置时,该路径将不存在(否则将无法访问,或者根本就是错误的)。始终使用Path.Combine()(如下所示)构建完整路径。此处的示例将Image保存在可执行路径的CroppedImages子文件夹中。不过,该主题的内容非常广泛(例如,可能不允许您将数据存储在可执行路径中,因此您可能需要在User AppData文件夹中使用专用路径)。

  • 不使用Image.Fromfile():如果出于某些原因必须使用,请始终使用允许保留嵌入的色彩管理信息的重载(string, bool)。由于可以避免这种情况,请使用此处显示的方法,使用File.ReadAllBytes()MemoryStream(或FileStream块中的using)。

  • Graphics.SetClip()不允许抗锯齿,因为构建区域(至少不是直接构建)。在这里,我使用的是TextureBrush,它是从位图(您调整大小后的位图)生成的特殊笔刷,然后将其用于填充调整大小后的图像crops的椭圆。

  • 所有计算都需要重新访问,看看我在这里发布的内容。

private void Recorte_Click(object sender, EventArgs e)
{
    using (var ofd = new OpenFileDialog()) {
        ofd.Filter = "Image Files (*.jpg; *.jpeg; *.gif; *.bmp; *.png)|*.jpg; *.jpeg; *.gif; *.bmp; *.png";
        ofd.RestoreDirectory = true;
        if (ofd.ShowDialog() != DialogResult.OK) return;

        Image croppedImage = null;
        using (var sourceImage = Image.FromStream(new MemoryStream(File.ReadAllBytes(ofd.FileName)))) 
        using (var resizedImage = ResizeImage(sourceImage, new Size(100, 300), false)) {
            croppedImage = CropToCircle(resizedImage, Color.Transparent, Color.Turquoise);
            pictureBox1.Image?.Dispose();
            pictureBox1.Image = croppedImage;
            string destinationPath = Path.Combine(Application.StartupPath, @"CroppedImages\Cortada.png");
            croppedImage.Save(destinationPath, ImageFormat.Png);
        }
    }
}

CropToCircle方法被重写,并且我添加了允许指定笔颜色的重载。然后将使用钢笔在裁剪的椭圆区域周围绘制边框。

public static Image CropToCircle(Image srcImage, Color backColor)
{
    return CropToCircle(srcImage, backColor, Color.Transparent);
}

public static Image CropToCircle(Image srcImage, Color backColor, Color penColor)
{
    var rect = new Rectangle(1, 1, srcImage.Width - 1, srcImage.Height - 1);
    var cropped = new Bitmap(srcImage.Width, srcImage.Height, PixelFormat.Format32bppArgb);
    using (var tBrush = new TextureBrush(srcImage))
    using (var pen = new Pen(penColor, 2))
    using (var g = Graphics.FromImage(cropped)) {
        g.SmoothingMode = SmoothingMode.AntiAlias;
        if (backColor != Color.Transparent) g.Clear(backColor);
        g.FillEllipse(tBrush, rect);
        if (penColor != Color.Transparent) {
            rect.Inflate(-2, -2);
            g.DrawEllipse(pen, rect);
        }
        return cropped;
    }

}

ResizeImage方法得到简化。

  • 缩放比例,当使用时,采用指定的新大小的最大值,并调整图像的大小以适合此大小边界。
  • 图形PixelOffsetMode设置为PixelOffsetMode.HalfThe notes here explain why

public static Image ResizeImage(Image image, Size newSize, bool preserveAspectRatio = true)
{
    float scale = Math.Max(newSize.Width, newSize.Height) / (float)Math.Max(image.Width, image.Height);
    Size imageSize = preserveAspectRatio 
                   ? Size.Round(new SizeF(image.Width * scale, image.Height * scale)) 
                   : newSize;

    var resizedImage = new Bitmap(imageSize.Width, imageSize.Height);
    using (var g = Graphics.FromImage(resizedImage)) {
        g.PixelOffsetMode = PixelOffsetMode.Half;
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(image, 0, 0, imageSize.Width, imageSize.Height);
    }
    return resizedImage;
}
© www.soinside.com 2019 - 2024. All rights reserved.