【问题标题】:How to draw smooth images with C#?如何用 C# 绘制平滑的图像?
【发布时间】:2010-10-08 15:37:37
【问题描述】:

我正在尝试在 C# 表单(在 PictureBoxes 中以及使用 Graphics.DrawImage())上绘制图像,并且正在寻找一种方法来绘制它们平滑。图像必须是支持透明度的格式,例如 PNG、GIF、SVG 和 WMF。 C# 不支持开箱即用的 SVG 文件,而且我还没有找到一个好的第三方库可以使用(我找到了 SvgNet,但无法弄清楚)。

我需要绘制一个 WMF 文件,C# 可以通过 Image.FromFile() 函数完成,但它没有消除锯齿。我想知道是否有什么办法可以解决这个问题?

【问题讨论】:

    标签: c# .net winforms picturebox wmf


    【解决方案1】:

    将图像绘制到画布时,您可以将插值模式更改为比最近邻更好的方式,以使调整大小的图像平滑:

    Graphics g = ...
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    g.DrawImage(...);
    

    您需要添加 System.Drawing.Drawing2D 以获取 InterpolationMode 枚举。

    使用 PictureBox 将是一个问题 - 它不会公开 InterpolationMode 属性,因此您需要自己滚动或下载一个。

    【讨论】:

    • 知道在哪里可以找到可下载的,或者如何自己做?我是一名 C# 开发新手,编写自己的 C# 可能有点超出我目前的能力。
    • 作为新手,开始滚动自己的类的最简单方法可能是放置一个 Panel 控件,然后编写它的 Paint 事件(在属性窗口中,选择事件 [闪电图标] 然后双击在列表中的 Paint 事件旁边)。使用 e.Graphics 参数编写替换绘制代码。
    【解决方案2】:

    之前的答案虽然是好的,但只是部分正确。

    什么是正确的? PictureBox 不公开 InterpolationMode。

    什么是离谱的?

    1) 虽然您可以从图片框、其父级或通过派生类中的覆盖轻松地在 Paint 事件中设置该属性。 . .无论哪种方式都有效,两者都一样容易。但是,除非设置 SmoothingMode,否则 InterpolationMode 将被忽略。如果将 SmoothingMode 设置为 SmoothingMode.AnitAlias,您将不会获得任何抗锯齿效果。

    2) 当您明确表示有兴趣使用 PictureBox 的功能时使用面板是错误的方向。您将无法直接加载、保存或分配图像,而无需明确编码这些属性。 . . 为什么要重新发明轮子?通过从 PictureBox 派生,您可以免费获得所有这些。

    消息变得更好,因为我已经为您完成了艰苦的工作,而且我花费的时间比写此消息要少。

    我提供了两个版本,它们都派生自 PictureBox。 First 是一个简单的示例,它始终使用尽可能高质量的渲染。这也是最慢的渲染。 Second 是一个允许任何人通过派生类的属性设置各种渲染参数的类。设置后,这些将在 OnPaint 覆盖中使用。

    public class HighQualitySmoothPictureBox : PictureBox
    {
        protected override void OnPaint(PaintEventArgs pe)
        {
            // This is the only line needed for anti-aliasing to be turned on.
            pe.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    
            // the next two lines of code (not comments) are needed to get the highest 
            // possible quiality of anti-aliasing. Remove them if you want the image to render faster.
            pe.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            pe.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            // this line is needed for .net to draw the contents.
            base.OnPaint(pe);
        }
    }
    

    ...

    public class ConfigurableQualityPictureBox : PictureBox
    {
        // Note: the use of the "?" indicates the value type is "nullable."  
        // If the property is unset, it doesn't have a value, and therefore isn't 
        // used when the OnPaint method executes.
        System.Drawing.Drawing2D.SmoothingMode? smoothingMode;
        System.Drawing.Drawing2D.CompositingQuality? compositingQuality;
        System.Drawing.Drawing2D.InterpolationMode? interpolationMode;
    
        public System.Drawing.Drawing2D.SmoothingMode? SmoothingMode
        {
            get { return smoothingMode; }
            set { smoothingMode = value; }
        }
    
        public System.Drawing.Drawing2D.CompositingQuality? CompositingQuality
        {
            get { return compositingQuality; }
            set { compositingQuality = value; }
        }
    
        public System.Drawing.Drawing2D.InterpolationMode? InterpolationMode
        {
            get { return interpolationMode; }
            set { interpolationMode = value; }
        }
    
        protected override void OnPaint(PaintEventArgs pe)
        {
            if (smoothingMode.HasValue)
                pe.Graphics.SmoothingMode = smoothingMode.Value;
            if (compositingQuality.HasValue)
                pe.Graphics.CompositingQuality = compositingQuality.Value;
            if (interpolationMode.HasValue)
                pe.Graphics.InterpolationMode = interpolationMode.Value;
    
            // this line is needed for .net to draw the contents.
            base.OnPaint(pe);
        }
    }
    

    【讨论】:

    • 一个很好的答案。我唯一要添加的是一些属性,例如 Browsable、ToolboxItem、Description 和 Category,以便能够在 VisualDesigner 中使用此控件。
    • @hichaeretaqua 感谢您的客气话。我同意最终实现将需要这些属性。但是,我发现与答案不直接相关的项目很混乱,并且可能会分散学习者对预期信息的注意力。这就是我没有提供它们的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 2014-10-11
    • 1970-01-01
    • 2021-04-06
    • 2017-01-14
    • 2023-03-11
    • 1970-01-01
    相关资源
    最近更新 更多