oxyplot / oxyplot-avalonia

A cross-platform plotting library for .NET. This package targets Avalonia apps.
https://oxyplot.github.io/
MIT License
274 stars 47 forks source link

`PngExporter.Resolution` is ignored #44

Closed colejohnson66 closed 2 years ago

colejohnson66 commented 2 years ago

I am attempting to export a chart to a PNG for inclusion in a PDF, so I need a resolution of 300+ dpi, not 96. My attempt to do so is this:

using (MemoryStream stream = new())
{
    OxyPlot.Avalonia.PngExporter exporter = new();
    exporter.Background = OxyColor.FromRgb(52, 58, 63);
    exporter.Width *= 2;
    exporter.Height *= 2;
    exporter.Resolution *= 2; // not 300; just for proof of issue
    exporter.Export(Chart, stream);
    File.WriteAllBytes("chart.png", stream.GetBuffer());
}

My issue is that the saved PNG file is 1400x800, but the actual rendering of the chart is 700x400 and shoved in the top-left corner.

Some digging seems to suggest this is related to Skia as the documentation for Avalonia.Media.Imaging.IBitmap.Dpi says:

Note that Skia does not currently support reading the DPI of an image so this value will always be 96dpi on Skia.

@VisualMelon suggests that this is actually a problem in Avalonia's implementation of the render code, specifically:

I probably won't get around to fixing it today, but line 121 of PngExporter looks wrong (should use the canvas size, not the unscaled Width/Height)

VisualMelon commented 2 years ago

On closer inspection, I think the issue is just that we are not setting the resolution of the final bitmap. Line 121 of PngParser should be

var bmp = new RenderTargetBitmap(new PixelSize(Width, Height), new Vector(Resolution, Resolution));
colejohnson66 commented 2 years ago

Yes, that fixed it! I made a PR to fix the issue: oxyplot/oxyplot-avalonia#45