GDI + Как изменить режим сглаживания линии?

Можно ли изменить PowerPacks.LineShape smoothingMode?

Я пробовал использовать этот код (класс, наследующий 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

У меня всегда один и тот же результат, например: //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

видимо режим сглаживания не принимается во внимание ...


person serhio    schedule 17.02.2010    source источник
comment
Вы хотите сказать, что линия не сглаживается? Независимо от настройки?   -  person Finglas    schedule 25.02.2010


Ответы (4)


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

http://www.ccswe.com/temp/SmoothingMode_AntiAlias.png http://www.ccswe.com/temp/SmoothingMode_None.png

Обновление. Как указал Морбо, если объект Graphics, представленный вам в PaintEventArgs, не является тем же объектом Graphics, который в конечном итоге будет использоваться для отображения, то изменение сглаживания может не иметь никакого эффекта. Хотя я бы не ожидал такой резкой разницы, если бы это был объект Graphics из памяти Image или что-то в этом роде.

Хотел бы я предложить больше. Может быть, если бы я лучше понимал, что LineShape давал вам и ваши аргументы в пользу его использования, вместо использования одного из методов Graphics.DrawLine ().

Причина, по которой я сомневаюсь в том, что вы используете LineShape, заключается в том, что вы переопределяете его OnPaint и рисуете свою собственную линию. Похоже, вы могли бы упростить свое приложение и отказаться от LineShape, но, возможно, я что-то упускаю.


Обновление: Хорошо, тогда понятно, почему вы используете LineShape. Единственное предложение, которое я могу предложить на этом этапе, - это переопределить OnPaint на вашей панели или LineShape, попробуйте установить там режим сглаживания перед вызовом базового события. Что-то вроде:

protected override void OnPaint(PaintEventArgs e)
{
    e.Graphichs.SmoothingMode = SmoothingMode.AntiAlias;
    base.OnPaint(e);
}
person Cory Charlton    schedule 26.02.2010
comment
спасибо, Кори. Однако я рисую не простые линии, а переопределяю PowerPacks.LineShape OnPaint, возможно, это повлияет. Редактировать. Прочтите комментарий Морбо. Постараюсь сменить родителя. - person serhio; 27.02.2010
comment
Наконец, я не понимаю, какое изменение режима сглаживания оказывает какое-либо влияние на рисование линии, когда я переопределяю OnPaint и вообще не использую логику base.OnPaint для моей пользовательской линии. - person serhio; 27.02.2010
comment
@serhio: Не уверен, что понимаю. Вы хотите сказать, что если раскомментировать MyBase.OnPaint(e), SmoothingMode работает? - person Cory Charlton; 27.02.2010
comment
SmoothingMode никогда не работает. Я не могу бросить LineShape. Он выполняет HitTest (клики), MouseOver и логику перерисовки. - person serhio; 01.03.2010
comment
Спасибо, Кори. Ваш код во втором обновлении почти такой же, как и в моем примере. Я отключил MyBase.OnPaint (e), но не вижу разницы между представлением строк с AntiAlias ​​или без него для этих LineShapes. - person serhio; 01.03.2010
comment
@serhio: В вашем примере, кого вы отменяете, OnPaint? LineShape или Panel? (Я даже не знаю, что у LineShape есть OnPaint) Может быть, если вы попробуете это переключить? Хватаюсь за соломинку, потому что у меня нет хорошего ответа :-) - person Cory Charlton; 01.03.2010
comment
LineShape - это компонент графического интерфейса, поэтому у него есть OnPaint. в моем коде я наследую LineShape, поэтому я переопределяю OnPaint LineShape. - person serhio; 01.03.2010
comment
@serhio: Вы пробовали наследовать ShapeContainer и заменять его OnPaint вместо отдельных LineShape s? Еще один выстрел в темноте ... - person Cory Charlton; 01.03.2010

Насколько я могу судить в Reflector, компонент PowerPack LineShape рисует с использованием объекта Graphics из исходного события Paint контейнера. Изменение свойств предоставленного вам объекта Graphics может повлиять на все остальное в контейнере, который рисует после вашей формы.

Какие объекты LineShape содержатся в вашем примере? (Если это настраиваемый элемент управления, создаете ли вы в какой-то момент растровое изображение? Как?) Если они находятся внутри настраиваемого элемента управления с низкой глубиной цвета, это может быть источником проблемы. LineShape по умолчанию рисует сглаживание на моем компьютере.

person Travis    schedule 26.02.2010
comment
+1: Для того, чтобы покопаться под капотом, чтобы узнать, что на самом деле делает PowerPack LineShape. - person Cory Charlton; 26.02.2010
comment
Я рисую lineShapes на настраиваемой панели. Как изменить свойства рисования этой панели? Как видите, я переопределяю OnPaint, поэтому e.Graphics - это не родительская графика, которой передаются? Также, как Вы можете видеть из моего кода, я не использую base.OnPaint - person serhio; 27.02.2010
comment
Кажется, я нашел проблему, см. Здесь: stackoverflow.com/questions/2370738/ - person serhio; 03.03.2010

Какие у вас настройки дисплея? Хотя бы 24 битный цвет?

Я могу подтвердить, что создание класса из LineShape и переопределение OnPaint, как вы показали, действительно действительно влияют на рендеринг линии, как и ожидалось. Я также могу подтвердить, что и Power Pack 3.0, и версия в Visual Studio 2010 специально используют AntiAlias ​​в методе LineShape.DrawInternal.

Я начал с пустого приложения Windows Forms .NET 2.0. Я добавил следующий класс, который почти идентичен вашему, и форму, которая содержит только 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, линия станет сглаженной (гладкой).

Так что это определенно должно сработать. Я знаю, что это кажется глупым вопросом, но проверяли ли вы, что ваш код попадает в отладчик? Вы пробовали вызывать Graphics.Flush () сразу после DrawLine?

Кроме того, какую версию PowerPack вы используете? Как я уже сказал, я довольно ясно вижу в Reflector, что LineShape.DrawInternal специально устанавливает SmoothingMode на AntiAlias ​​в блоке try / finally. Перед возвратом он восстанавливает старый режим сглаживания. Но в вашем примере вы никогда не должны даже нажимать это, потому что вы не вызываете базовый метод.

person Josh    schedule 03.03.2010
comment
Пользуюсь последней версией PowerPack - 3.0. Сделал тест еще и на другом специально созданном новом проекте ... AntiAlias ​​работает там работает ... что-то странное. - person serhio; 03.03.2010
comment
Кажется, я нашел проблему, см. Здесь: stackoverflow.com/questions/2370738/ - person serhio; 03.03.2010
comment
Ах, да, до Vista удаленный рабочий стол ограничен 16-битным цветом. Это сделало бы это. - person Josh; 03.03.2010