arklumpus/VectSharp

Save as PNG is a bit blurry

Closed this issue · 4 comments

I generate a SVG file and a PNG file of the same Page. If I open the SVG it in the browser more or less at the same resolution of the PNG, the browser's displayed image is a lot more clear than the PNG (that looks more blurry). Is there any way to mitigate or remove that?

Also, I have to say that even the documentation is quite good, I didn't find any references on how to set the background color for the resulting image so I was getting images with transparent background. Even if it is really easy to set it (page.Background = Colours.White), I didn't see it mentioned anywhere in the documentation and I think it will be a nice addition.

Thank you for this amazing library. The more I use it the more I like it.

Hi, I'm glad you like the library!

You're right, the Page.Background property was never mentioned anywhere... I have now included it in the "first plot" tutorial.

For the image issue, I'm not sure why the PNG would look different than an SVG at the same resolution... Do you have display DPI scaling enabled, maybe? This would explain why the SVG is rendered at a higher resolution.

I tried the following: I created a VectSharp page and rendered it as a 100x100 PNG file (testPNG.png) and as an SVG file (testSVG.svg). I then opened the SVG file in Inkscape and exported it to a 100x100 PNG from there (testSVGtoPNG.png), just for reference. I then created the following HTML document and opened it in Chrome:

<html>
    <body>
        <img src="testPNG.png" style="width: 100px; height: 100px">
        <img src="testSVG.svg" style="width: 100px; height: 100px">
        <img src="testSVGtoPNG.png" style="width: 100px; height: 100px">
    </body>
</html>

On a display without scaling, the images look identical:

While on a display with 200% DPI scaling, the SVG looks better than the others (as expected, since it gets rendered at a higher resolution):

The only advice I can give in this case would be to render the PNG image at a higher resolution (you can do so by increasing the scale parameter of the SaveAsPNG/SaveAsImage methods). For example, when testPNG.png is created with scale: 2, the first two images look the same even at the higher DPI levels (the third image is the unchanged 100x100 testSVGtoPNG.png):

If this is not the problem (e.g., because you are not using DPI scaling), would you be able to post a screenshot showing the issue?

Thank you for your ultra-fast response and the detail level of it!

I think I don't have DPI scaling
image

This is the setup I'm using to test it mimicking yours:

<html>
    <body>
        <img src="graficos.png" style="width: 633px; height: 416px">
        <img src="graficos.svg" style="width: 633px; height: 416px">
        <br />
        <img src="graficos.svg" style="width: 633px; height: 416px">
        <img src="graficosIllus.png" style="width: 633px; height: 416px">
    </body>
</html>

What I have noticed is that the browser matters. I was using Brave and the results are:
sidebyside_brave

where you can see some noticeable differences between the graphs, specially in the text.

With Edge I've got this that seems to be similar:
sidebyside_edge

The different font for the "graficosIllus.png" file is because Adobe Illustrator gave me this error when opening the SVG file:
image

Here are the source images:
src_images.zip

So, after the results I've got from Edge, the question will be more oriented to make the candles look less blurry.
I have to say that I have difficulties to generate a plot with the desired pixel dimensions. Maybe if I could calculate the number of candles I'm going to plot and generate it of the proper pixel dimensions (f.e. 4 pixels per candle), there won't be aliasing artifacts for the candles and the candles will look less blurry, but I'm not sure. Can you shed some light about it?

Yes, I think the differences you are seeing here are differences in how different programs handle sub-pixel text aliasing. It would definitely be less noticeable with larger text (maybe you could have fewer labels, but make them bigger), but ultimately I don't think it's something you can "solve"... An option would be to first render the page at a higher resolution, and then downscale it - but I don't think it will change much:

Page page = ...

double upscaling = 4;

DisposableIntPtr renderedImageBytes = pag.SaveAsRawBytes(out int width, out int height, out _, upscaling);
using RasterImage scaledRendering = new RasterImage(ref renderedImageBytes, width, height, true, true);

Page scaledPage = new Page(page.Width, page.Height);
scaledPage.Graphics.Scale(1 / upscaling, 1 / upscaling);
scaledPage.Graphics.DrawRasterImage(0, 0, scaledRendering);

pag.SaveAsPNG("testPNG_scaled.png");

The error you get from Illustrator is because it apparently doesn't support embedded subsetted fonts in SVG documents (I haven't yet found an SVG editor that supports this, actually, even though it works fine with viewers). To solve that, you can try using a different value for the textOption parameter of the SaveAsSVG method.

If you want to make sure that the plot elements are not blurry when rendered at a specific resolution, then you will indeed need to make sure that everything aligns to the pixel boundaries. Don't forget to take into account line thickness when you do this - e.g., if you want a sharp 1px vertical line, you will need to draw it from (5.5, 0) to (5.5, 10), rather than from (5, 0)to(5, 10)`. Also line caps may have an impact.

I can live with those differences of sub-pixel text aliasing.

I'll think If I really need that pixel perfect sharp PNG images...

Thank you very much for your help!