cppfw / svgren

:camera: SVG rendering library in C++
MIT License
206 stars 41 forks source link

Specifying DPI doesn't always work #22

Closed skalleAnka closed 7 years ago

skalleAnka commented 7 years ago

Hi again :)

I am trying to specify another DPI than 96 (tried 960 for all these example files) to svgren::render, but the resulting image seems to become the same anyways. I use parameters 0 for width and height. Here is a test file (the same snake picture I have submitted before) test.zip

Here is another file that behaves differently: The size of the image changes with DPI change, but the actual rendering is in the upper left corner and still the same size. test2.zip

I do have some files on which the DPI change seems to work, such as this: test3.zip

igagis commented 7 years ago

Hi :)

Well, I had a look at your sample files and all seems right. The DPI only has effect when there are any lengthes given in physical units like millimeters, or centimeters, or inches. Then DPI (dots per inch) says how to convert those to pixels. As for your samples:

test1: height and width of the outermost \ element are given in pixels, so, DPI has no effect.

test2: height and width of the outermost \ element are given in millimeters, so DPI affects the size of the image canvas. But all other coordinates are given in pixels, so the shapes are of the same size.

test3: height and width of the outermost \ element are given in millimeters and there is a viewBox! The viewBox causes all the content of the \ to be scaled so that the viewBox itself matches the dimensions of the image canvas, so all the contents of the \ are also scaled, no matter that their coordinates are also given in pixels.

So, all seems correct. If you still think something is wrong, then let me know, otherwise, please close the bug.

skalleAnka commented 7 years ago

I have to admit, I was under the impression that the px unit means one pixel when rendered at 96dpi. If it doesn't, there doesn't seem to be a way at all to scale images where units are specified in px. And still Chrome and Inkscape seem to be able to scale such images.

Is there another way to render such SVGs at scale with svgren?

igagis commented 7 years ago

There is a way for that. Check the docs for svgren::render() function: https://github.com/igagis/svgren/blob/master/src/svgren/render.hpp#L16

In short, if you set width parameter of render() to the width you need, and leave the height zero, then it will scale the whole image to that width and adjust the height to preserve aspect ratio.

Let me know if you still don't know how to solve your task.

skalleAnka commented 7 years ago

Yes, this works for scaling the images to 960 dpi: auto dom = svgdom::load(ist); unsigned int w = static_cast<unsigned int>(dom->width.toPx(960.0f)), h = 0; auto img = svgren::render(*dom, w, h, 96.0f);

Thank you so much again :)

igagis commented 7 years ago

If you bind to DPI of the display, I would recommend you to fix all your SVGs to be same as your test3.svg, i.e. dimensions to be in mm and define a viewBox. And then just render the image at DPI you need, like render(... bla bla... , 960);

skalleAnka commented 7 years ago

Thank you for your advice, I will certainly look into it!