Кэш растрового изображения в DrawingVisual имеет размытые части
Недавно я перешел на DrawingVisuals
повысить производительность наших трендовых графиков (особенно масштабирование и панорамирование).
Вот код, который у меня есть:
blocksToBeRendered = (baseItem as AvgCurve).GetStreamGeometryBlocks(ActualWidth, ActualHeight, _minPoint.X, _maxPoint.X, FixTimeStep ? _timeStep : 0, IsMainChart);
Pen stroke = new Pen((baseItem as AvgCurve).LineBrush, 1);
foreach (GeometryGroup group in blocksToBeRendered)
{
if (group.Children.Count != 0)
{
if (!cachedBlocks[baseItem].Any(x => x.Children[0] == group.Children[0]))
{
cachedBlocks[baseItem].Add(group);
ImprovedDrawingVisual vis = new ImprovedDrawingVisual();
BitmapCache cache = new BitmapCache() { SnapsToDevicePixels = true };
vis.CacheMode = cache;
using (DrawingContext context = vis.RenderOpen())
{
RenderOptions.SetEdgeMode(group, EdgeMode.Aliased);
if (group.Children.Count > 0)
{
context.DrawGeometry(null, stroke, group.Children[0]);
}
}
_host.VisualCollection.Add(vis);
}
}
}
Это ImprovedDrawingVisual
:
public class ImprovedDrawingVisual: DrawingVisual
{
public ImprovedDrawingVisual()
{
VisualEdgeMode = EdgeMode.Aliased;
VisualBitmapScalingMode = BitmapScalingMode.NearestNeighbor;
}
}
Теперь геометрия имеет Transforms
, что может быть важно.
Что происходит, так это то, что графики хорошо рисуются без кеширования растровых изображений (строки размером 1 пиксель), но когда я включаю кеширование растровых изображений, части графика иногда становятся размытыми.
Кто-нибудь знает, как я могу это исправить? Я пытался изменить RenderAtScale
из DrawingVisual
или отключив EdgeMode
настройка, но это не помогает.
РЕДАКТИРОВАТЬ: опустить геометрию заливки кисти, чтобы избежать путаницы, так как это не имеет значения здесь.
1 ответ
Если вы решили попробовать GDI+
в wpf
тогда рисунок будет выглядеть так:
using GDI = System.Drawing;
private int _counter; // count redraws
protected override void OnRender(DrawingContext context)
{
if (Figures != null && RenderSize.Height > 0 && RenderSize.Width > 0)
using (var bitmap = new GDI.Bitmap((int)RenderSize.Width, (int)RenderSize.Height))
{
using (var graphics = GDI.Graphics.FromImage(bitmap))
foreach (var figure in Figures)
figure.Render(this, graphics);
// draw image
var hbitmap = bitmap.GetHbitmap();
var size = bitmap.Width * bitmap.Height * 4;
GC.AddMemoryPressure(size);
var image = Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
image.Freeze();
context.DrawImage(image, new Rect(RenderSize));
DeleteObject(hbitmap);
GC.RemoveMemoryPressure(size);
// trigger garbage collecting
if (_counter++ > 10)
GC.Collect(3);
}
}
Это в основном делает Graph
на месте (не отложено wpf
рендеринг, ну только блинтинг финал image
). Ты звонишь InvalidateVisual()
перерисовать график. уведомление GC
штуки, они должны (особенно периодическая сборка мусора, если граф часто перерисовывается).
В моем коде Figures
список невизуальных объектов (простые классы, также реализующие рендеринг GDI) И у вас есть визуальные дети. Это проблема, которую я оставляю вам для решения. Благо очень высокая производительность.