WPF Blurriness - SnapsToDevicePixels
WPF Blurriness - SnapsToDevicePixels
I am upgrading my code from the version 3 to version 3 in WPF. One of the main issues I've run into is that the shapes and text are pretty blurry.
I know that this is how WPF renders, but by setting SnapToDevicePixels to true it should fix the blurriness. I set it to True on the TChart itself, but it seems to have no effect on the shapes that TChart draws. Is there another property I need to set through TChart, and if not, then can it be fixed so that if I do set it to true it draws all the shapes and text with that property on.
Thanks,
T-Mac
I know that this is how WPF renders, but by setting SnapToDevicePixels to true it should fix the blurriness. I set it to True on the TChart itself, but it seems to have no effect on the shapes that TChart draws. Is there another property I need to set through TChart, and if not, then can it be fixed so that if I do set it to true it draws all the shapes and text with that property on.
Thanks,
T-Mac
-
- Site Admin
- Posts: 14730
- Joined: Mon Jun 09, 2003 4:00 am
- Location: Banyoles, Catalonia
- Contact:
Hi T-Mac,
Could you send us an image of what you see as the problem? We can then try experimenting with SnapToDevicePixels in the source to see if that makes any difference.
You can either post your files at news://www.steema.net/steema.public.attachments newsgroup or at our upload page.
Thanks in advance.
Could you send us an image of what you see as the problem? We can then try experimenting with SnapToDevicePixels in the source to see if that makes any difference.
You can either post your files at news://www.steema.net/steema.public.attachments newsgroup or at our upload page.
Thanks in advance.
Best Regards,
Narcís Calvet / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
I posted the file as BlurryChart.zip. The difference can be seen mainly around the candlesticks. The WinForms version has very distinct edges while the WPF version is pretty blurry on the edges.
I was also able to reproduce this effect in a test project by drawing two WPF rectangles on a black background. Turn SnapsToDevicePixels to true for one of them, and you can clearly see the difference between them.
Thanks,
T-Mac
I was also able to reproduce this effect in a test project by drawing two WPF rectangles on a black background. Turn SnapsToDevicePixels to true for one of them, and you can clearly see the difference between them.
Thanks,
T-Mac
-
- Site Admin
- Posts: 1349
- Joined: Thu Jan 01, 1970 12:00 am
- Location: Riudellots de la Selva, Catalonia
- Contact:
T-Mac,
I've created a little UserControl to try and illustrate the issue. Here's the code behind:
And here's the XAML:
With any luck you should easily be able to drop this code into to a default-created UserControl and then drop the UserControl into a standard WPF Application.
Please understand that TChart does not paint objects by adding Shapes to a canvas, as can be seen in InitializeCanvas(). Rather, it draws directly to the DrawingContext, as in the code in the OnRender() overload.
Having said that, try as I might I cannot see a difference between the top two rectangles, both derived from System.Windows.Shapes.Shape, one with SnapsToDevicePixels set to true and the other set to false. Even commenting out the call to SnapsToDevicePixels in InitializeOther(), which sets the property on the UserControl itself and which should make the difference obvious, doesn't seem to make a visible difference to me.
On the other hand, there is a case that the rectangle drawn directly to the DrawingContext is blurrier than the other two. This rendering does not seem affected at all by SnapsToDevicePixels. Reading the following:
http://msdn.microsoft.com/en-us/library ... S.85).aspx (sorry, this link is not parsed correctly by this version of phpBB)
makes things clearer as to what is going on here. As it says in that article "To set guidelines on Drawing and DrawingContext objects, the GuidelineSet class is used." Well, at the moment we do not use the GuidelineSet class in TChart. We will definitely look into doing so, however, for future releases.
An interesting issue. Please let me explain.T-Mac wrote: I was also able to reproduce this effect in a test project by drawing two WPF rectangles on a black background. Turn SnapsToDevicePixels to true for one of them, and you can clearly see the difference between them.
I've created a little UserControl to try and illustrate the issue. Here's the code behind:
Code: Select all
namespace WpfControlLibrary1
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
InitializeCanvas();
InitializeOther();
}
private void InitializeOther()
{
this.SnapsToDevicePixels = true;
}
private void InitializeCanvas()
{
canvas1.Background = new SolidColorBrush(Colors.Black);
Rectangle rect = new Rectangle();
rect.Width = 100;
rect.Height = 100;
rect.SnapsToDevicePixels = false;
rect.Fill = new SolidColorBrush(Colors.Yellow);
rect.Stroke = new SolidColorBrush(Colors.Red);
Canvas.SetLeft(rect, 10);
Canvas.SetTop(rect, 10);
canvas1.Children.Add(rect);
Rectangle rect1 = new Rectangle();
rect1.Width = 100;
rect1.Height = 100;
rect1.SnapsToDevicePixels = true;
rect1.Fill = new SolidColorBrush(Colors.Yellow);
rect1.Stroke = new SolidColorBrush(Colors.Red);
Canvas.SetLeft(rect1, 150);
Canvas.SetTop(rect1, 10);
canvas1.Children.Add(rect1);
}
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawRectangle(new SolidColorBrush(Colors.Black), null, new Rect(RenderSize));
drawingContext.DrawRectangle(new SolidColorBrush(Colors.Yellow), new Pen(new SolidColorBrush(Colors.Red), 1), new Rect(10, 150, 100, 100));
}
}
}
Code: Select all
<UserControl x:Class="WpfControlLibrary1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<Grid>
<Canvas Margin="0,0,0,150" Name="canvas1" />
</Grid>
</UserControl>
Please understand that TChart does not paint objects by adding Shapes to a canvas, as can be seen in InitializeCanvas(). Rather, it draws directly to the DrawingContext, as in the code in the OnRender() overload.
Having said that, try as I might I cannot see a difference between the top two rectangles, both derived from System.Windows.Shapes.Shape, one with SnapsToDevicePixels set to true and the other set to false. Even commenting out the call to SnapsToDevicePixels in InitializeOther(), which sets the property on the UserControl itself and which should make the difference obvious, doesn't seem to make a visible difference to me.
On the other hand, there is a case that the rectangle drawn directly to the DrawingContext is blurrier than the other two. This rendering does not seem affected at all by SnapsToDevicePixels. Reading the following:
http://msdn.microsoft.com/en-us/library ... S.85).aspx (sorry, this link is not parsed correctly by this version of phpBB)
makes things clearer as to what is going on here. As it says in that article "To set guidelines on Drawing and DrawingContext objects, the GuidelineSet class is used." Well, at the moment we do not use the GuidelineSet class in TChart. We will definitely look into doing so, however, for future releases.
Thank you!
Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/
Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/
I was looking into the way that you guys are drawing and think I might have found a solution for it. Here's how I edited your code:
I found that when the rectangles in a specific location it is harder to recreate the blurring. If you allow it to move as you resize the window, it is much easier to see, it also seemed easier when the rectangle is smaller.
If you run the changes I made and resize the window, you will see that sometimes the Rectangle gets a little blurry. Using the Vista Magnifier tool, you can really see the difference between when it is blurry and not blurry, it creates a line of gradient pixels between the black and blue.
Uncommenting the RenderOptions.SetEdgeMode(this, EdgeMode.Aliased) line of code makes it show up perfectly. I went back to my original app and added this line of code to the parent of the TChart and it worked perfectly without any changes in the TChart code.
Let me know if you see any problems with this solution.
Thanks,
T-Mac
Code: Select all
<UserControl x:Class="WpfControlLibrary1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Canvas Name="canvas1" />
</Grid>
</UserControl>
Code: Select all
namespace WpfControlLibrary1
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
protected override void OnRender(DrawingContext drawingContext)
{
// Uncomment this to remove blurriness.
// RenderOptions.SetEdgeMode(this, EdgeMode.Aliased);
drawingContext.DrawRectangle(new SolidColorBrush(Colors.Black), null, new Rect(RenderSize));
drawingContext.DrawRectangle(new SolidColorBrush(Colors.LightBlue), null, new Rect(RenderSize.Width / 2, RenderSize.Height / 2, 10, 50));
}
}
}
If you run the changes I made and resize the window, you will see that sometimes the Rectangle gets a little blurry. Using the Vista Magnifier tool, you can really see the difference between when it is blurry and not blurry, it creates a line of gradient pixels between the black and blue.
Uncommenting the RenderOptions.SetEdgeMode(this, EdgeMode.Aliased) line of code makes it show up perfectly. I went back to my original app and added this line of code to the parent of the TChart and it worked perfectly without any changes in the TChart code.
Let me know if you see any problems with this solution.
Thanks,
T-Mac
-
- Site Admin
- Posts: 1349
- Joined: Thu Jan 01, 1970 12:00 am
- Location: Riudellots de la Selva, Catalonia
- Contact:
T-Mac,
Thank you for putting some of your time in to looking into this problem for us. Your input is most appreciated!
As it happens, I had also run into this solution while searching for information on this issue and had given it a quick run. Again, I could see no visible difference and so rather dismissed it in the hope that the GuidelineSet class would give better results! When I have a little more time to look into this issue more thoroughly then I will evaluate these two options in more detail.
Most certainly not. If the solution works for you, then that's great!T-Mac wrote: Uncommenting the RenderOptions.SetEdgeMode(this, EdgeMode.Aliased) line of code makes it show up perfectly. I went back to my original app and added this line of code to the parent of the TChart and it worked perfectly without any changes in the TChart code.
Let me know if you see any problems with this solution.
Thank you for putting some of your time in to looking into this problem for us. Your input is most appreciated!
As it happens, I had also run into this solution while searching for information on this issue and had given it a quick run. Again, I could see no visible difference and so rather dismissed it in the hope that the GuidelineSet class would give better results! When I have a little more time to look into this issue more thoroughly then I will evaluate these two options in more detail.
Thank you!
Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/
Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/
-
- Site Admin
- Posts: 1349
- Joined: Thu Jan 01, 1970 12:00 am
- Location: Riudellots de la Selva, Catalonia
- Contact:
T-Mac
I'm now running with the following code:
As the code is, I get the following:
1. top left rectangle
2. top right rectangle
3. bottom left rectangle
Changing the EdgeMode to Aliased, I get:
1. bottom left rectangle
From this test I summize:
1. Setting SnapsToDevicePixels in the way I have done doesn't make any difference to the outcome.
2. Setting EdgeMode to Aliased is an improvement, but still does not draw as sharply as the System.Windows.Shapes.Rectangle does.
Do you get similar results on your machine? I wonder if the video card has a bearing on what is rendered here.
Anyhow, at least on my machine, I think I'll have to look at the other option, the use of the GuidelineSet class, to get optimal results. This is a shame, as the use of this class seems somewhat more complicated than a one-liner
Just a quick update, FYI.Chris wrote:When I have a little more time to look into this issue more thoroughly then I will evaluate these two options in more detail.
I'm now running with the following code:
Code: Select all
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
InitializeCanvas();
}
private void InitializeCanvas()
{
this.SnapsToDevicePixels = false;
canvas1.Background = new SolidColorBrush(Colors.Black);
Rectangle rect = new Rectangle();
rect.Width = 25;
rect.Height = 25;
rect.SnapsToDevicePixels = false;
rect.Fill = new SolidColorBrush(Colors.Yellow);
rect.Stroke = new SolidColorBrush(Colors.Red);
Canvas.SetLeft(rect, 10);
Canvas.SetTop(rect, 10);
canvas1.Children.Add(rect);
Rectangle rect1 = new Rectangle();
rect1.Width = 25;
rect1.Height = 25;
rect1.SnapsToDevicePixels = true;
rect1.Fill = new SolidColorBrush(Colors.Yellow);
rect1.Stroke = new SolidColorBrush(Colors.Red);
Canvas.SetLeft(rect1, 150);
Canvas.SetTop(rect1, 10);
canvas1.Children.Add(rect1);
}
protected override void OnRender(DrawingContext drawingContext)
{
RenderOptions.SetEdgeMode(this, EdgeMode.Unspecified);
drawingContext.DrawRectangle(new SolidColorBrush(Colors.Black), null, new Rect(RenderSize));
drawingContext.DrawRectangle(new SolidColorBrush(Colors.Yellow), new Pen(new SolidColorBrush(Colors.Red), 1), new Rect(10, 150, 25, 25));
}
1. top left rectangle
2. top right rectangle
3. bottom left rectangle
Changing the EdgeMode to Aliased, I get:
1. bottom left rectangle
From this test I summize:
1. Setting SnapsToDevicePixels in the way I have done doesn't make any difference to the outcome.
2. Setting EdgeMode to Aliased is an improvement, but still does not draw as sharply as the System.Windows.Shapes.Rectangle does.
Do you get similar results on your machine? I wonder if the video card has a bearing on what is rendered here.
Anyhow, at least on my machine, I think I'll have to look at the other option, the use of the GuidelineSet class, to get optimal results. This is a shame, as the use of this class seems somewhat more complicated than a one-liner
Thank you!
Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/
Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/
-
- Site Admin
- Posts: 1349
- Joined: Thu Jan 01, 1970 12:00 am
- Location: Riudellots de la Selva, Catalonia
- Contact:
T-Mac,
gives me the following for the bottom left rectangle:
That seems to be exactly the same as what the System.Windows.Shapes.Rectangle gives me. So, I'll try and incorporate this as an option into the WPF chart. A reasonable amount of work to get it up and running for all TChart drawing primitives. Shame really
Changing the OnRender() overload to this:Chris wrote: Anyhow, at least on my machine, I think I'll have to look at the other option, the use of the GuidelineSet class, to get optimal results. This is a shame, as the use of this class seems somewhat more complicated than a one-liner
Code: Select all
protected override void OnRender(DrawingContext drawingContext)
{
RenderOptions.SetEdgeMode(this, EdgeMode.Unspecified);
drawingContext.DrawRectangle(new SolidColorBrush(Colors.Black), null, new Rect(RenderSize));
double halfPenWidth = 1.0 / 2.0;
Rect rect = new Rect(10, 150, 25, 25);
GuidelineSet guidelines = new GuidelineSet();
guidelines.GuidelinesX.Add(rect.Left + halfPenWidth);
guidelines.GuidelinesX.Add(rect.Right + halfPenWidth);
guidelines.GuidelinesY.Add(rect.Top + halfPenWidth);
guidelines.GuidelinesY.Add(rect.Bottom + halfPenWidth);
drawingContext.PushGuidelineSet(guidelines);
drawingContext.DrawRectangle(new SolidColorBrush(Colors.Yellow), new Pen(new SolidColorBrush(Colors.Red), halfPenWidth * 2), rect);
drawingContext.Pop();
}
That seems to be exactly the same as what the System.Windows.Shapes.Rectangle gives me. So, I'll try and incorporate this as an option into the WPF chart. A reasonable amount of work to get it up and running for all TChart drawing primitives. Shame really
Thank you!
Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/
Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/
That looks pretty good with the GuideLines. I can't create the blurriness on my machine with the EdgeMode set to Aliased, but I have a ridiculously powerful video card on this machine. That might make the difference.
Could you let me know when the GuideLines option becomes available....
Thanks!
T-Mac
Could you let me know when the GuideLines option becomes available....
Thanks!
T-Mac
-
- Site Admin
- Posts: 1349
- Joined: Thu Jan 01, 1970 12:00 am
- Location: Riudellots de la Selva, Catalonia
- Contact:
T-Mac,
This new feature has now been implemented and will become available in the next maintenance release, due out at the beginning of week 51. You will be able to activate guidelines with the following line of code:T-Mac wrote: Could you let me know when the GuideLines option becomes available....
Code: Select all
tChart1.Aspect.UseGuidelines = true;
Thank you!
Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/
Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/