GDI+如何更改线条平滑模式?

发布于 2024-08-21 16:17:04 字数 1575 浏览 5 评论 0原文

是否可以更改 PowerPacks.LineShape 平滑模式?

我尝试使用此代码(继承 LineShape 的类):

  Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    Dim g As Graphics = e.Graphics   

    ' no difference when changing the SmoothingMode ' 
    g.SmoothingMode = SmoothingMode.AntiAlias 

    Using pen As New Pen(Color.Blue, 3)
      g.DrawLine(pen, X1, Y1, X2, Y2)
    End Using

    ' MyBase.OnPaint(e) '
  End Sub

我总是得到相同的结果,如下所示: 替代文本 http://lh6.ggpht.com/_1TPOP7DzY1E/ S3v1IbxlbCI/AAAAAAAADD4/q1Y9kP8wJ0g/s800/Capture2.png

=======

编辑

更新了测试:

  Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    Dim g As Graphics = e.Graphics

    Dim oldmode As SmoothingMode = g.SmoothingMode

    Using pen As New Pen(Color.Blue, 3)
      g.SmoothingMode = SmoothingMode.AntiAlias
      g.DrawLine(pen, X1, Y1, X2, Y2)
      g.SmoothingMode = SmoothingMode.None
      g.DrawLine(pen, X1 + 50, Y1, X2 + 50, Y2)
    End Using

    g.SmoothingMode = oldmode
    g.Flush()

    'MyBase.OnPaint(e)'
  End Sub

结果(不考虑标签和圆圈):

替代文本 http://lh3.ggpht。 com/_1TPOP7DzY1E/S447qYvTqzI/AAAAAAAADE8/eP3kCLqQJbk/s800/Capture2.png

显然没有考虑平滑模式...

Is it possible to change PowerPacks.LineShape smoothingMode?

I tried to use this code(a class that inherits LineShape):

  Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    Dim g As Graphics = e.Graphics   

    ' no difference when changing the SmoothingMode ' 
    g.SmoothingMode = SmoothingMode.AntiAlias 

    Using pen As New Pen(Color.Blue, 3)
      g.DrawLine(pen, X1, Y1, X2, Y2)
    End Using

    ' MyBase.OnPaint(e) '
  End Sub

I always have the same result, like this:
alt text http://lh6.ggpht.com/_1TPOP7DzY1E/S3v1IbxlbCI/AAAAAAAADD4/q1Y9kP8wJ0g/s800/Capture2.png

=======

EDIT

updated the test:

  Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    Dim g As Graphics = e.Graphics

    Dim oldmode As SmoothingMode = g.SmoothingMode

    Using pen As New Pen(Color.Blue, 3)
      g.SmoothingMode = SmoothingMode.AntiAlias
      g.DrawLine(pen, X1, Y1, X2, Y2)
      g.SmoothingMode = SmoothingMode.None
      g.DrawLine(pen, X1 + 50, Y1, X2 + 50, Y2)
    End Using

    g.SmoothingMode = oldmode
    g.Flush()

    'MyBase.OnPaint(e)'
  End Sub

Result (don't take in consideration labels and circles):

alt text http://lh3.ggpht.com/_1TPOP7DzY1E/S447qYvTqzI/AAAAAAAADE8/eP3kCLqQJbk/s800/Capture2.png

apparently smoothing mode is not taken inconsideration...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

画离情绘悲伤 2024-08-28 16:17:04

SmoothingMode 肯定会影响您的输出

以下是我最近用于以最小质量损失调整图像大小的一些设置:

graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

InterpolationMode 可能与您的示例无关,但 PixelOffsetMode 可能与您的示例相关。让我启动一个快速测试应用程序。

更新:这是快速测试应用程序,SmoothingMode 肯定会影响我绘制的线条。

private void Form1_Load(object sender, EventArgs e)
{
    foreach (var value in Enum.GetValues(typeof(SmoothingMode)))
    {
        _ComboBoxSmoothingMode.Items.Add(value);
    }

    foreach (var value in Enum.GetValues(typeof(PixelOffsetMode)))
    {
        _ComboBoxPixelOffsetMode.Items.Add(value);
    }

    _ComboBoxPixelOffsetMode.SelectedIndex = 0;
    _ComboBoxSmoothingMode.SelectedIndex = 0;
}

private void _ButtonDraw_Click(object sender, EventArgs e)
{
    using (Graphics g = _LabelDrawing.CreateGraphics())
    {
        g.Clear(Color.White);

        if (_ComboBoxPixelOffsetMode.SelectedItem != null && (PixelOffsetMode)_ComboBoxPixelOffsetMode.SelectedItem != PixelOffsetMode.Invalid)
        {
            g.PixelOffsetMode = (PixelOffsetMode)_ComboBoxPixelOffsetMode.SelectedItem;
        }

        if (_ComboBoxSmoothingMode.SelectedItem != null && (SmoothingMode)_ComboBoxSmoothingMode.SelectedItem != SmoothingMode.Invalid)
        {
            g.SmoothingMode = (SmoothingMode)_ComboBoxSmoothingMode.SelectedItem;
        }

        using (Pen pen = new Pen(Color.Blue, 3))
        {
            g.DrawLines(pen, new[] { new Point(0, 0), new Point(25, 50), new Point(_LabelDrawing.Width - 25, _LabelDrawing.Height - 50), new Point(_LabelDrawing.Width, _LabelDrawing.Height), });
        }
    }
}

<强>

SmoothingMode: AntiAlias                             None

SmoothingMode.AntiAlias http://www.ccswe.com/temp/SmoothingMode_AntiAlias.png
SmoothingMode.None http://www.ccswe.com/temp/SmoothingMode_None.png

更新: 正如 Morbo 指出的,如果 PaintEventArgs 中呈现给您的 Graphics 对象与 Graphics 不同最终将用于显示的对象,然后更改平滑可能不会产生任何效果。尽管如果这是来自内存Image或其他东西的Graphics对象,我不会期望有如此巨大的差异。

希望我能提供更多。也许如果我更好地理解 LineShape 为您提供的内容以及您使用它的理由,而不是仅使用 Graphics.DrawLine() 方法之一。

我质疑您使用 LineShape 的原因是您重写了它的 OnPaint 并绘制了自己的线条。似乎您可以简化您的应用程序并放弃 LineShape 但也许我错过了一些东西。


更新: 好吧,这就是为什么您使用 LineShape 的原因了。此时我能提供的唯一建议是覆盖面板或 LineShape 中的 OnPaint,在调用基本事件之前尝试在那里设置平滑模式。像这样的东西:

protected override void OnPaint(PaintEventArgs e)
{
    e.Graphichs.SmoothingMode = SmoothingMode.AntiAlias;
    base.OnPaint(e);
}

The SmoothingMode should definitely impact your output

Here's some settings I recently used for resizing an image with minimal quality loss:

graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

The InterpolationMode is probably not relevant for your example but the PixelOffsetMode might be. Let me spin up a quick test app.

Update: Here's the quick test app, SmoothingMode definitely impacts the lines I draw.

private void Form1_Load(object sender, EventArgs e)
{
    foreach (var value in Enum.GetValues(typeof(SmoothingMode)))
    {
        _ComboBoxSmoothingMode.Items.Add(value);
    }

    foreach (var value in Enum.GetValues(typeof(PixelOffsetMode)))
    {
        _ComboBoxPixelOffsetMode.Items.Add(value);
    }

    _ComboBoxPixelOffsetMode.SelectedIndex = 0;
    _ComboBoxSmoothingMode.SelectedIndex = 0;
}

private void _ButtonDraw_Click(object sender, EventArgs e)
{
    using (Graphics g = _LabelDrawing.CreateGraphics())
    {
        g.Clear(Color.White);

        if (_ComboBoxPixelOffsetMode.SelectedItem != null && (PixelOffsetMode)_ComboBoxPixelOffsetMode.SelectedItem != PixelOffsetMode.Invalid)
        {
            g.PixelOffsetMode = (PixelOffsetMode)_ComboBoxPixelOffsetMode.SelectedItem;
        }

        if (_ComboBoxSmoothingMode.SelectedItem != null && (SmoothingMode)_ComboBoxSmoothingMode.SelectedItem != SmoothingMode.Invalid)
        {
            g.SmoothingMode = (SmoothingMode)_ComboBoxSmoothingMode.SelectedItem;
        }

        using (Pen pen = new Pen(Color.Blue, 3))
        {
            g.DrawLines(pen, new[] { new Point(0, 0), new Point(25, 50), new Point(_LabelDrawing.Width - 25, _LabelDrawing.Height - 50), new Point(_LabelDrawing.Width, _LabelDrawing.Height), });
        }
    }
}

SmoothingMode: AntiAlias                             None

SmoothingMode.AntiAlias http://www.ccswe.com/temp/SmoothingMode_AntiAlias.png
SmoothingMode.None http://www.ccswe.com/temp/SmoothingMode_None.png

Update: As Morbo pointed out if the Graphics object presented to you in the PaintEventArgs isn't the same Graphics object that will ultimately be used for display then changing the smoothing might not have any effect. Although I would not expect such a drastic difference if that was a Graphics object from a memory Image or something.

Wish I could offer more. Maybe if I understood better what the LineShape was giving you and your reasoning for using it over just using one of the Graphics.DrawLine() methods.

The reason I question your use of the LineShape is that you are overriding it's OnPaint and drawing your own line. Seems like you could simplify your application and ditch the LineShape but maybe I'm missing something.


Update: Ok that makes sense why you are using the LineShape then. Only suggestion I can offer at this point is to override OnPaint in your panel or LineShape, try setting the smoothing mode there before calling the base event. Something like:

protected override void OnPaint(PaintEventArgs e)
{
    e.Graphichs.SmoothingMode = SmoothingMode.AntiAlias;
    base.OnPaint(e);
}
最美的太阳 2024-08-28 16:17:04

据我在 Reflector 中所知,PowerPack LineShape 组件使用容器原始 Paint 事件中的 Graphics 对象进行绘制。更改给定的 Graphics 对象的属性可能会影响容器中根据您的形状绘制的所有其他内容。

您的示例中包含哪些 LineShape 对象? (如果它是自定义绘制的控件,您是否会在某个时候创建​​位图?如何?)如果它们位于颜色深度较低的自定义控件内,则可能是问题的根源。 LineShape 在我的机器上默认绘制抗锯齿效果。

From what I can tell in Reflector, the PowerPack LineShape component paints using the Graphics object from the container's original Paint event. Changing properties on the Graphics object you're given could affect everything else in the container that paints after your shape.

What are your LineShape objects contained within in your sample? (If it's a custom-painted control, do you create a Bitmap at some point? How?) If they're inside of a custom control with a low color depth, that could be the source of the problem. LineShape draws antialiased by default on my machine.

み零 2024-08-28 16:17:04

您的显示设置是什么?至少 24 位颜色?

我可以确认,从 LineShape 派生一个类并重写 OnPaint (如您所展示的)确实会按预期影响线条渲染。我还可以确认 Power Pack 3.0 和 Visual Studio 2010 中的版本都专门在 LineShape.DrawInternal 方法中使用 AntiAlias。

我从一个空白的 .NET 2.0 Windows 窗体应用程序开始。我添加了以下与您的几乎相同的类和一个仅包含 ShapeContainer 和对角线 MyLine 形状的表单。

Imports Microsoft.VisualBasic.PowerPacks

Public Class MyLine
    Inherits LineShape

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

        Dim g As Graphics = e.Graphics

        'g.SmoothingMode = SmoothingMode.AntiAlias '

        Using pen As New Pen(Color.Blue, 3)
            g.DrawLine(pen, X1, Y1, X2, Y2)
        End Using

        'MyBase.OnPaint(e) '

    End Sub

End Class

如果我按原样使用上述代码运行项目,则该行会出现别名(锯齿状)。如果我取消注释 SmoothingMode 设置,线条将变得抗锯齿(平滑)。

所以它绝对应该有效。我知道这似乎是一个愚蠢的问题,但是您是否检查过以确保您的代码在调试器中被命中?您是否尝试过在 DrawLine 之后立即调用 Graphics.Flush() ?

另外,您使用的是哪个版本的 PowerPack?就像我说的,我可以在 Reflector 中清楚地看到 LineShape.DrawInternal 在 try/finally 块中专门将 SmoothingMode 设置为 AntiAlias。它在返回之前恢复旧的平滑模式。但在您的示例中,您甚至不应该点击此按钮,因为您没有调用基本方法。

What are your display settings set to? At least 24 bit color?

I can confirm that deriving a class from LineShape and overriding OnPaint like you showed does in fact affect the line rendering as expected. I also can confirm that both Power Pack 3.0 and the version in Visual Studio 2010 both specifically use AntiAlias in the LineShape.DrawInternal method.

I started with a blank .NET 2.0 Windows Forms app. I added the following class which is nearly identical to yours and a form which only contains the ShapeContainer and a diagonal MyLine shape.

Imports Microsoft.VisualBasic.PowerPacks

Public Class MyLine
    Inherits LineShape

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

        Dim g As Graphics = e.Graphics

        'g.SmoothingMode = SmoothingMode.AntiAlias '

        Using pen As New Pen(Color.Blue, 3)
            g.DrawLine(pen, X1, Y1, X2, Y2)
        End Using

        'MyBase.OnPaint(e) '

    End Sub

End Class

If I run the project with the above code as-is, the line is aliased (jagged). If I uncomment the SmoothingMode setting, the line becomes antialiased (smooth).

So it definitely should work. I know it seems like a dumb question but have you checked to make sure your code is getting hit in the debugger? Have you tried calling Graphics.Flush() immediately after your DrawLine?

Also, which version of the PowerPack are you using? Like I said I can see quite clearly in Reflector that LineShape.DrawInternal specifically sets the SmoothingMode to AntiAlias in a try/finally block. It restores the old smoothing mode before returning. But in your example you should never even hit this because you're not calling the base method.

毁我热情 2024-08-28 16:17:04

问题出在我的开发模式中:通过虚拟 PC 上的远程桌面连接。

在我的例子中,RDC 没有考虑 AntiAlias 图形属性。

更多详细信息:您在虚拟 PC 上进行开发时遇到过问题吗?< /a>

感谢大家的参与,抱歉,这并不是一个真正的 .NET 问题。

The question was in my development mode: via Remote Desktop Connection on a virtual PC.

The RDC does not take in consideration in my case the AntiAlias graphics property.

more details: Have you had problems developing on a Virtual PC?

Thanks everybody for participating, sorry that is wasn't a really .NET problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文